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]
↓
[큐에 전달된 메시지 소비]
↓
[웹소켓 서버에서 메시지 수신]
↓
[웹소켓을 통해 클라이언트에 실시간 전송]
구현 흐름 예시
- 웹소켓 서버가 MQ의 특정 큐를 소비자(Consumer)로 등록
- MQ에 메시지가 도착하면 웹소켓 서버에서 이를 수신
- 웹소켓 세션을 통해 클라이언트에게 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와 웹소켓을 결합하면 높은 확장성과 유연성을 확보할 수 있다.
'Back-End' 카테고리의 다른 글
| 금융기관 API에서 사용하는 Signed JWT + RFC8785 메시지 서명 구조 정리 (0) | 2026.02.25 |
|---|---|
| jstat로 JVM 메모리 모니터링: 실무용 해석 가이드 (3) | 2025.08.12 |
| 웹소켓 정리 2 (0) | 2025.05.07 |
| 웹소켓 정리 (1) | 2025.05.06 |
| exitCode (0) | 2024.11.21 |