뉴스피드란?
SNS 서비스를 이용해본 사람이라면 뉴스피드가 뭔지 알 수 있을 것이다.
다음은 Chat GPT 의 답변입니다.
"뉴스피드"는 주로 소셜 미디어 플랫폼에서 사용되는 용어입니다. 뉴스피드는 해당 플랫폼에서 사용자가 팔로우한 친구, 페이지, 그룹 등의 활동 및 업데이트를 보여주는 피드를 가리킵니다. 예를 들어, Facebook, Instagram, Twitter와 같은 소셜 미디어 플랫폼에서 사용자가 로그인하면 가장 먼저 볼 수 있는 그 화면이 바로 뉴스피드입니다. 뉴스피드에는 친구들의 게시물, 사진, 동영상, 뉴스 기사, 광고 등이 표시됩니다.
구현 요구 사항
- 다른 사용자를 팔로우 하면 해당 사용자의 활동을 더 쉽게 확인할 수 있습니다.
- 팔로우한 사용자의 활동이 나의 뉴스피드에 떠야 한다.
- 포스트
- 댓글 ex. B님이 C님의 글에 댓글을 남겼습니다.
- 상호작용 ex. B님이 C님의 글을 좋아합니다.
- 팔로우 활동 ex. B님이 C님을 팔로우 합니다.
- 팔로우한 사용자의 활동이 나의 뉴스피드에 떠야 한다.
- 뉴스피드는 팔로우한 사용자들의 포스트 및 소식을 보여주어 사용자가 소식을 신속하게 받을 수 있습니다.
- 뉴스피드를 최신 순으로 보여준다.
- 팔로우한 사용자들의 활동 (2. 팔로우 관계 섹션 참고)
- 나의 팔로우 활동
- 나를 팔로우 하는 사용자 소식
- 나의 포스트
- 나의 포스트에 남겨진 댓글 ex. B님이 OO 포스트에 댓글을 남겼습니다.
- 나의 포스트의 상호작용 ex. B 님이 OO 포스트를 좋아합니다.
정리해보면 다음과 같다.
- 내가 팔로우 한 사람들의 활동
- 나를 팔로우 하는 팔로우 소식
- 나의 포스터에 남겨진 댓글, 좋아요 소식
위와 같이 3가지 활동이 뉴스피드 화면에 보여야 한다.
구현 방식
뉴스피드 구현 방식은 Fan Out On Write, Fan Out On Read 두가지 방식이 존재한다.
각 방식의 작동 원리와 시간복잡도, 공간복잡도, 실제 구현하고 있는 서비스에 대해서 알아보겠다.
Fan Out On Write
Fan Out On Write 은 사용자가 활동을 하면 그 활동 데이터를 기반으로 바로 뉴스피드 데이터를 생성하는 방식이다.
예제
UserA의 팔로워는 3명이고 UserA가 포스터를 작성했다
여기서 UserA의 id 는 1이고 작성한 포스터 id 도 1이라고 가정하자.
다음과 같은 NewsFeedTable이 완성 될 것이다.
공간복잡도
위 테이블을 보면 UserA의 팔로우 수에 비례하는 공간복잡도가 발생하는 것을 확인 할 수 있다.
뉴스피드 테이블의 공간 복잡도 = 활동 수 * 활동 유저의 팔로워 수
그렇기 때문에 팔로워 수가 많은 서비스인 경우 적절하지 적절하지 않을 수 있다.
시간복잡도
그렇다면 저장과 읽기 시간 복잡도는 각각 어떻게 될까 ?
1. 쓰기 시간 복잡도
팔로워 목록을 가져오는 시간 + 뉴스피드를 저장하는 시간일 것이다.
팔로워 목록을 가져오는 시간은 Follow Table의 인덱싱 여부에 따라 다르지만 인덱싱이 되어 있다고 가정하면
log(팔로우 테이블 크기) 만큼의 시간복잡도가 발생할 것이다.
뉴스피드 저장하는 시간복잡도는 어떻게 될까? 만약 user_id를 기준으로 인덱싱이 되었다고 가정하면
log(뉴스피드 테이블 크기) * 팔로워 수 만큼의 시간복잡도가 발생할 것이다.
저장시간 복잡도 = log(팔로우 테이블 크기) + log(뉴스피드 테이블 크기) * 팔로워 수
2. 읽기 시간 복잡도
한 유저의 뉴스피드 데이터를 읽는 시간복잡도는 NewsFeed Table의 인덱싱 여부에 따라 다르지만
user_id 기준으로 인덱싱 되어 있다고 가정하였기 때문에 log( 뉴스피드 테이블 크기) 일 것이다
읽기시간 복잡도 = log( 뉴스피드 테이블 크기)
요약
실제 사용 서비스
Twitter 는 Fan Out On Write 모델을 사용하며 다음과 같은 제약사항을 걸어두었다.
Fan Out On Read
Fan Out On Read 은 사용자가 활동을 하면 그 활동 데이터만 저장해 두었다가.
사용자가 뉴스피드데이터를 요청하면 활동데이터 안에서 뉴스피드 데이터를 생성하는 방식이다.
예제
UserA의 id 는 1이고 작성한 포스터 id 도 1이라고 가정하자.
Fan Out On Write 와는 다르게 단지 Activity 데이터만 저장될 것이다.
공간복잡도
그렇다면 공간 복잡도는 단지 활동수에만 비례 하게 될 것이다.
활동 테이블 공간 복잡도 = 활동 수
시간복잡도
저장 시간복잡도와 읽기 시간 복잡도는 각각 어떻게 될까?
1. 쓰기 시간 복잡도
저장 조건은 user_id를 인덱스로 잡아 저장한다.
저장시간 복잡도 = log(활동 테이블 크기)
2. 읽기 시간 복잡도
읽기 시간 복잡도는 나의 팔로잉을 읽어오는 시간 + 내 팔로잉들의 활동을 읽어 오는 시간 + 시간순으로 정렬하는 시간일 것이다.
먼저 나의 팔로잉을 읽는 시간은 팔로잉 테이블이 인덱싱이 되어 있다는 가정하에 log(팔로잉 테이블 크기) 일 것이다.
다음으로 내 팔로잉들의 활동을 읽어 오는 시간은 log(활동 테이블 크기) * 팔로잉 수 일 것이다.
여기서 더하여 시간순으로 정렬을 해야하기 때문에 정렬시간 만큼의 시간복잡도가 추가 될 것이다.
읽기시간 복잡도 = log( 팔로잉 테이블 크기 ) + log(활동 테이블 크기) * 팔로잉 수 + 정렬 시간
즉 사용자가 읽기를 많이 하는 경우 Fan Out On Write 보다 좋지 못한 경험을 하게 될 것이다.
요약
실제 사용 서비스
Facebook과 Instagram 은 Fan Out On Read 모델을 사용하며 다음과 같은 제약사항을 걸어두었다.
구현 방식 선택
구현 방식 비교
결국 각각의 장단점이 분명하다.
Fan Out On Write
- 읽기 성능이 좋으며 , 쓰기 성능이 좋지 않다.
- 저장시에 서버에 과부하를 일으킬 수 있다.
- 팔로워 수가 많아지면 저장시 문제가 생길 수 있다.
- 활동수가 많을 수록 서버에 과부하가 걸린다.
Fan Out On Read
- 읽기 성능이 좋지 않으며 , 쓰기 성능이 좋다.
- 많은 읽기 요청이 들어오면 서버에 과부하를 일으킬 수 있다.
- 팔로잉수가 많아지면 읽기 성능이 느려진다.
- 유저가 뉴스피드 읽기를 많이 요청할 수록 떨어지는 성능을 경험한다.
구현 방식 선택
먼저 나는 Fan Out On Write 방식을 채택하였다.
이유는 다음과 같다.
- 종목토론방의 특성상 활동수가 다른 SNS 보다 적을 것이라고 예상하여 공간복잡도문제는 해결 될 것
- 동시에 저장요청이 많을 경우는 카프카를 통하여 문제를 해결할 수 있을 것
- 공간 복잡도 문제는 해결 됐기 때문에 읽기 성능이 뛰어난 Fan Out On Write 방식 채택
요약
Fan Out On Read, Fan Out On Write 각각 장단점이 존재한다.
각 장단점을 잘 파악하고 서비스 특성에 맞게 적용하는 것이 중요할 것이다.
참조
'프로젝트 > 주식종목토론방' 카테고리의 다른 글
'Monolithic'에서 'MSA'구조로 전환 (1) | 2024.03.18 |
---|---|
스프링 대용량 데이터 저장 성능 issue - jpa saveAll, batch insert, multi thread (0) | 2024.03.04 |