이전에 작업했던 'SNS' 프로젝트에 1 대 1 채팅 기능을 추가하려 합니다. 채팅 시스템을 어떻게 구축할지 고민하던 중 Kafka, STOMP, MongoDB, WebSocket 같은 기술들을 접하게 되었는데, 흥미로운 점은 이 중 한 번도 사용해본 적이 없는 기술들이라는 것입니다. 하지만 이번 기회를 통해 이들을 활용하여 프로젝트를 더 발전시켜보고자 합니다.
WebSocket은 HTML5 표준 기술로, 클라이언트와 서버 간에 하나의 TCP 연결을 통해 실시간 전이중 통신을 가능하게 하는 프로토콜입니다. WebSocket이 등장하기 전까지는 Polling이나 Long Polling 방식으로 실시간에 가까운 통신을 구현했지만, 이는 한계가 분명했습니다.
WebSocket이 등장하면서, 클라이언트와 서버 간 실시간 통신이 가능해졌습니다. HTTP 통신에서는 단방향 요청만 가능했지만, WebSocket을 통해 양방향 통신이 가능해졌습니다. 클라이언트와 서버가 지속적으로 연결되어 서로 데이터를 주고받는 시대가 열린 것입니다.
WebSocket은 기본적으로 두 가지 메시지 유형(텍스트, 바이너리)만 정의하고, 메시지 내용은 정의하지 않습니다. 여기서 등장한 것이 STOMP입니다. STOMP는 메시지 전송을 효율화하기 위한 프로토콜로, 기본적으로 pub/sub 구조를 따릅니다. 메시지를 전송하고 처리하는 구조가 명확하여 채팅 시스템 구현에 적합한 장점을 가지고 있습니다.
STOMP를 사용하여 채팅 시스템을 구축하면, 주로 아래의 두 가지 행동이 가능합니다.
STOMP를 사용하여 채팅 기능을 구현하면 다음과 같은 이점을 얻을 수 있습니다.
💡 WebSocket과 STOMP는 양방향 통신을 제공하지만, STOMP는 메시지 전송을 보다 효율적으로 관리할 수 있는 프로토콜입니다.
제가 구현하려는 기능은 채팅 시스템입니다. WebSocket으로도 구현은 가능하지만, 세션을 관리하고, 각 채팅방에 접속한 사용자를 파악해야 하는 번거로움이 있습니다. 반면, STOMP를 사용하면 사용자가 채팅방을 구독하는 순간 모든 관련 메시지가 구독된 사용자에게 자동으로 전달됩니다. 이런 이유로, 채팅 시스템 구현에는 STOMP가 더 적합하다고 판단하여 STOMP를 선택했습니다.
메시지 큐를 떠올리면 두 가지 대표적인 솔루션이 있습니다: Kafka와 RabbitMQ. 둘은 비슷한 목적을 가지고 있지만, 작동 방식과 사용 사례에서 차이가 있습니다.
RabbitMQ는 가장 널리 사용되는 메시지 브로커 중 하나로, Publisher-Consumer 구조에서 메시지를 큐에 저장하고 소비자가 가져가는 방식을 사용합니다. 이때 메시지는 처리 후 삭제되며, 주로 트래픽이 크지 않은 상황에서 활용됩니다. 다만, 수평 확장성이 떨어지고, 한 번 처리된 메시지를 다시 재생할 수 없다는 단점이 있습니다.
Kafka는 이벤트 스트리밍 플랫폼으로, RabbitMQ와 달리 이벤트 로그를 저장하여 필요에 따라 메시지를 재생할 수 있는 기능을 제공합니다. 이벤트가 발생하면 이를 레코드 로그로 기록하고, consumer가 데이터를 처리한 이후에도 로그는 유지됩니다. 이는 문제가 발생했을 때 다시 이벤트를 재생할 수 있는 강력한 기능을 제공합니다. Kafka는 분산 시스템에서 더 높은 확장성과 유연성을 제공하며, 대규모 트래픽을 처리할 때 적합합니다.
💡 Kafka는 메시지를 재생할 수 있는 이벤트 로그를 제공하여, 장애 발생 시에도 복구가 용이합니다.
이번 프로젝트는 고도의 트래픽이 예상되지는 않지만, 안정성과 확장성을 고려한 메시지 처리 시스템이 필요했습니다. Kafka는 메시지 로그 유지와 재생 가능성이라는 장점이 있어, 시스템 안정성과 장애 복구 측면에서 유리하다고 판단했습니다.
따라서, Kafka를 선택하여 안정적인 메시지 처리와 확장성을 대비했습니다. RabbitMQ는 더 간단하고 빠르게 구축할 수 있지만, 장기적으로 Kafka가 유연성과 안정성에서 더 적합하다고 결론을 내렸습니다.
채팅 시스템의 채팅 내역 저장소로는 두 가지 옵션을 고민했습니다: MongoDB와 MySQL. 결론적으로, 채팅방 정보는 MySQL, 채팅 기록은 MongoDB로 분리하여 사용하기로 결정했습니다.
채팅방 자체는 관계형 데이터가 필요한 부분입니다. 예를 들어, 회원과 채팅방 간의 관계를 다루어야 하며, 이를 통해 JOIN 연산이 필요할 수 있습니다. 특히, 회원이 채팅방 리스트를 조회할 때는 MySQL을 사용하는 것이 더 적합합니다.
💡 MongoDB는 대규모 채팅 내역 저장에 적합하고, MySQL은 관계형 데이터 관리에 강점을 가집니다.
따라서, 채팅방 정보는 MySQL에 저장하고, 채팅 내역은 MongoDB로 관리하는 방식으로 두 가지 DB의 강점을 최대한 활용하기로 결정했습니다.