Kafka + Stomp + Kotlin을 사용한 채팅 구현(1) - Bockerl편

의혁·2025년 1월 27일
0

[Kafka] 카프카 학습

목록 보기
3/6
post-thumbnail

💡 Kafka와 Stomp과 Kotlin을 사용한 채팅 구현 과정을 기록하여보자!

개요

이번 "다문화 가정 정착 지원 어플리케이션"에서 1대1, 1대다 채팅방 구현을 맡게 되었다.
물론 sse를 통한 알림 서비스를 개발해 본 적이 있긴 하나, 실시간 통신이 필요한 채팅 서비스는 구현해본 적이 없었기 때문에, 신나는 마음으로 맡게 되었다.


🤔 Why Websocket?

💡 채팅 서버 메시지 처리 방식 ( Http vs Websocket )

채팅 서비스를 구현하기 위해서는 "실시간 통신"이 중요하다.
실시간 통신 방식은 일반적으로 Http 방식과 Websocket 방식이 존재한다.
이 두가지 방식을 비교해보고, 우리 프로젝트와 적합한 방식을 채택하고자 한다.

1. HTTP 방식 ( connectless )

1) Polling 방식

  • 가장 기본적인 메시징 처리 방식
  • 브라우저(Client)가 일정한 시간마다 서버에 Request를 보내어 새로운 메시지나 데이터를 확인하는 방식
  • 서버는 Request가 들어오는 시점의 데이터를 브라우저(Client)에게 보낸다.

장점

  • Connectionless이므로, 필요할 때만 전송하기 떄문에 서버 리소스가 절약

단점

  • 일정한 주기마다 요청을 보내는 것이므로, 연결 지연 발생 (실시간성 안좋음)
  • 각자 보는 주기가 달라서 메시지가 다르게 보일 수 있음
  • 서버 부하 증가

2) Long Polling 방식

  • Polling의 서버 부하를 줄이기 위해 나온 방식
  • 브라우저(Client)에게서 Request가 들어오면, 새로운 메시지가 도착할 때까지 Response를 지연시킨다.
  • 새로운 메시지가 도착하면 Server에서 바로 Response를 보내주고, Response를 받은 브라우저는 다시 Request를 보내는 방식을 반복한다.

장점

  • 메시지가 전송되면 response를 보내기 때문에, Polling 방식보다 실시간성 증가

단점

  • 한번에 여러 Client에게 보낼 경우 서버 리소스 증가 (서버 부하 증가)
  • 연결 지연 발생 가능

3) Streaming 방식

  • long polling의 연결 구축시 발생하는 서버 부하를 줄이기 위한 방식
  • 브라우저(Client)가 보낸 Request에 대한 response를 보내기 전에 계속 들어오는 event에 대해서 response를 보내는 방식

장점

  • Long Polling의 문제점 중 하나인 서버 부하가 줄어듬

단점

  • 브라우저(Client)에서 서버로 Request를 보내기가 어려움
  • 실시간 단방향 통신에 주로 사용됨

2. Websocket 방식

  • 브라우저(Client)와 서버가 하나의 Connection을 유지하면서, 실시간으로 데이터를 주고 받는 방식
  • Connection은 하나의 TCP 연결을 통해서 양 방향 통신(전이중-Full Deplex)을 지원한다

장점

  • 실시간성 높음 (통신 연결 지연 거의 X)
  • 서버 리소스 사용 적음
  • 실시간 채팅에 많이 이용됨

단점

  • 서버와 연결이 지속되어야 하므로 서버당 처리할 수 있는 클라이언트의 수가 제한됨

위의 실시간 채팅 메시지 처리 방식을 살펴본 결과, 우리 프로젝트는 1대1 채팅, 1대다 채팅이 모두 존재하고, 채팅에서 매끄러운 실시간 채팅과 리소스 적인 부분에서 절감이 필요하기 때문에 최종적으로 "WebSocket"을 사용하기로 결정하였다.


