11. Designing a News Feed System

뉴스 피드 시스템 설계

뉴스 피드 시스템은 소셜 미디어 플랫폼에서 핵심적인 기능 중 하나입니다. 사용자에게 최신 정보와 컨텐츠를 빠르고 효율적으로 제공하는 것이 이 시스템의 주요 목적입니다.

전체 설계도

  • 사용자 단말: 사용자는 웹 브라우저나 모바일 앱을 통해 뉴스 피드를 요청합니다. 이 요청은 v1/me/feed 엔드포인트로 전달되며, 요청에는 콘텐츠와 인증 토큰이 포함됩니다.

  • DNS: 사용자의 요청은 DNS를 통해 웹 서버로 라우팅됩니다.

  • 로드밸런서: 로드밸런서는 들어오는 요청을 여러 웹 서버로 분배하여, 특정 서버에 부하가 집중되지 않도록 합니다.

  • 웹 서버: 웹 서버는 인증을 처리하고, 요청의 유효성을 검증합니다. 이 서버는 요청에 대한 기본적인 처리를 담당하며, 처리량 제한 등의 기능도 포함되어 있습니다.

  • 포스팅 전송 서비스: 이 서비스는 요청한 사용자의 친구 목록을 추출하고, 그 친구들이 작성한 게시물을 사용자에게 전달할 준비를 합니다. 이 과정에서 다음과 같은 하위 단계들이 포함됩니다:

    • ① 친구 ID 목록 추출: 그래프 데이터베이스에서 사용자의 친구 목록을 추출합니다.

    • ② 친구들의 최신 게시물 ID 추출: 친구들의 게시물 정보를 캐시나 데이터베이스에서 가져옵니다.

  • 메시지 큐: 포스팅 전송 서비스에서 처리된 데이터는 메시지 큐에 저장됩니다. 메시지 큐는 비동기적으로 데이터를 처리하여, 포스팅 전송 작업 서버로 전달합니다. 이는 시스템의 성능을 높이고, 병목 현상을 방지하는 데 도움을 줍니다.

  • 포스팅 전송 작업 서버: 메시지 큐에서 받은 데이터를 처리하여 최종적으로 사용자가 볼 수 있는 뉴스 피드를 생성합니다. 이 과정에서 여러 사용자에게 전송될 뉴스 피드를 효율적으로 구성합니다.

  • 포스트 캐시: 포스팅 저장 서비스에서 자주 접근되는 포스트 데이터는 캐시에 저장됩니다. 이를 통해 데이터베이스의 부하를 줄이고, 사용자에게 신속하게 데이터를 제공할 수 있습니다.

  • 사용자 정보 캐시: 사용자 정보와 관련된 데이터도 캐시에서 관리됩니다. 이는 사용자 정보 데이터베이스와 연결되어 있으며, 사용자의 프로필 정보나 관계 데이터를 빠르게 제공할 수 있습니다.

  • 뉴스 피드 캐시: 최종적으로 생성된 뉴스 피드는 뉴스 피드 캐시에 저장됩니다. 이를 통해 사용자가 뉴스 피드를 요청할 때, 빠르게 응답할 수 있습니다.

  • 포스팅 데이터베이스: 모든 게시물 데이터는 이 데이터베이스에 영구 저장됩니다. 캐시에서 데이터를 찾지 못하는 경우, 이 데이터베이스에서 데이터를 가져옵니다.

  • 사용자 정보 데이터베이스: 사용자 프로필, 관계, 설정 등과 관련된 정보는 이 데이터베이스에 저장됩니다.

  • 그래프 데이터베이스: 사용자 간의 관계(팔로우/친구 관계)를 관리하는 특화된 데이터베이스입니다. 이 데이터베이스는 사용자 네트워크를 빠르게 탐색하고, 친구 목록을 추출하는 데 최적화되어 있습니다.

  • 알림 서비스: 뉴스 피드와는 별도로, 사용자가 게시물을 작성하거나 친구의 새 게시물을 확인할 때 알림을 보내는 역할을 합니다. 이는 사용자 참여를 높이는 중요한 서비스 중 하나입니다.

전체적인 흐름

  • 사용자가 뉴스 피드를 요청합니다.

  • 로드밸런서가 요청을 적절한 웹 서버로 전달합니다.

  • 웹 서버가 요청을 처리하고, 포스팅 전송 서비스로 요청을 전달합니다.

  • 포스팅 전송 서비스는 친구 목록과 최신 게시물을 조회하여 메시지 큐로 전달합니다.

  • 포스팅 전송 작업 서버가 메시지 큐의 데이터를 받아 뉴스 피드를 구성합니다.

  • 구성된 뉴스 피드는 뉴스 피드 캐시에 저장되고, 사용자에게 전달됩니다.

