상세 컨텐츠

본문 제목

[Serendi] 프로젝트 #4 플레이리스트가 유지하는 음악의 인덱스가 바뀌었을 경우

알고리즘, 백엔드/Serendi

by grizzly 2025. 7. 18. 16:31

본문

친구와 프로젝트를 하던 중 구현 로직에 막힌 부분이 있었다.

 

우리가 플레이리스트를 생각해보면 노래의 순서가 굉장히 중요하다. 빵빵 터지는 음악이 계속될 수도, 터지다가 가라 앉을 수도, 가라 앉다가 다시 터지게 노래를 배치할 수 있다. 즉, 노래의 순서는 계속해서 취향에 따라 바뀔 수 있는 부분이다. 그렇다면 이 부분에 대한 로직은 어떻게 작성되어야 할까?

 

1번 - 4번 까지의 노래가 있다는 가정 하에

4번이 1번과 2번 사이의 위치하기 위해 이동시킨다면, 배열이라면 거의 전부가 이동해야한다. 1번 4번 2번 3번 -> 2 3 4가 모두 이동해야하는 비효율적인 코드이다.

 

그렇다면 딕셔너리 형태로 구현한다면 {노래_id: index} 꼴 : [{1 : 1 }, {2 : 2} , {3 : 3}, {4 : 4}] 여기서도 마찬가지로 하나 하나 요소에 접근하는 것은 빠르지만, 전부 다 바꿔야 할 것이다. [{1:1},{4:2},{2:3},{3:4}]

 

뭔가 순서가 바뀔 때마다 계속해서 업데이트가 일어나는 것이 올바른 상황일까?

 

당연하게 순서가 바뀌고 저장되면 업데이트는 일어나야 한다. 하지만 업데이트가 일어날 때마다 너무나 많은 양의 연산이 들어간다. 그러면 이 부분을 어떻게 하면 줄일 수 있을까. 또한 프론트와 백 중에서 어느 부분에서 이 업무를 하는게 맞을까?

 

백이 하게 된다면, 즉각적인 정보 접근이 어렵다. 순서를 한 번, 두 번 바꾸는 것이 아니라 계속 바꾸게 될 것이고, Music_id가 없는 상황에서 index 정보와 결과 만으로 어떤 노래가 살아남게 되었는 지 알기가 어렵다. (이 상황이면 결국 playlist를 통으로 갈아버리고 새로 업데이트를 해야한다)

 

해당 부분에 대한 결과로는

[{Id : 1, index: 2.5}]

1 - 1, 2 - 2, 3 - 3, 4 - 4, 5 - 5, 6 - 6, 7 - 7

만약 5가 1과 2 사이에 들어갔다면?
1 - 1, 5 - 1.5, 2 - 2, 3 - 3, 4 - 4, 6 - 6, 7 - 7

6이 1 과 5 사이에 들어갔다면,

1 - 1, 6 - 1.25, 5 - 1.5, 2 - 2, 3 - 3, 4 - 4, 7 - 7

그러면 프론트 쪽에서 나한테 줄 값 [{id : 6, index : 1.25}, {id : 5, index : 1.5}]

이거 기준으로 인덱스 값을 수정하고 적용해야 함.

지금 기준으로 playlist_music 테이블에서

music_id, playlist_id, index 이렇게 유지중이기 때문에
music_id와 playlist_id를 통해서 먼저 해당 테이블에 접근하고 값을 저장한다.

 

이런 로직을 통해 구현하는 것으로 하였다. 저 index의 변화의 경우 프론트에서 저장을 한 후, 백 쪽으로 결과만 전송하게 된다. 이렇게 하여 playlist_music 테이블의 인덱스 값만 업데이트를 하고 삭제된 노래의 경우 -1의 인덱스를 전송하게 되어 playlist_music 테이블을 삭제하게 된다.

근데 여기서 논의 부분. index 값이 float 값이기 때문에 계속해서 유지하기엔 좀 그럴 수 있음.
그러므로 인덱스 값을 수정해야 할 수 있음. -> 우리가 playlist를 가져올 때 음악을 가져오기 위해선, playlist_id를 통하여 playlist_music 테이블에 접근할 것임.
그러면 음악이 10개라한다면, 10개의 테이블에 접근이 됨. 그러면 10개의 테이블을 계속하여 서로 값을 비교하여 정렬한 후 보내줘야 함.
따라서 이 부분에 대한 정렬이 미리 되어 있어야 함.

 

float값이 계속해서 업데이트 될 경우 1.5 -> 1.25 -> 1.125 ... 등의 기하급수적으로 자릿수가 늘어나게 되며 금방 제한될 수 있다.

따라서 한번 사용한 값은 언젠가 다시 1 , 2 ... 등의 int 값으로 업데이트 해줘야 한다.

 

이 경우 float index의 최소 간격(threshold)을 정한 후 해당 값 보다 작아지게 되면 re-indexing을 시켜줘야 한다. 

추가적으로 유지하는 입장이 아닌 프론트의 호출 입장에선, ORDER BY index 를 통하여 실수 / 정수 상관없이 불러오면 된다.

 

re-indexing의 경우는 playlist_id로 접근하여 전체 노래에 대해서 전부 크기 순으로 index를 새로 할당하면 된다.

 

이런 로직으로 플레이리스트의 노래 인덱스를 관리하게 된다. 

관련글 더보기