11. 뉴스 피드

💬 뉴스 피드

  • 트위터나 인스타그램처럼 누군가 게시글을 올리고 이를 다른 사람이 확인할 수 있는 뉴스 피드를 설계해야 한다.

💬 컴포넌트

피드 발행

  • 사용자가 피드를 포스트하면 캐시와 데이터베이스에 저장해야 한다. 새 포스팅은 친구의 뉴스 피드에 전송되야 한다.

  • 사용자의 요청을 로드밸런서가 웹 서버들에 분배하고, 웹 서버에서는 내부 서비스들로 요청을 중계하게 된다.

  • 포스팅 저장 서비스는 저장소에 포스팅 정보를 저장하고, 포스팅 전송 서비스는 친구의 뉴스 피드를 캐싱해둔 저장소에 포스팅을 저장한다. 알림 서비스는 새 포스팅이 올라왔음을 사용자의 친구에게 알려야 한다.

웹 서버

  • 클라이언트로부터 요청을 받으며, 인증이나 처리율 제한의 기능도 수행한다.

  • 스팸이나 유해 컨텐츠를 방지하기 위해 특정 기간동안 한 사용자가 올릴 수 있는 포스트 수에 제한을 걸어두어야 한다.

포스팅 전송 서비스

  • 포스팅 전송 서비스 아키텍쳐를 자세히 설계하면 다음과 같다.

    • 그래프 데이터베이스에서 친구 ID 목록을 가져온다.

    • 사용자 정보 캐시에서 친구들의 정보를 가져온다. 특정 사용자의 게시글을 뉴스 피드에서 보이지 않게 mute 하는 등의 속성을 반영하기 위함이다.

    • 친구 목록과 새 포스트의 ID를 메시지 큐에 넣는다.

    • 포스팅 전송 작업 서버는 메시지 큐의 데이터를 읽어 각 사용자의 뉴스 피드 캐시에 데이터를 추가한다.

    • 뉴스 피드 캐시는 <포스트 ID, 사용자 ID> 엔트리를 보관하는 매핑 테이블이다. 캐시에 저장되는 데이터이므로 메모리 크기를 적절하게 유지하기 위해 모든 데이터를 저장하지 않고 ID 정보만 저장한다. 또한, 저장할 수 있는 엔트리의 개수도 제한하도록 한다.

  • 특정 사용자가 새 포스팅을 올렸을 때 해당 사용자의 친구들에게 전달해야 한다. 이 과정을 팬아웃이라고 부른다.

  • 쓰기 시점의 팬아웃 (fanout on write)

    • Push 모델이라고도 한다.

    • 포스팅을 기록하는 시점에 친구 목록에 있는 사용자들의 뉴스 피드를 갱신한다.

    • 뉴스 피드를 읽는 데 드는 시간이 짧아진다.

    • 친구가 많은 사용자의 경우 친구 목록을 가져와 모든 친구의 뉴스 피드 갱신에 많은 시간이 소요될 수 있다. 즉, hotkey 문제가 발생한다.

    • 서비스를 자주 이용하지 않는 사용자 피드까지 갱신해야 하므로 자원 낭비가 발생할 수 있다.

  • 읽기 시점의 팬아웃 (fanout on read)

    • Pull 모델이라고도 한다.

    • 사용자가 뉴스 피드를 읽는 시점에 뉴스 피드를 갱신한다.

    • 서비스를 자주 이용하지 않는 사용자는 로그인하기전까지 어떠한 컴퓨팅 자원도 소모하지 않으므로 효율적이다.

    • hotkey 문제가 발생하지 않는다.

    • 다만 뉴스 피드 읽기에 많은 시간이 소요될 수 있다.

  • 절충안

    • 대부분의 사용자에 대해 Push 모델을 사용하고, 친구나 팔로워가 많은 사용자의 경우 Pull 모델을 사용한다.

뉴스 피드 읽기

  • 모든 친구의 포스팅을 시간 역순으로 모아 뉴스 피드를 만들 수 있다.

  • 사용자가 뉴스 피드 조회를 요청하면 캐시로부터 피드 ID를 조회 후 뉴스 피드 서비스로부터 포스팅을 조회한다.

  • 웹 서버는 피드를 가져오기 위해 뉴스 피드 서비스를 호출한다.

  • 뉴스 피드 서비스는 뉴스 피드 캐시에서 가져온 포스트 ID를 기반으로 완전한 뉴스 피드를 만들어 클라이언트에게 반환한다.

  • 캐시는 다음과 같이 5계층으로 나누어 저장할 수 있다.

Last updated