요구 사항 분석

뉴스 피드 시스템 설계를 시작하기 전, 시스템이 충족해야 할 주요 요구 사항을 분석해야 합니다. 이를 통해 적절한 아키텍처를 선택하고, 성능을 최적화하며, 유지보수를 용이하게 할 수 있습니다.

  1. 실시간 업데이트: 사용자는 친구나 팔로우하는 사람들의 최신 활동을 실시간으로 확인할 수 있어야 합니다.

  2. 높은 처리량: 대규모 사용자 기반을 대상으로 대량의 데이터가 지속적으로 생성되고 소비되기 때문에, 시스템은 높은 처리량을 처리할 수 있어야 합니다.

  3. 사용자 맞춤화: 사용자의 관심사에 맞춘 컨텐츠를 추천하여 개인화된 피드를 제공해야 합니다.

  4. 지연 최소화: 피드 업데이트와 사용자 응답 간의 지연 시간을 최소화해야 합니다.

  5. 확장성: 사용자 수와 데이터의 증가에 따라 시스템이 확장 가능해야 합니다.

시스템 아키텍처 설계

뉴스 피드 시스템의 설계는 크게 게시(Write) 경로읽기(Read) 경로로 나눌 수 있습니다.

  1. 게시 경로: 사용자가 새로운 포스트를 올리거나 활동을 기록할 때 시스템이 이를 어떻게 처리하고 저장할지 정의합니다.

  2. 읽기 경로: 사용자가 뉴스 피드를 볼 때 어떤 방식으로 데이터를 가져와 사용자에게 제공할지 결정합니다.

게시 경로 설계

뉴스 피드 시스템의 게시 경로에서는 사용자 활동(포스트, 좋아요, 댓글 등)이 발생할 때 이를 효율적으로 처리하고 저장해야 합니다. 일반적으로 다음과 같은 전략을 고려합니다.

  • 큐 기반 처리: 사용자의 게시 요청을 큐(Queue)에 넣어 비동기적으로 처리함으로써 시스템의 부하를 줄일 수 있습니다.

  • 이벤트 소싱(Event Sourcing): 사용자의 모든 활동을 이벤트로 기록하여 나중에 필요한 데이터를 재구성할 수 있도록 합니다.

  • 데이터 파티셔닝: 사용자 데이터를 파티셔닝(Partitioning)하여 여러 데이터베이스에 분산 저장함으로써 확장성을 높입니다.

읽기 경로 설계

읽기 경로 설계는 뉴스 피드 시스템의 핵심입니다. 여기서는 사용자가 피드를 조회할 때 신속하게 결과를 반환하는 데 초점을 맞춥니다.

Hotkey 문제

핫키(Hot Key) 문제는 분산 시스템에서 특정 키에 대한 접근이 지나치게 집중되어 발생하는 성능 문제를 의미합니다. 이 문제는 주로 캐싱 시스템이나 분산 데이터베이스에서 나타납니다.

핫키 문제는 특정 키(데이터 항목)에 대한 요청이 과도하게 몰리는 상황에서 발생합니다. 예를 들어, 소셜 미디어에서 매우 인기 있는 포스트나 트렌드가 되는 해시태그는 수많은 사용자가 동시에 접근하려고 할 수 있습니다. 이러한 상황에서 특정 키에 대한 요청이 급격히 증가하면, 해당 키가 저장된 서버나 캐시 노드에 과부하가 걸리게 됩니다.

핫키 문제의 영향

  • 성능 저하: 특정 서버나 노드에 과부하가 걸리면서 전체 시스템의 응답 속도가 느려집니다.

  • 서버 과부하: 지속적인 요청으로 인해 서버의 CPU, 메모리, 네트워크 자원이 고갈될 수 있습니다.

  • 서비스 불안정: 핫키로 인한 과부하가 지속되면 서비스 장애로 이어질 수 있습니다.

핫키 문제 해결 방안

