주요 구현 기능
- 회원 닉네임 변경 히스토리
- 게시물 좋아요 기능
- 오프셋 기반 페이징, 커서 기반 페이징
- 회원간 팔로우 기능
- 타임라인 기능(팔로우한 회원의 게시글 배달)
member table
membrer_id | nickname | .. |
---|
nickname_history table
naickname_history_id | member_id | nickname | .. |
---|
- 필드의 이름(nickname)이 같다고 중복이 아니다.
- 히스토리성 데이터는 정규화의 대상이 아니다.
- 정규화의 대상이 항상 데이터의 최신성을 유지해야하는지 고려
게시물 좋아요와 같이 "조회 -> 변경 -> 저장" 로직을 따르는 기능은 동시성 문제를 고려해야 한다.
- 컬럼을 통한 구현(비관적 락, 낙관적 락)
-
- 조회시 컬럼만 읽어보면 된다.
- 쓰기시 게시물 레코드에 대한 경합이 발생한다 -> 하나의 자원을 두고 락 대기
- 같은 회원이 하나의 게시물에 대해 여러번 좋아요를 누를 수 있는 문제
= 쓰기 지점 병목(락 대기)
- 테이블을 이용한 구현
-
- 조회시 매번 count 쿼리 발생(어느 회원의 게시물 타임라인을 불러오기 위해 post_like 테이블에서 좋아요 수를 count)
- 쓰기시 경합 없이 insert만 발생 = 락 대기 해결
- 회원 정보 등 다양한 정보 저장 가능
= 조회 지점 병목(count 쿼리)
고려 사항 : 좋아요 수는 높은 정합성을 요구하는가? -> no
해결 방법
- 회원이 게시물 좋아요를 누를 경우 post_like(post_id, member_id, ..) 테이블에 insert
- 이후 게시물 조회 시점에 매번 post_like 테이블에 count를 하지 않고 post_like를 일종의 캐시처럼 활용
- 스케줄러를 이용하여 일정 주기마다 count -> post의 like_count 필드를 업데이트
- **스케줄러라는 별도의 모듈을 구성, 관리해야하는 단점 존재(관리 포인트가 늘어나고 시스템 복잡도가 올라간다.)
- 유튜브 조회수, 좋아요 수가 이런 방식인 것 같음. 영상들의 조회수, 좋아요 수가 곧바로 적용되지 않는걸 보아 스케줄러를 이용하는 듯 하다.(단 내가 좋아요 등을 누르면 프론트 측에서 곧바로 화면의 좋아요 수만 +1)
- 오프셋 기반 페이징
- 일반적인 페이징 기법
- 구현이 쉽고 직관적이다.
- 오프셋 기반 페이징은 조회된 모든 데이터의 총 합을 알아야하기 때문에 속도가 느려지는 문제 발생
- 커서 기반 페이징(무한 스크롤)
- 일관성 & 실시간 데이터 처리에 적합
- 일정한 성능 유지
- 커서 로직 구현이 필요하다는 단점이 존재
공통 기능 - 팔로우한 회원의 게시물이 나에게 배달
- pull model
- 게시물을 올리면 마땅한 로직을 거치지 않음
- 대신 게시물을 올린 회원을 팔로우한 사람이 타임라인을 조회하면 follow table -> post table을 거쳐 게시물을 읽어온다.
- 쓰기 성능up 조회 성능 down (follow -> post 를 거쳐 탐색을 하기 때문에 read 성능 저하)
- push model
- 게시물을 올리면 팔로우한 회원들에게 게시물을 직접 배달 (timeline table로 구현)
- 만약 팔로워가 무수히 많다면 쓰기 지점 병목 발생 (팔로우 수 만큼 timeline 테이블에 쓰기 작업 발생)
- 쓰기 성능 down 조회 성능 up
pull / push model 성능 테스트 참고
... 공사중