사용자가 팔로우하는 사람들의 게시물, 행동(좋아요, 리쉐어 등)을 최신성 + 개인화 기준으로 정렬해 무한 스크롤 피드로 제공한다. 대용량 트래픽에서도 낮은 지연과 높은 가용성을 유지해야 한다.
(score, createdAt, id)
형태의 스코어 + 시간 기반 커서POST /api/v1/posts
GET /api/v1/feed?limit=30&cursor=<opaque>
POST /api/v1/follows { followerId, followeeId }
DELETE /api/v1/follows/{id}
POST /api/v1/posts/{id}/like
커서 기반 페이지네이션: cursor
는 (lastScore,lastId)
를 인코딩한 opaque 토큰
-- 게시물
Post(id PK, author_id, text, media_urls[], created_at, visibility, like_count, comment_count, ...)
-- 팔로우 그래프
Follow(follower_id, followee_id, created_at, PRIMARY KEY(follower_id, followee_id))
-- 타임라인(푸시형 복제 저장)
Timeline(user_id, post_id, score, created_at,
PRIMARY KEY(user_id, score DESC, post_id DESC))
-- score = f(recency, affinity, engagement)
하이브리드 시 셀럽 글은 Timeline에 복제하지 않고 Read 시점 합산한다.
[Client]
|
[API Gateway/Auth]
|
+--+-------------------------------+
| Backend Services |
| PostSvc FollowSvc FeedSvc |
| | | |
| v | |
| [Kafka/PostTopic] |
| | | |
| FanoutWorkers (rank/affinity)|
| | |
| [Timeline Store] <---- [Social Graph DB]
| | |
| [Redis Cache] <---- [Feature Store / CTR]
+--------|-------------------------+
v
[CDN/S3 for media]
feed:{userId}
→ 상위 N개(100~300) ID 리스트post:{id}
(메타), user:{id}
(프로필/친밀도 피처)PostTopic
(새 글), FanoutTopic
(복제 작업), SignalTopic
(좋아요/댓글)(followerId % P)
로 타임라인 순서 유지timeline:{userId}:{postId}
중복 삽입 방지base64(score:lastId)
WHERE (score,id) < (cursorScore,cursorId)
ORDER BY score DESC, id DESC LIMIT K”followers_of(author) > CELEB_THRESHOLD
이면 풀 전략:recent posts by celeb
을 한 번만 읽어 모든 팔로워 피드에 병합뉴스피드 시스템 설계는 단순히 “게시물을 모아 보여주는 것”이 아니라 읽기와 쓰기의 균형을 어떻게 잡을지라는 근본적인 문제를 다루는 작업이었다. 처음에는 단순히 최신 글을 모아서 보여주면 될 것 같았지만 실제로는 fan-out on write
와 fan-out on read
각각의 방식이 가진 장단점을 고려해야 했고 특히 팔로워 수가 많은 셀럽 계정을 처리할 때 쓰기 부하가 폭발적으로 늘어난다는 점에서 현실적인 해법은 결국 하이브리드 전략임을 깨달을 수 있었다.
또한 단순한 시간순 정렬만으로는 좋은 사용자 경험을 줄 수 없다는 것도 중요한 배움이었다. 최신성과 개인화 요인을 동시에 고려해 (score, createdAt, id)
로 정렬하고 온라인에서는 빠른 점수 계산으로 재랭킹을 적용하며 오프라인에서는 CTR이나 참여도를 학습해 품질을 높이는 이원화된 구조는 실시간성과 추천 품질을 동시에 만족시키는 설계 패턴으로 이해할 수 있었다.
운영적인 측면에서도 많은 고민거리가 있었다. 모든 캐시에 강한 일관성을 보장하려 하기보다는 삭제나 차단 같은 민감한 이벤트만 즉시 반영하고 나머지는 최종적 일관성을 허용하는 것이 성능과 사용자 경험을 균형 있게 맞추는 방법이었다. 여기에 큐 기반 아키텍처에서 멱등 키를 사용하고 DLQ·재시도로 장애를 흡수하는 방식은 대규모 분산 시스템에서 안정성을 확보하는 기본기라는 점도 새삼 느꼈다.
결국 뉴스피드 시스템은 데이터 모델링, 랭킹 알고리즘, 캐시 전략, 장애 대응까지 아우르는 종합 설계 과제였고 모든 의사결정의 기준은 “대규모 트래픽 환경에서 비용을 어떻게 통제할 것인가”였다. 동시에 단순히 기술적 효율만이 아니라 사용자가 체감하는 품질이 최종 지표가 되어야 한다는 점을 다시금 확인할 수 있었다.