대표 테이블들만 표시를 해봤는데 각 테이블 간의 관계가 너무 많이 묶여있어서 정규화를 지키려면 sub table들이 많이 생겨 JOIN 과도화 될 것 으로 예상되었다.
모든 테이블이 다른 테이블을 참조하고 있다.
현재 사용자가 속한 커뮤니티들 중에서 채널의 정보를 RDBS로 한다고 가정해보자
사용자 (A) x 커뮤니티 (B) + 사용자 (A) x 채널 (C) 만큼의 검색이 더 필요하다…
→ NoSQL을 활용해 비정규화 한다면?
사용자가 속한 커뮤니티 정보들을 사용자 Document에 커뮤니티라는 column을 만들고 내부를 key-value 형식으로 저장한다면! → JOIN Table 탐색을 없앨 수 있을 것 같다!
사용자 document의 communities는 용량 측면으로는 어차피 RDB도 JOIN Table을 생성해야해서 추가로 발생하는 용량은 비슷할 것이라 생각했다.
사용자는 커뮤니티 field를 가지고 있고 value는 객체로 채널 id를 key, 채널 마지막 접속 시간을 value로 한object를 가지도록했다.
id는 document 생성시 자동으로 생성되는 document unique id(_id) 이다.
프로젝트 시작 전에 멘토님이 하나의 document에 너무 많은 data를 담고있으면 분할하는 것을 권장하셨다. (검색해보니 max 16KB)
따라서 채널의 채팅 로그 기록들은 100개 단위로 document를 구성하고, 초과하면 새로운 document를 생성하기로 설계하였다.
followings : 내가 팔로우하는 사용자 목록
followers : 나를 팔로우 하는 사용자 목록
A가 B를 팔로우하기 시작하면 A의 document followings에 추가 + B의 document followers에 추가
A가 B를 팔로우 취소 했을 때 A의 document followings에서 삭제 + B의 document followers에 삭제
→ 하나의 Transaction에 2개의 쿼리 실행이 필요하다.
그러나 followers field만 가지고있다면, 화면에 followers 정보를 보여줘야할 때, Users collection 전체를 확인하면서 followers에 현재 사용자의 id가 있는지를 확인해봐야한다.
→ 갱신 이상이 생기지 않도록 백엔드에서 더 챙기기로 했다.
어떤 DB를 사용할 지 정하기 전에, 조원 중 한명이 Prisma를 추천했다. (직관적이고 러닝커브가 짧다)
Prisma를 확인해보니 확실히 직관적으로는 보이지만, NestJS에서 mongodb 사용을 위해 TypeORM과 mongoose를 지원하고 있었다.
TypeORM은 mongodb v3까지 지원했고, mongoose가 가장 많이 사용하는 MongoDB의 ORM으로 문서 찾기가 편하여 mongoose를 선택했다.
https://docs.nestjs.com/techniques/mongodb
설계를 마치고 실제로 사용하면서 추가적으로 어떤 고민들을 했는지는 다음 포스팅으로 적어두었습니다.