본문 바로가기

항해99_10기/105일의 TIL & WIL

[7주차] [20221226] Notion clone 프로젝트 DB 설계

1주일 노션 클론 팀 챌린지


1주일 내에 완성하기 위해 프로젝트 스코프를 최대한 간결하게 잡았다.

소켓 사용을 주 목적으로 하여, 다른 것은 다 빼고, 실시간 통신 기능을 구현하는데 초점을 맞추기로 했다.

 

도메인으로 접속하는 모든 사용자를 소켓으로 연결해 한 명의 유저가 페이지에 입력하는 내용을 실시간으로 다 함께 볼 수 있고, 편집할 수 있는 기능을 만들고자 기획하였다.

 

구현 기능

1. 입장하는 유저에 랜덤 닉네임 부여 -> 사이드바에 현재 접속자 닉네임 띄우기

2. 페이지 상단에 실시간으로 입장 공지 띄우기

3. 페이지에 사용자가 텍스트를 입력하면 이를 감지하여 서버로 전송 -> 서버에서는 접속한 모든 소켓에 보내어, 실시간으로 페이지에 반영

4. 퇴장 유저의 닉네임 제거

 

사실상, 백에서는 소켓을 핸들링 하는 것은 그렇게 어렵지 않고, 코드도 몇 줄 안나왔다...

 

이 후에 저장 기능을 더 붙일 수 있을지는 모르겠지만...

만약에 붙일 수 있다면, 아래와 같이 설계해보았다.

 

추가 구현하고 싶은 기능

  1. 1시간에 한 번씩 페이지의 데이터를 db에 저장하고 리셋한다.
  2. 매 시간 저장된 페이지 데이터는 6시간 단위로 갱신한다. -> 페이지가 저장되고 6시간이 지나면 더이상 볼 수 없게 삭제 된다.
  3. 저장된 6개의 페이지는 사이드바에 get 메소드로 호출하여 http 통신을 통해 조회만 할 수 있게 한다.

 

 

추가기능 구현을 위한 DB 설계


이렇게 설계된 프로젝트에서 db 사용은 크게 두가지 전략으로 나눠볼 수 있다고 생각했다.

  1. 실시간 페이지 데이터의 버전관리를 위해, 스택 형태로 저장하여 최신 버전을 사용자에게 보내주고, 만약 충돌이 날 경우, 이전 버전에 접근할 수 있도록 함.
  2. 1시간마다 마지막 수정본을 db에 쌓아놓고, 6시간마다 새로운 버전으로 갱신

위와 같이 db 사용 전략을 세우고, 어떤 db가 이에 어울릴까 고민하다가, 인메모리 캐시 형태의 redis는 어떨까 하고 알아보게 되었다.

 

기본적으로 in-memory db는 한번 db에서 조회한 데이터를 cache에 저장하여 같은 데이터를 조회하기 위해 매번 db를 뒤지고, sort하고, 하는 작업 없이, 이미 원하는 형태로 가공된 데이터를 캐쉬에서 가져다 사용할 수 있어, 데이터 호출에 대한 빠른 대응이 가장 큰 장점이라고 할 수 있다. 

 

전통적인 사용 방식으로, RDBMS인 redis를 서버 뒤에 두고, 그 뒤에 다시 mySQL. PostgreSQL과 같은 DBMS를 두어 DBMS 조회/사용을 최소화하는 형태의 db 사용 전략을 가져갔다.

 

예를 들어, 게시판에서 게시글 데이터를 생각해보면, 여러 수의 사용자가 게시판 사이트에 접속해서 get api를 호출할 때마다 같은 데이터가 호출된다.(게시글이 수정/삭제되지 않는다면) 

 

이렇게, 사용자가 접속할 때마다 같은 데이터를 조회하고 가공(sort, joint 등등등)해서 반응하는 것보다, 한번 DBMS에서 가공해서 꺼낸 데이터를 캐쉬로 저장해 두었다가 캐쉬를 사용해 반응해 준다면, db 조회에 걸리는 시간이 월등히 절약되는 것이다.

 

때문에, 전통적인 db 사용 전략에서 in-memory database는 자주 가공되지 않고, 많이 호출되는 특성의 데이터, 그리고 유실되어도 괜찮고 자주 진화하는 데이터를 사용할 때 이점을 챙길 수 있다.

 

 

위와 같이 전통적인 사용 전략만 놓고 본다면, 우리가 기획하고 있는 서비스와는 조금 결이 다르다고 느낄 수 있겠다.

하지만, 그럼에도 불구하고, redis를 사용해야 하는 이유는, 바로, redisJSON 사용에 있다.

in-memory에 JSON 객체를 저장하고 이를 override 할 수 있다.

 

redis를 사용한 DB 설계

이렇게 우리 서비스에 접목시킬 redis 사용 전략을 그림으로 그리다보니, 사실상 redis가 우리 서비스에 딱 맞다는 것을 알게 되었다.

db에는 총 두가지 종류의 데이터가 저장되는데,

  1. 실시간 페이지 변경 추적 데이터 (3개의 버전으로 관리)
    • (사용관점) 가장 마지막에 저장된 데이터를 가장 먼저 꺼내는 STACK
    • (저장관점) 가장 먼저 저장한 데이터를 가장 먼저 밀어내는 QUEUE
  2. 1시간마다 생성되는 페이지 데이터 (6시간 간격으로 갱신)
    • documents data의 특징 : 변하지 않지만, 자주 호출되고, 지워져도 서비스에 큰 영향을 미치지 않으며, 계속해서 진화하는 데이터
    • (사용관점) redisJSON & in-memory cache의 장점을 취할 수 있음
    • (저장관점) 가장 먼저 저장한 데이터를 먼저 밀어내는 QUEUE

각각 데이터를 사용하는 관점과 저장하는 관점으로 구분해서 생각해볼 수 있고, 그 결과, redis가 정말 잘 들어 맞는 선택이란 것을 알 수 있었다.

(물론, redis를 사용해보고 싶어서 끼워맞춘 것일 수도 있다..ㅋㅋㅋ)

 

Q. 데이터 셋이 매우 자주 변경되고, 같은 내용을 같은 형태로 자주 렌더링 해야 하는 관점에서 mongoDB와 비교한다면 어떨까?

 

참고로, DB 선택을 고려할 때, 우리 서비스가 데이터의 정합성이 중요한 서비스가 아니기 때문에, DBMS는 배제했다.

만약 진짜로 노션과 같이 중요 문서를 저장하는 시스템이었다면, 나는 DBMS와 in-memory cache DB, 그리고 noSQL을 모두 선택했을 것이다.