🤔 Why Stomp?

💡 Websocket vs Stomp

채팅 메시지 방식으로 WebSocket 방식을 채택하였지만, Websocket은 "메시지의 데이터 타입"에 대해서만 2가지(Text,Binary) 형태로 정의하지, "메시지 내용"은 따로 저장하지 않기 때문에, 채팅이 주요 MVP 중에 하나인 채팅 서비스에 만족하기 위해서는 추가적으로 메시지 내용을 저장하는 복잡하 로직 구현이 필요했다.
따라서, 이러한 사항을 해결하기 위해서 "메시지 브로커"를 이용하여, 메시지를 효율적으로 전송 및 저장하는 "STOMP"를 사용하기로 결정하였다.

1) Stomp란?

  • Simple Text Oriented Messaging Protocol(STOMP)
  • 메시징 시스템 간에 데이터를 교환하기 위한 텍스트 기반 프로토콜
  • Websocket 보다 한 단계 고수준의 프로토콜

2) Stomp의 기능

  • Pub/Sub 구조
    - Stomp는 Pub/Sub구조로 사용자가 원하는 주제나 채널에 대해서 구독(subscribe)을 할 수 있고, 발행자(서버)는 구독 정보에 맞게 메시지를 전송한다.

  • 헤더 기반 메시징
    - 헤더와 바디로 구성되어 있으며, 헤더를 통해 메시지의 라우팅, 우선순위, 유효성 등을 관리할 수 있다

  • 메시지 브로커와의 통합
    - In Memory 기반(휘발성)이므로, 종료되거나, 전원이 나가게 되면 메시지 정보가 모두 사라지는 단점을 보완하기 위한 "외부 메시지 브로커"와의 호환성이 뛰어나다.

  • 크로스-플래폼과의 호환성
    - STOMP 클라이언트 라이브러리는 다양한 프로그래밍 언어 및 플랫폼에서 사용할 수 있다


🤔 Why Kafka?

외부 메시지 브로커는 여러가지 종류가 존재하고, Rabbit MQ, Redis Queue, Kafka 중에서 우리 프로젝트는 채팅이 많이 발생하기도 하고, 1대1 채팅방과 1대다 채팅방 모두 구현하여야 함으로, 대용량 트래픽 처리가 용이한 "KafKa"를 선정하게 되었습니다.
또한, Kafka는 메시지 로그 유지와 재생 가능성이라는 장점이 있어, 시스템 안정성과 장애 복구 측면에서 유리하다는 장점이 있기 떄문에 안정적인 메시지 처리와 확장성을 위해서 선정하게 되었습니다.

Kafka에 대한 개념 정리는 카프카 개념 정리에 따로 정리해 두었습니다.


🤔 Why MongoDB & PostgreSQL?

채팅 시스템에 필요한 데이터베이스 저장공간은 2가지를 선정하였습니다. 채팅 기록을 저장할 MongoDB와 채팅방 기록을 저장할 PostgreSQL을 사용하기로 채택하였습니다.

1) MongoDB

  • MongoDB는 NoSQL로 빈번히 발생하는 읽기/쓰기 작업에 적합한 DB이다.
  • 채팅 내역은 빈번하게 수정되고, 대용량으로 처리가 되는 비정형 데이터이므로, MongoDB가 적합하다.

2) PostgreSQL

  • 기존 프로젝트에서 사용하는 데이터 베이스가 "PostgreSQL"이기 때문에, 회원이나 게시글과 같은 도메인들과의 관계를 맺기 위해서는 기존에 사용하는 RDBMS를 통해 채팅방 정보를 저장한다.

참조 블로그
Websocket & Stomp: https://brunch.co.kr/@springboot/695
채팅 기반 기술 비교: https://yenjjun187.tistory.com/996

profile
매일매일 차근차근 나아가보는 개발일기

0개의 댓글