핫키 문제를 해결하기 위해서는 여러 가지 전략을 사용할 수 있습니다.

  1. 키 분산: 핫키를 여러 키로 분산시켜 부하를 줄이는 방법입니다. 예를 들어, 키를 시간별로 나누거나 사용자를 기준으로 분할할 수 있습니다.

  2. 캐시 확장: 캐시 서버를 확장하여 부하를 여러 노드에 분산합니다. 이를 통해 특정 노드에 집중되는 요청을 줄일 수 있습니다.

  3. 부하 분산: 로드 밸런서를 사용하여 특정 노드에 집중되는 트래픽을 다른 노드로 분산시킵니다.

  4. TTL(Time To Live) 설정: 캐시 항목의 TTL을 짧게 설정하여, 데이터가 자주 갱신되도록 유도합니다. 이를 통해 오래된 핫키가 캐시에서 계속 유지되는 것을 방지할 수 있습니다.

  5. 쓰로틀링(Throttling): 특정 키에 대한 요청이 일정 한도를 초과할 경우, 요청을 제한하는 방법입니다. 이를 통해 서버에 과부하가 걸리는 것을 방지할 수 있습니다.

조회 시 풀(Pull)

사용자가 피드를 조회할 때마다 새로 생성된 컨텐츠를 불러오는 방법입니다. 이 방법은 시스템의 부하를 줄일 수 있지만, 실시간성이 떨어질 수 있습니다.

장점:

  • 뉴스 피드가 실시간으로 갱신됩니다.

  • 뉴스 피드 읽는 시간이 짧습니다.

단점:

  • 친구가 많은 경우 사용자 모두의 뉴스 피드를 갱신하는 데 많은 시간이 소요될 수 있습니다. (핫키 문제)

  • 서비스를 자주 사용하지 않는 사용자의 피드까지 갱신해야해서 컴퓨팅 자원이 낭비됩니다.

게시 시 푸시(Push)

새로운 컨텐츠가 생성될 때 해당 사용자들의 피드에 즉시 푸시하는 방법입니다. 이 방법은 실시간 성능이 우수하지만, 사용자 수가 많아질수록 부담이 커질 수 있습니다.

장점:

  • 비활성화된 사용자가 로그인하기전까지 어떤 컴퓨팅 자원도 소모하지 않습니다.

  • 데이터를 갱신하지 않아도 되어서 핫키 문제가 발생하지 않습니다

단점:

  • 뉴스 피드 읽는 시간이 길어집니다. (UX적으로 가장 큰 문제)

하이브리드 접근

위 두 가지 방식을 결합하여 푸시와 풀 방식을 상황에 따라 조합하여 사용하는 방법입니다.

  • 주요 사용자 또는 이벤트에 대한 푸시: VIP, 인기 게시물 또는 중요한 이벤트에 대해서 푸시 방식을 사용합니다.

  • 일반 사용자에 대한 풀(Pull): 일반 사용자는 뉴스피드를 조회할 때 필요한 데이터를 실시간으로 가져옵니다.

  • 피드 생성 시 혼합 사용: 피드를 생성할 때 최신 게시물은 푸시된 데이터를 사용하고, 그 외에는 Pull 방식으로 가져옵니다.

고려 사항:

  • 데이터 동기화: Push와 Pull 방식 간의 데이터 일관성을 유지해야합니다. CQRS나 이벤트 소싱을 사용할 수 있습니다.

  • 사용자 행동 분석: 어떤 경우에 Pull 또는 Push를 사용할지 행동을 분석합니다.

  • 리소스 관리: 푸시 방식의 사용을 최소화하여 리소스를 절약하는 전략이 필요합니다. (장시간 사용하지 않을때는 푸시를 일시 중지)

이벤트 소싱

**이벤트 소싱(Event Sourcing)**은 시스템에서 발생하는 모든 상태 변경을 이벤트(Event)로 기록하는 아키텍처 패턴입니다. 이 패턴에서는 데이터의 현재 상태를 저장하지 않고, 상태 변경이 발생할 때마다 그 변경 내역(이벤트)을 기록합니다. 이후 이 이벤트들을 순차적으로 재생하여 시스템의 현재 상태를 재구성할 수 있습니다.

CQRS

**CQRS(Command Query Responsibility Segregation)**는 명령(Command)과 조회(Query) 작업을 분리하여 서로 다른 모델로 처리하는 아키텍처 패턴입니다. 즉, 쓰기 작업(명령)과 읽기 작업(조회)을 서로 다른 경로로 처리함으로써, 성능을 최적화하고 확장성을 높일 수 있습니다.

데이터 베이스 설계

뉴스 피드 시스템에서 데이터베이스는 성능과 확장성에 중요한 역할을 합니다. 일반적으로 관계형 데이터베이스와 NoSQL 데이터베이스를 조합하여 사용합니다.

4.1 관계형 데이터베이스

  • 사용자 정보: 사용자 프로필, 팔로우 관계 등 기본적인 데이터를 저장합니다.

  • 포스트 정보: 게시물 ID, 작성자, 작성 시간, 텍스트 등을 저장합니다.

