Foundry
뉴스 피드 시스템 설계
고급
핵심

변하는 목록에서 다음 장 넘기기

점수가 변하면 커서도 안전하지 않다

첫 화면 20개를 보여준 뒤 사용자가 아래로 내립니다. 다음 20개를 무엇으로 가져올지가 이 절입니다. 시간순 목록이라면 이미 풀린 문제인데, 점수순에서는 그렇지 않습니다.

커서가 안전하다는 말의 조건

점수가 변하는 목록에서는 커서를 써도 중복과 누락이 함께 생긴다 첫 페이지를 보낸 뒤 커서는 점수 4.5 글 A 점수 4.9 반응이 식어 4.2 두 번째 장에 또 나온다 글 B 점수 4.3 반응이 붙어 4.7 어디에도 안 나온다 커서가 안전한 것은 정렬키가 변하지 않을 때다 점수는 변하므로 첫 조회의 순서를 따로 붙들어 둔다 붙들어 두는 방법 첫 조회에서 후보 수백 건의 순서를 정해 저장하고 그 목록을 넘긴다 그 목록은 짧게만 살아 있다. 오래 두면 낡은 피드를 보게 된다

건너뛰기 방식은 목록이 변하면 항목이 밀려서 중복과 누락이 생깁니다. 그래서 보통 커서를 씁니다. 마지막으로 본 값을 들고 가서 그 이후를 읽는 방식입니다.

그런데 커서가 안전한 것은 정렬키가 변하지 않을 때입니다. 작성 시각으로 정렬하면 그 값은 절대 바뀌지 않습니다.

점수는 바뀝니다. 반응이 붙고 시간이 지나면 값이 달라집니다.

커서가 4.5 인 상태에서결과
4.9 였던 글이 4.2 로 내려감두 번째 장에 또 나온다
4.3 이던 글이 4.7 로 올라감어느 장에도 안 나온다

중복과 누락이 동시에 생깁니다. 커서를 썼는데도 건너뛰기 방식의 문제가 그대로 돌아옵니다.

첫 조회의 순서를 붙들어 둔다

해결은 정렬키를 고치는 것이 아니라 목록을 고정하는 것입니다.

첫 조회에서 후보 수백 건의 순서를 정한다
그 순서를 저장하고, 다음 장은 그 목록에서 잘라 준다

이렇게 하면 사용자가 아래로 내리는 동안 순서가 흔들리지 않습니다. 커서는 그 저장된 목록 안의 위치를 가리키므로 안전합니다.

이 방식은 이미 앞 절에서 만든 것을 재사용합니다. 미리 만들어 둔 후보 목록이 곧 붙들어 둘 목록입니다.

붙들어 둔 목록은 짧게만 산다

목록을 오래 두면 낡은 피드를 계속 보게 됩니다. 사용자가 한 시간 뒤에 다시 내리면 한 시간 전 순서가 이어집니다.

목록 수명결과
너무 짧다스크롤 중에 목록이 사라져 순서가 흔들린다
너무 길다새 글이 안 보인다

한 번의 세션 동안 유지될 만큼만 둡니다. 그리고 사용자가 처음으로 다시 올려 새로 고치면 목록을 버리고 다시 만듭니다. 그것이 사용자가 새 순서를 원한다는 신호입니다.

목록이 끝나면 어떻게 하나

붙들어 둔 후보가 수백 건이므로 사용자가 계속 내리면 끝에 닿습니다.

끝에 닿으면 그 시점 기준으로 다음 후보 묶음을 만든다

이때 이미 보여준 것을 제외해야 하는데, 그것이 다음 절의 문제입니다. 목록을 이어 붙일 때마다 이미 본 것과 겹칠 수 있고, 그것은 순서 문제가 아니라 기억의 문제입니다.

면접에서 이렇게 나옵니다

Q.점수순 목록에서 커서 방식을 쓰면 안전합니까

안전하지 않습니다. 커서가 안전한 것은 정렬키가 변하지 않을 때입니다.

커서가 4.5 인 상태에서결과
4.9 였던 글이 4.2 로 내려감두 번째 장에 또 나온다
4.3 이던 글이 4.7 로 올라감어느 장에도 안 나온다

작성 시각은 절대 바뀌지 않지만 점수는 반응과 시간에 따라 바뀝니다. 그래서 중복과 누락이 동시에 생깁니다.

흔한 실수: 커서를 쓰면 목록 변동에 안전하다고 외운 것을 그대로 적용하는 것. 그 말의 전제는 정렬키 불변입니다. 전제가 깨지면 결론도 깨집니다.

Q.그러면 다음 장을 어떻게 가져오시겠습니까

첫 조회에서 순서를 정해 저장하고, 다음 장은 그 목록에서 잘라 줍니다.

첫 조회에서 후보 수백 건의 순서를 정한다
커서는 그 저장된 목록 안의 위치를 가리킨다

정렬키를 고치는 것이 아니라 목록을 고정하는 것입니다. 사용자가 아래로 내리는 동안 순서가 흔들리지 않습니다.

미리 만들어 둔 후보 목록을 그대로 쓰므로 새 저장소가 필요하지 않습니다.

흔한 실수: 점수에 타이브레이커를 붙여 해결하려는 것. 타이브레이커는 같은 점수의 순서를 정할 뿐이고, 점수 자체가 변하는 문제는 그대로 남습니다.

Q.붙들어 둔 목록을 얼마나 오래 두시겠습니까

한 번의 세션 동안 유지될 만큼만 둡니다.

목록 수명결과
너무 짧다스크롤 중에 목록이 사라져 순서가 흔들린다
너무 길다새 글이 안 보인다

그리고 사용자가 위로 올려 새로 고치면 목록을 버리고 다시 만듭니다. 그것이 새 순서를 원한다는 신호입니다.

수명을 정하는 것은 곧 사용자가 같은 순서를 볼 기간을 정하는 것입니다.

흔한 실수: 목록을 사용자별로 하나만 두는 것. 같은 사용자가 두 기기에서 보면 서로의 위치를 흔듭니다. 목록은 조회 단위로 두고 식별자를 클라이언트가 들고 다니게 합니다.

Q.붙들어 둔 목록의 끝에 닿으면 어떻게 하나요

그 시점 기준으로 다음 후보 묶음을 만듭니다.

후보가 수백 건이므로 계속 내리면 끝에 닿습니다. 새로 만들 때는 그때의 점수를 쓰므로 순서가 자연히 갱신됩니다.

문제는 이미 보여준 것이 새 묶음에 다시 들어올 수 있다는 것입니다. 점수가 여전히 높은 글은 새 후보에도 뽑힙니다.

이것은 순서 문제가 아니라 기억의 문제이고, 이미 본 것을 걸러내는 장치가 따로 필요합니다.

흔한 실수: 새 묶음을 만들 때 앞 묶음을 제외 조건으로만 넣는 것. 사용자가 여러 번 내리면 제외 목록이 계속 길어져서 조건 자체가 비싸집니다. 본 것을 따로 기억하는 쪽이 낫습니다.

먼저 스스로 답해보고 아래 답변과 견줘보세요. 막히는 부분은 문제로 확인할 수 있어요.

읽었으면 문제로 확인해보세요

뉴스 피드 시스템 설계 문제를 풀면 틀린 문제가 자동으로 노트에 쌓입니다. 가입 없이 5문제를 먼저 풀어볼 수도 있어요.