지난번 express에서 사용한 web socket io를 nest에 적용해 보기로 했다.
사실 nest에 적용하기 위해 express를 먼저 경험한 것이기 때문에 본 작업이 들어간 과정이라 생각했다.
ws 프로토콜을 처음 다뤄보고, socket io 의 함수들이 아직 낮설었기 때문에 이런 과정을 거쳤고,
nest에서 진행한 내용을 적어보려 한다.
🪴 데이터베이스 선택
일단 데이터베이스 선택에 앞서 어떤 기능을 구현할 것인지 먼저 정리해 보았다.
사용자들의 실시간 방송에 대한 실시간 채팅 기능을 구현하려 하였고,
복잡한 관계가 있는게 아닌 단순 메세지를 주고받을 예정이였으며,
추후 종료된 방송에 유저의 채팅 내역이 조회 할 수 있는 가능성을 열어두려 하였다.
먼저 기존의 다른 기능에 대한 데이터들은 관계형 데이터베이스인 mysql로 진행하기로 했는데,
채팅 기능의 경우 읽기 쓰기가 많은 점을 고려해서 어떤게 좋을지 비교를 해봤다.
찾아보니 한 논문을 번역한 글에 다음과 같은 실험 결과가 있었다.
실험은 이런 환경에서 진행했다고 한다.
- OS: Microsoft Windows 10 Pro 64 bit
- CPU: Intel (R) Core (TM) i5-3210M CPU @ 2.50GHz
- RAM: DDR3 8GB 1333MHz
- Storage: SAMSUNG MZ7PC128HAFU-000H1
- Database Settings: InsertsPerQuery: 5000; Indexing Technology: BTree;
- Test Data: 1,000,000 Records, 100% randomness
읽기 작업을 생각했을때 mysql과 mongodb간 차이는꽤 났다.
key value 타입인 berkeleyDB는 3가지 중 가장 빨랐다.
물론 mysql에서 어떤 join도 없이 가져오는 경우에서 테스트를 한 것인지는 나와있지 않아
어떤 상황이던 저런 결과가 나온다는 보장은 없지만,
일반적으로 비관계형이 훨씬 빠른 결과를 보여준다고 해 비 관계형 중에서 선택하기로 했다.
(참고로 Berkeley DB는 디스크 기반의 내장형 데이터베이스이고, 주로 임베디드 어플리케이션, 서버 어플리케이션 에서 사용한다고 한다)
비 관계형 데이터 베이스는 몽고디비와 레디스만 알고 있었는데, 좀더 다양한 선택지가 있었다.
이번 기회에 각 데이터베이스 들은 어떤 특성이 있고, 어떤 상황에 사용하는게 좀더 적합할지 알아보았다.
👀 비관계형 데이터베이스 종류 및 특성
1. Key-value
장점 : 읽기가 매우 빠르다. 확장이 쉽고 분산 시스템에 효율적이다.
단점 : 복잡한 관계를 표현하기 어렵고, 데이터에 대한 구조적 정보가 없어 검색에 제한적이다.
2. document
장점 : 비정형 데이터에 유연하게 대처가 가능하다(유동적 스키마). 또 상대적으로 쿼리작성이 쉬운편이다.
단점 : 데이터의 일관성이 좋지 않다. 스키마 변경이 계속 될경우 유지보수가 어려워 질 수 있다.
3. column
장점 : 특정 컬럼에 대해 연산이 빠르고, 각 로우는 다른 스키마를 가질 수 있어 유연성이 있다.
단점 : 일반적 읽기 쓰기 연산에는 적합하지 않으며, 특정 컬럼에 대한 집계 도는 통계에 적합하다.
4. graph
장점 : 복잡한 연산을 처리하는데 적합한 그래프 이론을 알고리즘으로 채택 하고 있어 복잡한 관계에 데이터 처리에 효과적이다.
데이터 요소간 탐색에도 용이하다.
단점 : 상호 연결된 데이터의 쿼리가 복잡할 수 있다.
🐕 추려내기
현재 진행하는 채팅 기능의 경우,
따로 복잡한 관계는 없고, 단순 메세지 전송, 읽기, 저장 정도이기 때문에 graph 는 제외했고,
채팅기능에 대한 통계를 낼것은 아니기 때문에 column도 제외했다.
key-value타입과 document타입 중에서 고민을 했는데,
그 이유는 복잡한 검색이 필요한게 아니라 단순한 내용 검색, 닉네임 검색 정도를 채팅기능에서 사용할 예정이였고,
key-value는 성능이 가장 빠른 타입이기 때문에 좀더 고민해 보기로 했다.
key-value에는 redis와 amazon DynamoDB, berkeleyDB, cassandra 가 있는데,
amazon DynamoDB의 경우 비용문제가 있어 고려대상에서 제외했다.
berkeleyDB 는 디스크 기반 저장소이기 때문에 빠른 데이터 처리가 필요한 채팅기능에 적합하지 않아 제외했다.
cassandra 는 여러가지 측면에서 따져봣을때 훌륭한 선택지였지만, 경험해 보지 않은 데이터베이스 였다.
어떤 측면에서, 왜 cassandra가 훌륭한 선택지였는지는 길어질 것 같아서 1차 구현 이후 다시 작성하도록 하겠다.
프로잭트의 정해진 시간 안에 계획된 일정들이 있었고, nestjs로 socket 을 이용해 채팅기능 구현 자체가 처음이였기 때문에,
일단 데이터베이스가 익숙하지 않은 cassandra는 배재하였다.
1차 구현 이후 성능개선할때 1순위로 고민해볼 데이터베이스 라고 생각한다.
redis 승
document 에는 mongodb, CouchDB, Elasticsearch 가 있는데,
CouchDB 에는 인메모리 를 지원하지 않기 때문에
빠른 읽기, 쓰기가 중요한 채팅기능에는 적합하지 않다고 생각해 고려대상에서 제외했다.
그런데 차마 생각하지 못했던 부분이 있었다.🫠
🧐 mysql 과 관계를 맺을것인가?
다른 기능들은 데이터베이스를 sql을 사용하는데,
live, user, alert 테이블 들과 관계를 맺을 것인가 에 대한 부분이다.
관계를 맺는다면 이부분 또한 지원이 가능한지 따져봐야 하기 때문에 먼저 이부분을 결정하기로 했다.
참고하고 있는 사이트인 아프리카 티비와, 치지직을 살펴보니
아프리카 티비는 유저의 채팅 댓글을 조회할 수 없었고, 치지직은 조회가 가능했다.
고민해 본 결과 내가 시청한 방송에 대한 채팅을 조회할 일은 없을 것 같다고 생각해 불필요한 기능이라고 생각했고,
myslq 테이블과 관계를 맺지 않기로 했다.
🤨 다시 고민 (mongodb와 elasticsearch 그리고 redis )
그렇다면 데이터베이스 고려 대상들 중
mongodb와 elasticsearch 그리고 redis 가 남았다.
사실 검색기능을 생각하면 elasticsearch가 특화된 구조라 이걸 선택하는게 합당하다고 생각했다.
그렇지만 검색을 제외하고 생각해 본다면
과연 이 elasticsearch 데이터베이스를 사용하는게 최선일까 라는 부분에 대해서는 고민이였다.
읽기와 쓰기에는 적합하지 않기 때문이다.
다시 되짚어 보자면, 구현하려고 하는 채팅 기능은
1️⃣ 실시간 채팅 , 읽기, 쓰기 기능
2️⃣ 채팅내역 저장 기능
3️⃣ 채팅 내용 및 닉네임 검색 기능
저장을 생각했을때, 장애 발생시 데이터가 날아갈 위험이 있는 레디스는 적합하지 않았다.
그렇지만 가장 빠른 데이터베이스였다.(읽기, 쓰기)
elasticsearch는 검색에 가장 최적화 되어있지만, 쓰기작업에 있어서 성능이 떨어진다.
mongoDB는 저장에 있어서 레디스 보다 안정적이고,
key-value타입인 레디스, 그리고 다른 데이터베이스 들과 비교했을때 괜찮은 데이터베이스였고,
다양한 쿼리를 지원해 데이터 검색도 가능했다.
😆 선택
결론부터 말하자면, 두개의 데이터베이스를 함께 사용할 수 있는 방법이 있는지는 차차 알아보도록 하고,
( 레디스를 캐시 디비로 두고 쓴다는 말을 들었는데 이부분에 대해서는 좀더 찾아봐야 겠다)
일단은 mongoDB로 작업하기로 했다.
1️⃣ 채팅 데이터 저장에 있어서 레디스보다 데이터 저장 측면에서 안정적이였다.(복제, 샤딩)
2️⃣ 다른 데이터베이스 들에 비해 빠르게 읽기쓰기 작업이 가능했고,
3️⃣ 쿼리와 인덱싱을 통한 검색기능 지원도 하기때문에 이 3가지 모두를 괜찮은 성능으로 사용하기 위해 선택했다.
참고한 사이트
https://aws.amazon.com/ko/nosql/
https://db-engines.com/en/system/CouchDB%3BElasticsearch%3BMongoDB
'TIL' 카테고리의 다른 글
24/01/22 TIL __ 채팅기능에 금칙어 기능 추가 ( aho-corasick 라이브러리) (0) | 2024.01.22 |
---|---|
24/01/21 TIL __ nestjs에서 socket io를 이용해 실시간 채팅기능 구현(mongodb) (0) | 2024.01.21 |
24/01/19 TIL __ ejs 에서 js파일 인식이 안될때(nest.js) (0) | 2024.01.19 |
24/01/18 TIL __ 웹소켓 (0) | 2024.01.18 |
24/01/17 TIL __ CORS (Cross Origin Resource sharing) (0) | 2024.01.18 |