4.2 NoSQL 데이터베이스

NoSQL 데이터베이스는 빠른 조회와 확장성을 위해 사용됩니다.

  • 타임라인 스토리지: 각 사용자의 뉴스 피드를 저장하며, 포스트 ID의 목록을 키로 사용합니다.

  • 분산 처리: 데이터가 여러 서버에 분산되어 저장되므로 대규모 데이터를 처리하는 데 유리합니다.

캐시 구조

캐시 구조 계층 설명(*논리적인 분리입니다. 물리적으로 분리될수도, 아닐수도 있습니다)

  1. 뉴스 피드 캐시:

    • 뉴스 피드: 이 캐시는 사용자가 조회하는 뉴스 피드 자체를 저장합니다. 사용자가 자신의 피드를 요청할 때, 이 캐시에서 데이터를 바로 가져올 수 있어 응답 시간이 매우 빠릅니다.

    • 이 캐시는 사용자가 자주 조회하는 데이터이기 때문에, 가장 상위 계층에 위치하며, 캐시 히트율(캐시에서 데이터를 찾을 확률)이 높은 편입니다.

  2. 콘텐츠 캐시:

    • 인기 콘텐츠: 이 캐시는 플랫폼에서 인기가 많은 콘텐츠(예: 특정 게시물, 동영상 등)를 저장합니다. 이 콘텐츠는 여러 사용자에게 자주 노출되기 때문에, 캐시에서 관리하면 전체 시스템 성능이 향상됩니다.

    • 일반 콘텐츠: 이 캐시는 일반적인 콘텐츠를 저장합니다. 여기에는 특정 사용자 또는 그룹에게 자주 조회되는 콘텐츠가 포함될 수 있습니다.

    • 콘텐츠 캐시는 사용자가 피드를 볼 때, 뉴스 피드 캐시와 함께 자주 사용됩니다. 특히 인기 콘텐츠는 여러 사용자에게 반복적으로 노출되므로 캐시가 큰 역할을 합니다.

  3. 소셜 그래프 캐시:

    • 팔로어: 이 캐시는 특정 사용자를 팔로우하는 다른 사용자 목록을 저장합니다. 예를 들어, A 사용자가 B를 팔로우할 때, A의 팔로워 목록에 B가 추가됩니다.

    • 팔로잉: 반대로, 사용자가 팔로우하는 대상(팔로잉)의 목록을 저장합니다. 예를 들어, A 사용자가 C를 팔로우하면, A의 팔로잉 목록에 C가 포함됩니다.

    • 소셜 그래프 캐시는 사용자의 관계 데이터를 빠르게 조회할 수 있도록 도와줍니다. 이는 뉴스 피드 생성 시, 어떤 사용자의 게시물을 피드에 포함시킬지를 결정하는 데 중요합니다.

  4. 행동 캐시:

    • 좋아요: 특정 게시물에 대한 좋아요 수나, 사용자가 특정 게시물에 좋아요를 눌렀는지 여부를 저장합니다. 예를 들어, 특정 게시물에 대해 좋아요를 누른 사용자의 목록을 캐시합니다.

    • 댓글: 특정 게시물에 대한 댓글과 그 댓글에 대한 메타데이터(예: 댓글 수, 누가 댓글을 달았는지 등)를 저장합니다.

    • 기타 행동: 사용자가 콘텐츠와 상호작용하는 다양한 활동(예: 공유, 북마크 등)을 저장할 수 있습니다.

    • 행동 캐시는 사용자가 콘텐츠와 상호작용할 때 발생하는 데이터를 관리하여, 빠른 피드백을 제공할 수 있습니다.

  5. 횟수 캐시:

    • 좋아요 횟수: 게시물 또는 콘텐츠가 받은 총 좋아요 수를 저장합니다. 이 데이터는 피드에 표시되거나 콘텐츠의 인기도를 평가하는 데 사용됩니다.

    • 댓글 횟수: 특정 콘텐츠에 달린 댓글 수를 저장합니다. 이 데이터 역시 피드에서 콘텐츠의 인기도를 나타내는 중요한 요소입니다.

    • 기타 횟수: 기타 중요한 이벤트의 횟수를 저장합니다. 예를 들어, 공유 횟수, 조회 수 등이 포함될 수 있습니다.

    • 횟수 캐시는 데이터베이스에 매번 접근하지 않고도 다양한 통계 정보를 빠르게 제공할 수 있습니다.

Last updated