뉴스 피드
1. 문제 정의와 요구사항 잡기
뉴스 피드를 구현하기 전에 어떤 사용자 경험을 제공할지, 어느 정도 규모를 감당할지, 무엇을 이번 설계에서 제외할지를 먼저 정리합니다.
가장 먼저 해야 할 일은 서버나 데이터베이스를 고르는 것이 아니라 요구사항을 확정하는 것입니다. 이 예제에서는 사용자가 게시물을 작성하고 친구의 게시물을 시간 역순으로 볼 수 있으며 웹과 모바일을 모두 지원한다고 가정합니다. 이후 사용자 수, 친구 수, 읽기와 쓰기 비율 같은 규모 조건을 정하면 필요한 구조가 자연스럽게 보이기 시작합니다.
2. 전체 아키텍처와 API
뉴스 피드를 쓰는 흐름과 읽는 흐름을 나누고, 클라이언트 요청이 어떤 서버들을 통과하는지 큰 그림을 잡습니다.
전체 시스템은 크게 피드 발행과 피드 생성으로 나누면 이해하기 쉽습니다. 쓰기 경로에서는 게시물 저장과 팬아웃이 핵심이고, 읽기 경로에서는 피드 캐시와 게시물 조립이 핵심입니다. 두 흐름을 분리해서 생각하면 어느 부분이 느린지, 어느 부분을 독립적으로 확장해야 하는지도 쉽게 보입니다.
3. 게시물 발행과 팬아웃
사용자가 게시물 하나를 올린 뒤 데이터가 저장되고 친구들의 피드에 전달되는 과정을 단계별로 살펴봅니다.
먼저 게시물을 안전하게 저장한 뒤 친구들의 뉴스 피드에 반영하는 작업이 시작됩니다. 단순화하면 클라이언트 → 로드 밸런서 → 웹 서버 → 게시물 저장 서비스 → 캐시·데이터베이스 순서로 저장하고, 별도의 팬아웃 서비스가 친구 목록을 기준으로 피드를 갱신합니다. 알림 서비스도 독립시켜 게시물 저장과 알림 전송이 서로 기다리지 않도록 만들 수 있습니다.
4. Fanout-on-Write와 Fanout-on-Read
피드를 미리 만들어 둘지 읽을 때 만들지 비교하고, 왜 실제 대규모 서비스가 혼합 방식을 사용하는지 이해합니다.
두 방식의 핵심 차이는 뉴스 피드를 계산하는 시점입니다. Fanout-on-Write는 쓰기 비용을 늘려 읽기를 빠르게 만들고, Fanout-on-Read는 쓰기를 가볍게 만드는 대신 읽기 비용을 늘립니다. 따라서 어느 방식이 항상 좋은 것이 아니라 서비스의 읽기·쓰기 특성과 사용자 관계 규모에 따라 선택해야 합니다.
5. 뉴스 피드를 읽는 과정과 캐시
사용자가 앱을 열고 뉴스 피드를 요청했을 때 어떤 데이터가 어떤 캐시에서 조립되는지 살펴봅니다.
먼저 뉴스 피드 캐시에서 해당 사용자가 볼 게시물 ID 목록을 가져옵니다. 그 ID를 이용해 게시물 캐시에서 글 내용을, 사용자 캐시에서 작성자 이름과 사진을 가져와 하나의 응답으로 조립합니다. 이미지와 동영상은 CDN URL을 전달해 클라이언트가 별도로 가져오게 하면 애플리케이션 서버의 부담을 줄일 수 있습니다.
6. 데이터베이스와 대규모 확장
데이터가 한 서버를 넘어설 때 필요한 샤딩, 복제, 일관성, 장애 대응 개념을 뉴스 피드에 연결해 이해합니다.
트래픽이 커지면 한 서버의 성능을 계속 높이는 것만으로는 한계가 있으므로 여러 서버로 작업과 데이터를 나누는 수평 확장을 사용합니다. 웹 서버, 캐시, 데이터베이스, 팬아웃 작업 서버를 각각 독립적으로 늘릴 수 있도록 설계하는 것이 중요합니다. 데이터 계층에서는 샤딩과 복제를 함께 사용해 저장 용량과 읽기 처리량, 장애 대응 능력을 높일 수 있습니다.
7. 운영, 장애 상황, 설계 트레이드오프
정상 동작뿐 아니라 트래픽 폭증, 느린 작업, 데이터 지연 같은 현실적인 상황을 어떻게 관찰하고 대응하는지 살펴봅니다.
기능이 동작하는 것만으로는 충분하지 않고 실제 운영 중 발생할 수 있는 병목과 장애를 확인해야 합니다. QPS, 응답시간, 캐시 적중률, 메시지 큐 길이, 팬아웃 처리 지연 같은 지표를 지속적으로 관찰해야 합니다. 시스템 설계의 핵심은 완벽한 구조를 만드는 것이 아니라 어떤 선택이 어떤 장점과 비용을 만드는지 이해하고 문제 발생 시 대응할 수 있게 만드는 것입니다.