
💡 Kafka와 Stomp과 Kotlin을 사용한 채팅 구현 과정을 기록하여보자!
이번 "다문화 가정 정착 지원 어플리케이션"에서 1대1, 1대다 채팅방 구현을 맡게 되었다.
물론 sse를 통한 알림 서비스를 개발해 본 적이 있긴 하나, 실시간 통신이 필요한 채팅 서비스는 구현해본 적이 없었기 때문에, 신나는 마음으로 맡게 되었다.
💡 채팅 서버 메시지 처리 방식 ( Http vs Websocket )
채팅 서비스를 구현하기 위해서는 "실시간 통신"이 중요하다.
실시간 통신 방식은 일반적으로 Http 방식과 Websocket 방식이 존재한다.
이 두가지 방식을 비교해보고, 우리 프로젝트와 적합한 방식을 채택하고자 한다.

장점
단점

장점
단점

장점
단점

장점
단점
위의 실시간 채팅 메시지 처리 방식을 살펴본 결과, 우리 프로젝트는 1대1 채팅, 1대다 채팅이 모두 존재하고, 채팅에서 매끄러운 실시간 채팅과 리소스 적인 부분에서 절감이 필요하기 때문에 최종적으로 "WebSocket"을 사용하기로 결정하였다.
💡 Websocket vs Stomp
채팅 메시지 방식으로 WebSocket 방식을 채택하였지만, Websocket은 "메시지의 데이터 타입"에 대해서만 2가지(Text,Binary) 형태로 정의하지, "메시지 내용"은 따로 저장하지 않기 때문에, 채팅이 주요 MVP 중에 하나인 채팅 서비스에 만족하기 위해서는 추가적으로 메시지 내용을 저장하는 복잡하 로직 구현이 필요했다.
따라서, 이러한 사항을 해결하기 위해서 "메시지 브로커"를 이용하여, 메시지를 효율적으로 전송 및 저장하는 "STOMP"를 사용하기로 결정하였다.

Pub/Sub 구조
- Stomp는 Pub/Sub구조로 사용자가 원하는 주제나 채널에 대해서 구독(subscribe)을 할 수 있고, 발행자(서버)는 구독 정보에 맞게 메시지를 전송한다.
헤더 기반 메시징
- 헤더와 바디로 구성되어 있으며, 헤더를 통해 메시지의 라우팅, 우선순위, 유효성 등을 관리할 수 있다
메시지 브로커와의 통합
- In Memory 기반(휘발성)이므로, 종료되거나, 전원이 나가게 되면 메시지 정보가 모두 사라지는 단점을 보완하기 위한 "외부 메시지 브로커"와의 호환성이 뛰어나다.
크로스-플래폼과의 호환성
- STOMP 클라이언트 라이브러리는 다양한 프로그래밍 언어 및 플랫폼에서 사용할 수 있다
외부 메시지 브로커는 여러가지 종류가 존재하고, Rabbit MQ, Redis Queue, Kafka 중에서 우리 프로젝트는 채팅이 많이 발생하기도 하고, 1대1 채팅방과 1대다 채팅방 모두 구현하여야 함으로, 대용량 트래픽 처리가 용이한 "KafKa"를 선정하게 되었습니다.
또한, Kafka는 메시지 로그 유지와 재생 가능성이라는 장점이 있어, 시스템 안정성과 장애 복구 측면에서 유리하다는 장점이 있기 떄문에 안정적인 메시지 처리와 확장성을 위해서 선정하게 되었습니다.
Kafka에 대한 개념 정리는 카프카 개념 정리에 따로 정리해 두었습니다.
채팅 시스템에 필요한 데이터베이스 저장공간은 2가지를 선정하였습니다. 채팅 기록을 저장할 MongoDB와 채팅방 기록을 저장할 PostgreSQL을 사용하기로 채택하였습니다.
참조 블로그
Websocket & Stomp: https://brunch.co.kr/@springboot/695
채팅 기반 기술 비교: https://yenjjun187.tistory.com/996