팔로우한 작성자·그룹·추천 source를 분리해 후보를 만들고 post ID로 합칩니다.
뉴스 피드 시스템
설계
피드는 단순히 게시물을 모으는 목록이 아닙니다. 누구에게 미리 복사할지, 언제 읽어 합칠지, 무엇을 먼저 숨길지, 랭킹이 멈춰도 무엇을 보여 줄지를 함께 결정하는 개인화 시스템입니다.
일반 작성자의 post는 follower inbox에 미리 후보 ID를 쓰는 fan-out on write로 빠르게 읽습니다. 매우 인기 있는 작성자는 timeline만 기록하고 요청 시 합치는 fan-out on read로 폭발적인 쓰기를 피합니다. 어느 경로든 권한·삭제·차단 필터가 랭킹보다 먼저 작동합니다.
빠른 목록보다 안전한 노출 경계를 먼저 정한다
홈 피드는 작성·팔로우·차단·삭제처럼 서로 다른 정본을 만납니다. inbox의 빠른 후보와 실제 열람 권한을 같은 것으로 취급하지 않습니다.
불투명 cursor와 정렬 snapshot으로 새 post가 들어와도 스크롤 중복을 줄입니다.
삭제·차단·언팔로우·공개 범위 변경은 다음 응답에서 숨길 수 있어야 합니다.
ranker나 feature가 실패해도 정책 필터를 거친 시간순 후보를 제한적으로 보입니다.
post 정본, graph, 후보 inbox, ranker를 분리한다
post 저장과 outbox 기록은 같은 쓰기 경계에서 확정하고, fan-out·색인·랭킹 feature는 재시도 가능한 소비자로 분리합니다. 읽기에서는 hot timeline과 inbox 후보를 합친 뒤 정책을 먼저 확인합니다.
쓰기에는 후보를, 읽기에는 정책과 순위를 둔다
작성 ACK 전에 post 정본과 전파 이벤트가 함께 기록되어 유실 창을 줄입니다.
follower 배치에 post ID를 멱등 upsert해 개인 inbox 후보를 만듭니다.
수백만 inbox write 대신 author timeline 하나를 기록해 읽을 때만 합칩니다.
block, mute, audience, 삭제, tombstone을 ranker 앞에서 제거합니다.
신선도·관계 feature로 정렬하고 세션 안정성을 위한 snapshot cursor를 돌려줍니다.
평균이 아니라 긴 꼬리와 철회 비용을 비교한다
fan-out 전략은 랭킹 여부와 별개입니다. 어떤 전략이든 후보는 중복될 수 있고, 삭제·차단·공개 범위 변경은 최종 노출 전에 확인해야 합니다.
| 선택 | 강점 | 제약 | 적용 판단 |
|---|---|---|---|
| fan-out on write | 개인 inbox 읽기가 빠르고 단순 | 팔로워 수만큼 queue·저장 write가 증가 | 일반 작성자, 높은 읽기 빈도 |
| fan-out on read | post는 한 번 기록, write 폭발 방지 | feed 열기 때 timeline 병합·hydrate 비용 | 매우 큰 follower를 가진 hot 작성자 |
| hybrid | 긴 꼬리 비용을 제한 | 경계, 이행, dedupe, 관측이 복잡 | 팔로워 분포가 크게 치우친 서비스 |
| 시간순 fallback | 설명·복구·디버깅이 쉬움 | 관련성·다양성 최적화가 제한 | ranker 장애, 초기 제품 |
| inbox에 post ID | 삭제·수정·privacy를 정본에서 확인 | read-time hydrate 필요 | 철회 요구가 중요한 피드 |
지연·중복·철회를 측정 가능한 복구 절차로 만든다
새 post가 follower inbox에 늦어져 작성 시각과 노출 시각이 크게 벌어집니다.
한 post가 수백만 inbox write를 만들어 일반 작성자까지 밀어냅니다.
at-least-once 재시도나 이행 구간에서 같은 카드가 두 번 보일 수 있습니다.
feature 지연·모델 오류가 빈 피드나 높은 p99로 이어집니다.
stale inbox와 cache에 삭제·차단된 post가 잠시 남습니다.
팔로우·block 정책을 읽지 못해 노출 판단이 불명확해집니다.
보안·관측·비용을 후보 생성 밖에서 운영한다
cursor를 viewer·정책 버전에 결속하고, 권한 필터를 ranker보다 먼저 둡니다. 관계 그래프·본문·feature는 최소 권한과 보존 기간으로 접근합니다.
fan-out lag, candidate shortage, hot merge, ranker fallback, duplicate, revoke-to-hide를 author·source·policy 차원으로 제한해 관측합니다.
inbox write·복제·TTL, timeline merge, post hydrate, feature read, purge와 고카디널리티 로그가 비용을 만듭니다. hit ratio 하락은 origin read를 급증시킵니다.
공식·1차 출처
- USENIX ATC 2013 — TAO: Facebook’s Distributed Data Store for the Social Graph: 대규모 소셜 그래프 저장·캐시의 1차 연구.
- Meta Engineering — TAO: The power of the graph: TAO의 그래프 계층 개요.
- Apache Kafka — Design: 파티션 순서와 consumer group의 공식 설계 문서.
- 이 페이지의 fan-out 경계, 규모, TTL, 신선도·랭킹 식, 삭제 SLA는 제품 사실이 아닌 학습용 설계 가정입니다.
작성·검토·참고 자료
참고 자료
- Nathan Bronson et al., **TAO: Facebook’s Distributed Data Store for the Social Graph**, USENIX ATC 2013: https://www.usenix.org/conference/atc13/technical-sessions/presentation/bronson
- Meta Engineering, **TAO: The power of the graph**: https://engineering.fb.com/2018/06/08/core-infra/tao/
- Apache Kafka, **Design** — partition order와 consumer group 설계: https://kafka.apache.org/documentation/#design
- Martin Kleppmann, **Making Sense of Stream Processing** (공개 강연/자료와 구분해 일반 설계 참고로만 사용): https://www.oreilly.com/library/view/making-sense-of/9781491974707/
- 이 문서의 규모, hot 경계, TTL, 랭킹 점수, 노출·삭제 SLA는 학습용 설계 가정이다. 실제 도입 전에는 현재 제품 정책, 개인정보·보존 의무, 실험 안전성, 부하·장애 시험으로 검증한다.
사실 오류·출처 정정은 문의·정정 페이지로 알려 주세요.