1대1 매칭서비스가 성사 된 이후 그 둘에 대해서만 채팅이 가능하게 하는 서비스 구현 계획을 세우고 있습니다.
이에 대한 연관관계는?
1대1 매칭 서비스가 성사된 이후 1대1 채팅 서비스를 구현할 때 필요한 주요 연관관계는 사용자와 채팅 세션 또는 채팅 메세지 간의 관계가 있습니다.
엔티티 구조
사용자(Users)
1대1 매칭(Matching) 각 사용자는 1대1 매칭 엔티티를 통해 매칭 관계를 설정합니다.
1대1 매칭(Matchings)
일대다(User와 연관): 두 명의 사용자(user_id_1, user_id_2)를 연결하여 매칭을 성사시킵니다.
1대1 채팅세션(chatrooms): 매칭이 완료된 후 채팅 세션을 생성하여 두 사용자가 연결될 수 있도록 합니다.
1대1 채팅 세션(chatrooms)
필드: chatrooms_id, matching_id
연관관계
Matching과 일대일 관계 : 매칭과 1대1 관계를 가지며, 각 매칭당 하나의 채팅 세션이 생성됩니다.
Chatting와 1대다 관계: 각 채팅 세션은 여러개의 메시지(chatting)와 연결됩니다.
채팅(Chattings)
필드: chatting_id, chatroom_id, created_at, (is_read읽음여부는 추후에 개발 예정)
연관관계
chatrooms과 다대일 관계: 여러개의 메세지가 하나의 채팅 세션에 속합니다.
User와 다대일 관계: 각 메세지는 하나의 사용자(sende_id)가 보낸 것으로 저장됨
서로의 연관관계에 대해 정리해서 설명하면?
사용자(User)와 매칭(Match):
각 사용자는 여러 개의 매칭을 가질 수 있으므로 1:N 관계를 가집니다.
매칭이 완료되면 두 명의 사용자 간 1대1 채팅 세션이 생성됩니다.
매칭(Match)과 채팅 세션(ChatSession):
매칭이 성사되면 한 개의 채팅 세션이 생성되며, 1:1 관계를 갖게 됩니다.
매칭당 하나의 채팅 세션만을 허용하여 두 사용자가 대화할 수 있는 단일 경로를 제공합니다.
채팅 세션(ChatSession)과 채팅 메시지(ChatMessage):
각 채팅 세션은 여러 개의 메시지를 포함하므로 1:N 관계를 가집니다.
하나의 채팅 세션 내에서 다수의 메시지가 주고받으며, 각각의 메시지는 sender_id로 사용자와 연결됩니다.
사용자(User)와 채팅 메시지(ChatMessage):
각 메시지는 발신자를 명시하기 위해 User와 다대일 관계를 가집니다.
사용자 -> 매칭 -> 채팅 세션 -> 메세지로 이어지는 관계를 통해 매칭이 성사된 후 1대1 채팅을 관리합니다.
각 기술 스택을 사용하는 이유
Kafka VS Rabbit MQ
"결론적으로 말하면 Rabbit MQ를 사용하는 것이 더 적합할 가능성이 높다!"
설치 및 관리의 용이성
- RabbitMQ는 설치와 관리가 상대적으로 간단하고, 소규모 프로젝트에서 필요한 기본 메시징 기능을 빠르게 설정할 수 있습니다. 또한, Docker 컨테이너로도 쉽게 배포할 수 있어 개발 환경에서의 설정이 간편합니다.
- Kafka는 고성능과 대규모 분산 시스템을 위한 메시징 솔루션으로, Zookeeper와 함께 구성되어야 하는 등 초기 설정과 관리가 복잡합니다. 유지 보수 측면에서도 소규모 프로젝트에는 다소 부담이 될 수 있습니다.
성능과 메시지 보장 특성
- RabbitMQ는 전통적인 메시지 큐 방식으로, 주로 작업 큐, 채팅 서비스, 알림 처리 등에 적합합니다. 메시지 전송 보장(At-Least-Once Delivery)과 ACK 기능이 내장되어 있어, 메시지 전달 실패 시 재시도를 자동으로 수행할 수 있습니다.
- Kafka는 분산 로그 시스템에 가까우며, 고성능 데이터 스트리밍과 대규모 데이터 처리에 특화되어 있습니다. 그러나 소규모 프로젝트에서 1대1 채팅과 같은 단순 메시징에는 과도한 성능이 될 수 있으며, 관리 부담이 커집니다.
- At-Least-Once-Delivery: 메세지 전송에서 최소한 한번 이상 메세지가 수신자에게 도달하도록 보장하는 전달 방식
-> 즉, 메세지가 전달 실패할 경우 재전송을 통해 메세지가 수실될 떄까지 시도합니다.
- ACK(Acknowledgment): 메세지 시스템에서 메세지가 성공적으로 수신되었음을 알리는 확인 응답. 메세지의 송신자는 ACK를 통해 수신자가 메세지를 제대로 받았는지 확인할 수 있으며, 메세지 손실 방지를 위한 중요한 역할을 한다.
실시간 메시징에 최적화된 기능
- RabbitMQ는 AMQP 프로토콜을 기반으로 하여 실시간 메시지 전송에 최적화된 다양한 기능을 지원합니다. 특히, 1대1 채팅 서비스와 같은 실시간 데이터 흐름을 처리할 때 STOMP와 함께 사용하기 편리합니다.
- Kafka는 일반적으로 높은 처리량을 요구하는 로그 수집이나 이벤트 스트리밍 등에 최적화되어 있으므로, 실시간 상호작용이 필요한 1대1 채팅 서비스에는 RabbitMQ가 더 유리합니다.
- AMQP(Advanced Message Queuing Protocol): 메세지 브로커를 통한 신뢰성 있는 메세지 전송을 위해 설계된 오픈 표준 프로토콜. RabbitMQ와 같은 메세지 브로커에서 사용, 애플리케이션 간의 데이터 전송을 안전하고 효율적으로 관리가 가능.
메모리 및 리소스 효율성
- RabbitMQ는 상대적으로 가벼운 리소스를 사용하여, 작은 규모의 애플리케이션에서도 무리 없이 동작합니다.
- Kafka는 높은 처리량을 위해 더 많은 메모리와 스토리지를 필요로 하므로, 소규모 프로젝트에서는 필요 이상의 리소스를 소모할 수 있습니다.
메시지 우선순위 및 유연한 큐 관리
- RabbitMQ는 큐 단위로 메시지 우선순위를 설정하거나, 지연 메시지 기능 등을 통해 유연하게 메시지를 제어할 수 있습니다. 이는 특정 채팅 메시지를 우선적으로 처리하거나, 알림 메시지를 지연시키는 등의 로직 구현에 유리합니다.
- Kafka는 기본적으로 메시지를 토픽 단위로 관리하므로, RabbitMQ만큼 큐의 세밀한 제어가 어렵습니다.
즉!
소규모 1대1 채팅 서비스와 같은 실시간 메시징과 낮은 관리 부담이 중요한 상황에서는 RabbitMQ가 Kafka보다 더 적합합니다. RabbitMQ는 간단한 설정과 사용 편리성, 메시지 보장 및 실시간 처리에 특화되어 있어 이 프로젝트의 요구사항에 잘 맞습니다. Kafka는 분산 환경에서 대규모 데이터 스트리밍이 필요한 경우 적합하지만 소규모 실시간 메시징에는 과도한 솔루션이 될 수 있습니다.
WebSocket VS STOMP
"결론은 STOMP가 더 유리하다"
메시지 라우팅 및 관리 용이성
- STOMP는 메시지 목적지(destination)와 구독(subscription) 구조를 통해, 메시지의 흐름을 쉽게 관리할 수 있습니다.
- WebSocket만 사용할 경우, 채팅 참여자나 채널에 대한 라우팅 로직을 직접 구현해야 하기 때문에, 메시지 관리를 위해 STOMP가 더 적합합니다.
메시지 브로커와의 통합성
- STOMP는 RabbitMQ와 같은 메시지 브로커와의 통합이 용이하여, 안정적인 메시지 큐잉 및 전송 보장이 가능합니다. 이는 특히 메시지의 중복, 순서 보장이 중요한 1대1 채팅 서비스에서 유용합니다.
- WebSocket은 메시지 브로커와의 기본적인 통합이 어렵고, 재전송이나 중복 제거와 같은 고급 메시징 기능을 직접 구현해야 하므로 관리가 복잡해집니다.
구독 기반의 메시징 모델
- STOMP의 구독 모델을 사용하면, 특정 사용자에게만 메시지를 전송하거나 다수의 사용자에게 동시에 전송할 때 매우 유용합니다. 예를 들어, 1대1 채팅에서 특정 사용자 간의 메시지 전송을 구독을 통해 간편하게 설정할 수 있습니다.
- WebSocket은 주로 단순한 양방향 통신을 위한 용도로 사용되므로, 구독 기반의 메시징을 별도로 구현해야 하며, 코드가 복잡해질 수 있습니다.
메시지 일관성 보장
- STOMP는 메시지를 목적지에 따라 라우팅하고, ACK를 통해 메시지 수신 여부를 확인할 수 있어, 메시지의 일관성과 신뢰성을 보장할 수 있습니다. 이는 채팅 서비스에서 메시지 손실을 줄이는 데 효과적입니다.
- WebSocket은 연결이 끊겼을 때 자동으로 메시지 전송이 중단되며, 재전송 기능이 없기 때문에 메시지 신뢰성 보장이 어렵습니다.
그래서 메세지 구조와 라우팅이 필요한 채팅 서비스에서는 STOMP가 더 적합합니다. RabbitMQ와의 통합을 통해 메세지 큐잉, 구독 모델, 메세지 일관성 보장 등 실시간 메세징에 필요한 기능을 손쉽게 구현할 수 있습니다.
MongoDB VS DynamoDB VS Cassandra
"소규모의 1대1 채팅 서비스에는 MongoDB가 가장 적합할 것으로 예상됨"
그러면 MongoDB를 선택한 이유가 무엇인가요?
유연한 스키마 구조:
- MongoDB는 JSON 형식의 문서 기반 데이터베이스로, 데이터 구조가 자주 변경될 가능성이 높은 프로젝트에 적합합니다.
- 채팅 서비스에서 사용자 정보, 메시지 내용, 읽음 상태, 첨부 파일 등 다양한 필드를 자유롭게 추가할 수 있습니다.
- DynamoDB와 Cassandra도 NoSQL로 스키마 유연성이 있지만, MongoDB만큼의 자유로운 구조 변경을 허용하지 않습니다.
복잡한 쿼리 지원:
- MongoDB는 범위 쿼리, 정렬, 필터링 등 복잡한 쿼리를 지원하여, 다양한 기준으로 채팅 메시지나 사용자 정보를 조회하는 데 적합합니다.
Ex) 특정 기간 동안의 채팅 내용을 검색하거나, 특정 조건으로 채팅 이력을 필터링할 수 있어 사용자 경험이 향상됩니다.
- Cassandra는 기본적으로 간단한 키-값 쿼리에 최적화되어 있어 복잡한 검색에 비효율적이며, DynamoDB는 쿼리 기능이 제한적이기 때문에 MongoDB보다 불편할 수 있습니다.
빠른 개발과 유지 관리 용이성:
- MongoDB는 개발 초기부터 스키마를 엄격히 정의하지 않아도 되기 때문에, 초기 설계 변경이 잦은 소규모 프로젝트에서 개발이 빠르고 간편합니다.
- MongoDB Atlas와 같은 관리형 서비스도 있어, 인프라 관리를 줄이면서도 빠르게 개발을 진행할 수 있습니다.
- DynamoDB는 초기 설정이 다소 복잡하고, Cassandra는 클러스터 구성 및 데이터 파티셔닝 설정이 필요해 유지 관리가 부담될 수 있습니다.
읽기/쓰기 성능과 확장성:
- MongoDB는 읽기/쓰기 성능이 우수하며, 샤딩을 통해 수평 확장이 가능하므로 데이터가 늘어나도 안정적인 성능을 유지할 수 있습니다.
- DynamoDB는 높은 쓰기 성능이 있지만, 읽기 성능이 요구되는 서비스에서는 비용 효율이 떨어질 수 있습니다. Cassandra는 대규모 분산 시스템에는 적합하지만, 소규모 서비스에서는 필요 이상의 기능이 될 수 있습니다.
그러면 다른 데이터베이스를 선택하지 않은 이유가 무엇인가요?
- DynamoDB: 빠른 쓰기 성능과 서버리스 환경의 장점이 있지만, 데이터 구조나 쿼리가 제한적이어서 복잡한 쿼리나 사용자별 맞춤 검색에는 불편할 수 있습니다. 또한, 트래픽 변동이 크지 않다면 비용 효율도 떨어질 수 있습니다.
- Cassandra: 높은 쓰기 성능과 대규모 분산 시스템에 유리하지만, 데이터 구조가 단순해야 하고 복잡한 조회에는 비효율적입니다. 또한, 설정과 관리가 다소 복잡하여, 소규모 실시간 채팅 서비스에는 오버 엔지니어링이 될 수 있습니다.
결론은...
MongoDB는 소규모 채팅 서비스의 데이터 구조 유연성, 복잡한 쿼리 지원, 빠른 개발 속도에서 다른 데이터베이스보다 적합한 선택입니다. DynamoDB와 Cassandra는 각각의 장점이 있지만, 소규모 프로젝트에서는 MongoDB가 필요한 유연성과 개발 편의성을 모두 제공하므로 적합하다고 판단되었습니다.
'우리 지금 만나' 카테고리의 다른 글
1대1 채팅 시퀸스 다이어그램 정리-(10)(우리 지금 만나) (2) | 2024.11.28 |
---|---|
채팅 시스템 성능 개선-(9)(우리 지금 만나) (0) | 2024.11.17 |
인프라 난항2-(7)(우리 지금 만나) (2) | 2024.11.03 |
소모임 단건 조회에 RedisLimiter를 적용 후 Jmeter 테스트-(6)(우리 지금 만나) (0) | 2024.10.30 |
소모임 다건 목록 Redis 적용 후 Jmeter 테스트 정리-(5)(우리 지금 만나) (0) | 2024.10.30 |