본문 바로가기

Back-End

실시간 데이터 처리를 위한 RabbitMQ 설계와 웹소켓 연동

반응형

RabbitMQ는 단순 메시지 큐잉 시스템을 넘어서, 다양한 메시지 라우팅 방식과 실시간 시스템 설계에 강력한 도구로 활용된다.

특히 웹소켓 기반 실시간 UI와 함께 사용할 때 높은 시너지를 낸다.

이 글에서는 RabbitMQ의 주요 동작 방식들과 웹소켓과의 연동 방법에 대해 정리한다.

 

1. RabbitMQ 기본 구조 다시 보기

RabbitMQ의 구성요소는 다음과 같다:

  • Producer: 메시지를 발행하는 주체
  • Exchange: 메시지를 수신받아 규칙에 따라 특정 큐로 전달
  • Queue: 메시지를 저장하고 소비자를 기다리는 공간
  • Consumer: 큐로부터 메시지를 꺼내 처리하는 주체

Producer → Exchange → Queue → Consumer
이 구조를 바탕으로, Exchange의 타입에 따라 메시지가 큐로 라우팅되는 방식이 달라진다.

 

2. Exchange 타입과 메시지 라우팅 방식

RabbitMQ의 핵심은 바로 Exchange 타입이다. 이 타입에 따라 메시지가 어느 큐로 가는지가 결정된다.

(1) Direct Exchange

  • 정확한 라우팅 키 일치에 따라 큐에 전달
  • 사용 예: "order.created" 라는 키로 메시지를 보내면, 이 키로 바인딩된 큐만 메시지를 받는다
Exchange: direct
Routing Key: user.signup
Queue: userQueue (바인딩 키: user.signup)

(2) Topic Exchange

  • 와일드카드(*, #)를 이용한 패턴 매칭
  • 다양한 주제를 계층 구조처럼 구성할 수 있음
Exchange: topic
Routing Key: log.error.database
Queue: dbQueue (바인딩 키: log.#)
Queue: errorQueue (바인딩 키: *.error.*)
  • *: 한 단어
  • #: 0개 이상의 단어

(3) Fanout Exchange

  • 모든 바인딩된 큐에 브로드캐스트 전송
  • 라우팅 키 무시
  • 주로 공지, 시스템 이벤트 방송에 적합
Exchange: fanout
→ Queue A, Queue B, Queue C 모두 같은 메시지를 수신

(4) Headers Exchange

  • 헤더 값으로 큐를 선택 (실무에서는 거의 사용되지 않음)

 

3. RabbitMQ와 웹소켓 연동 구조

RabbitMQ는 비동기 메시징 시스템이고, 웹소켓은 양방향 통신 채널이다.
이 둘을 함께 사용하면 다음과 같은 실시간 처리 흐름을 만들 수 있다.

[외부 시스템 or 서비스] -- 메시지 발행 --> [RabbitMQ Exchange]
                                       ↓
                            [큐에 전달된 메시지 소비]
                                       ↓
                            [웹소켓 서버에서 메시지 수신]
                                       ↓
                       [웹소켓을 통해 클라이언트에 실시간 전송]

구현 흐름 예시

  1. 웹소켓 서버가 MQ의 특정 큐를 소비자(Consumer)로 등록
  2. MQ에 메시지가 도착하면 웹소켓 서버에서 이를 수신
  3. 웹소켓 세션을 통해 클라이언트에게 push

웹소켓과 MQ를 연결하는 핵심은 MQ 메시지를 소비하는 프로세스와 웹소켓 세션 관리 로직을 분리하지 않는 것이다.

 

4. 기술 선택과 구조 설계 시 고려할 점

큐 설계 시 고려 사항

  • 큐 이름을 정적/동적으로 설계할지 결정
    예: 고정된 큐(subtitle.queue) vs. 특정 사용자나 주제 기반 큐(subtitle.user.1234)
  • 큐 수가 많아지면 메모리 사용량 증가 → 서버 리소스 고려 필요
  • 큐를 Auto-delete / Expire 처리할 수 있는 정책 설정 가능 → 일시적 사용자 구독 처리에 유용

웹소켓 서버 구현 팁

  • Spring Boot의 경우 @RabbitListener를 통해 메시지를 수신하고, 이를 WebSocketSession에 직접 전달
  • 세션 관리는 ConcurrentMap<String, WebSocketSession> 형태로 관리
  • 사용자별 세션을 매핑할 수 있다면, MQ 메시지에서 sessionId나 사용자 ID를 추출하여 해당 세션으로 메시지 push

 

5. 간단한 Spring Boot 연동 예시

@Component
public class NotificationConsumer {

    private final SimpMessagingTemplate messagingTemplate;

    public NotificationConsumer(SimpMessagingTemplate messagingTemplate) {
        this.messagingTemplate = messagingTemplate;
    }

    @RabbitListener(queues = "notification.queue")
    public void receive(String message) {
        // 클라이언트에게 실시간 전송
        messagingTemplate.convertAndSend("/topic/notification", message);
    }
}

위 코드는 메시지를 받자마자 웹소켓(/topic/notification)으로 바로 전달하는 구조이다.

 

 

RabbitMQ는 단순한 큐 시스템이 아니다.
Exchange, Queue, Routing Key를 유연하게 조합하면 복잡한 라우팅과 실시간 처리까지 가능하다.
특히 웹소켓과 함께 사용할 경우, MQ를 통해 비동기로 수신하고, 웹소켓으로 실시간으로 사용자에게 전달하는 구조는 실무에서 매우 유용하다.

  • 실시간 알림
  • 스트리밍 자막
  • 분산 환경에서의 이벤트 전파
  • 시스템 상태 변화 전달

이러한 다양한 목적에 맞게 RabbitMQ와 웹소켓을 결합하면 높은 확장성과 유연성을 확보할 수 있다.

반응형