Rabbit MQ + STOMP를 이용한 1:1 채팅

Zoonmy·2025년 4월 2일
post-thumbnail

🚀 차자바 1:1 채팅 서비스 구현기

1. 차자바 1:1 채팅 서비스 구현 🛠️

차자바 프로젝트에서 1:1 채팅 서비스를 개발하면서, 단순한 웹소켓을 넘어서 보다 안정적이고 효율적인 실시간 메시징 시스템을 구축하고자 했습니다.

처음에는 STOMP(WebSocket)만을 사용하여 채팅 기능을 구현했지만, 메시지의 손실과 관리의 어려움이 발생했습니다. 이에 따라 메시지 브로커를 도입해야겠다고 판단하였고, 최종적으로 STOMP + RabbitMQ 조합을 선택하여 채팅 시스템을 구축하였습니다.


2. STOMP + RabbitMQ를 선택한 이유 🤔

🔹 STOMP를 선택한 이유

  1. 웹소켓을 보다 간편하게 사용

    • STOMP는 웹소켓을 기반으로 한 텍스트 기반 메시징 프로토콜로, HTTP 요청처럼 메시지를 주고받을 수 있도록 지원합니다.
    • 단순한 웹소켓의 send() 및 onmessage() API만으로는 복잡한 채팅 로직을 구현하기 어려웠기 때문에, STOMP를 도입하여 프레임워크 차원에서 체계적인 메시징 시스템을 구현했습니다.
  2. 여러 목적지를 설정할 수 있음

    • /topic, /queue 등의 목적지를 활용하여 1:1 채팅과 그룹 채팅을 유연하게 처리할 수 있습니다.
    • STOMP는 Publish/Subscribe 패턴을 지원하여, 특정 사용자 또는 특정 그룹에게 메시지를 전달하는 기능을 쉽게 구현할 수 있었습니다.
  3. 백엔드와 프론트엔드의 손쉬운 연동

    • STOMP는 Spring WebSocket과 함께 사용하기에 적합하며, 클라이언트에서도 SockJS와 연동하여 안정적인 연결을 유지할 수 있었습니다.

🔹 RabbitMQ를 선택한 이유

  1. 메시지의 안정적인 저장과 전달

    • STOMP 단독으로 사용했을 때는 클라이언트가 오프라인 상태일 경우 메시지가 유실될 위험이 있었습니다.
    • RabbitMQ를 추가하여 비동기 메시지 처리를 가능하게 하고, 클라이언트가 다시 연결되었을 때 누락된 메시지를 안전하게 전달할 수 있도록 했습니다.
  2. 메시지 큐잉을 활용한 부하 분산

    • 대량의 채팅 요청이 발생할 경우, RabbitMQ의 큐잉 시스템을 활용하여 부하를 분산시킬 수 있습니다.
    • 특정 사용자에게 집중되는 메시지를 효율적으로 처리하고, 서버의 부담을 최소화할 수 있도록 설계했습니다.
  3. 다양한 메시지 브로커와의 확장성

    • RabbitMQ는 향후 Kafka 등 다른 메시지 브로커로 확장이 용이하기 때문에, 프로젝트의 확장성을 고려하여 선택했습니다.

3. 구현 방법 및 코드 설명 💻

1️⃣ WebSocket 설정 (STOMP 적용)

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        registry.addEndpoint("/ws").setAllowedOrigins("*").withSockJS();
    }

    @Override
    public void configureMessageBroker(MessageBrokerRegistry registry) {
        registry.enableSimpleBroker("/queue", "/topic");
        registry.setApplicationDestinationPrefixes("/app");
    }
}
  • registerStompEndpoints: 클라이언트가 WebSocket을 연결할 수 있는 엔드포인트 등록
  • enableSimpleBroker: 메시지를 전달할 수 있는 목적지 설정 (1:1 채팅은 /queue, 그룹 채팅은 /topic)

2️⃣ 메시지 전송 및 RabbitMQ 연동

@Component
public class ChatMessageListener {
    private final SimpMessagingTemplate messagingTemplate;

    @RabbitListener(queues = "chat.queue")
    public void receiveMessage(ChatMessage message) {
        messagingTemplate.convertAndSendToUser(
            message.getReceiver(), "/queue/messages", message
        );
    }
}
  • RabbitMQ의 @RabbitListener를 통해 메시지를 수신하고, 이를 STOMP를 통해 해당 사용자에게 전달
  • 메시지를 안전하게 큐잉하고 전달할 수 있도록 설계

4. 부가적인 흐름도 🖼️

1. 사용자 흐름

2. 관리자 흐름

3. 전체적인 서비스 흐름도


5. 결론 및 향후 개선 방안 ✏️

🔧 향후 개선 방안

  1. Spring Batch 도입
    • 채팅 데이터를 일정 주기로 배치 처리하여 데이터베이스 부하를 줄이고 성능을 개선할 계획입니다.
  2. Redis 캐시 활용
    • 자주 조회되는 채팅 데이터를 Redis에 저장하여, 조회 속도를 향상시키고 서버 부하를 줄일 예정입니다.
  3. Kafka 도입 검토
    • RabbitMQ보다 더 높은 확장성과 성능을 제공하는 Kafka를 도입하여, 대규모 트래픽 처리를 더욱 최적화할 계획입니다.

6. 결론 및 마무리 🚀

이번 프로젝트를 통해 실시간 채팅 시스템을 구축하며, STOMP와 RabbitMQ를 활용한 비동기 메시징 시스템의 중요성을 배울 수 있었습니다.

💡 배운 점

  • WebSocket과 STOMP를 활용한 실시간 메시징 원리를 이해할 수 있었습니다.
  • RabbitMQ를 통해 메시지의 안정적인 전달과 부하 분산이 가능함을 경험했습니다.
  • STOMP와 메시지 브로커를 조합하여 확장성 있는 채팅 시스템을 구축하는 방법을 학습할 수 있었습니다.

향후 Redis, Spring Batch, Kafka 등의 기술을 추가로 도입하여 더욱 안정적이고 효율적인 실시간 채팅 시스템을 완성해 나가고자 합니다. 🚀

profile
열시미 해야쥐

0개의 댓글