브로커 내부의 'Routing Type' 결정 시점은?
ActiveMQ Artemis와 같은 모던 메시지 브로커 환경에서 주소(Address)와 큐(Queue)가 1:N으로 분리됨에 따라, 메시지가 1:1로 전달될지(Anycast) 아니면 1:N으로 복제될지(Multicast)를 결정하는 라우팅 타입(Routing Type)의 중요성이 극대화되었습니다.
시스템을 운영하다 보면 "생산자는 Queue라고 생각하고 보냈는데 브로커에서는 Topic처럼 동작한다"거나, "클라이언트가 접속할 때마다 라우팅 타입 충돌 에러가 발생한다"는 이슈를 자주 접하게 됩니다. 이는 라우팅 타입이 브로커 내부에서 어느 시점에, 누구의 주도권으로 결정되는지 정확히 파악하지 못했기 때문입니다.
라우팅 타입이 결정되는 3가지 핵심 시점과 그 내부의 우선순위 판별 기준을 상세히 분석합니다.

1. 브로커 기동 시점: 정적 설정(Static Configuration)에 의한 확정
라우팅 타입이 결정되는 가장 명확하고 원초적인 시점은 브로커가 기동(Startup)될 때입니다. 관리자가 broker.xml 파일에 명시적으로 Address와 Queue를 선언해 두었다면, 브로커는 메모리에 해당 객체들을 생성할 때 라우팅 타입을 고정합니다.
- 결정 주체: 브로커 관리자 (인프라 설정)
- 동작 방식:
<address>태그 하위에<anycast>또는<multicast>태그를 명시합니다. - 특징: 브로커에 가장 강력한 통제권이 부여됩니다. 정적으로 선언된 Address에 클라이언트가 접근할 경우, 클라이언트는 반드시 브로커에 설정된 라우팅 타입을 따라야 합니다. 만약 정적 설정과 다르게 접근하려고 시도하면 브로커는 클라이언트의 연결을 거부하거나 예외를 발생시킵니다. 인프라의 안정성을 최우선으로 해야 하는 Amazon MQ 프로덕션 환경 등에서 가장 권장되는 접근법입니다.
2. 생산자/소비자 접속 시점: 클라이언트 프로토콜에 의한 동적 요청 (Runtime)
클라이언트가 메시지를 보내거나(Produce) 받기 위해(Consume) 브로커에 연결 세션을 맺는 런타임 시점에도 라우팅 타입이 결정될 수 있습니다. 브로커에 사전 정의된 주소가 없는 상황에서 클라이언트가 접근할 때 이 메커니즘이 작동합니다.
- 결정 주체: 연결을 시도하는 클라이언트 애플리케이션 및 사용 중인 통신 프로토콜
- 프로토콜별 유추 기준:
- JMS (Java Message Service): 클라이언트가 사용하는 객체가
javax.jms.Queue인지javax.jms.Topic인지에 따라 브로커는 자동으로 Anycast 또는 Multicast를 결정합니다. 명시적으로queue://또는topic://접두사를 JNDI 설정에 포함하여 의도를 전달하기도 합니다. - AMQP (Advanced Message Queuing Protocol): AMQP 1.0 규격에 따라 접속 시 타겟 노드의 기능을 정의하는
Terminus객체의 속성(capabilities)을 검사합니다.queuecapability가 명시되어 있으면 Anycast로,topiccapability가 있으면 Multicast로 라우팅 타입을 판단합니다. - MQTT: 프로토콜 자체의 본질이 Pub/Sub 아키텍처이므로, 브로커는 MQTT 클라이언트가 생성하는 모든 주소와 구독을 기본적으로 Multicast 라우팅 타입으로 확정하여 처리합니다.
3. 브로커의 자동 생성(Auto-Creation) 개입 시점: 최후의 판단 (Fallback)
클라이언트가 메시지를 전송했는데 해당 Address가 broker.xml에 정적으로 존재하지 않고, 클라이언트의 프로토콜 단에서도 명확한 라우팅 타입 힌트(예: 단순 텍스트 기반의 STOMP 통신에서 대상 지정 없이 전송)를 주지 않은 모호한 상황이 발생할 수 있습니다.
이때 브로커는 주소 자동 생성(Auto-creation) 프로세스를 시작하며, 브로커의 기본 폴백(Fallback) 설정에 따라 라우팅 타입을 최종 결정합니다.
- 결정 주체: 브로커의 주소 설정(Address Settings) 정책
- 동작 방식:
broker.xml의<address-setting>블록 내에 정의된default-address-routing-type및default-queue-routing-type값을 참조합니다. - 주의사항: 만약 이 값이
MULTICAST로 기본 설정되어 있는데, 개발자는 Point-to-Point 통신을 기대하고 프로토콜 힌트 없이 메시지를 보냈다면, 브로커는 해당 주소를 Multicast로 자동 생성합니다. 이 경우 소비자가 접속하지 않았을 때 메시지가 큐에 쌓이지 않고 그대로 증발해버리는 심각한 데이터 유실 사고로 이어질 수 있습니다.
4. 결정 계층의 우선순위 및 충돌 해소 기준
실제 엔터프라이즈 통신 환경에서는 위 3가지 시점이 복합적으로 얽혀 동작합니다. 브로커 내부적으로 라우팅 타입을 확정하는 우선순위는 다음과 같습니다.
- 1순위 (절대적 기준): 정적 선언된 브로커 설정. 이미 메모리에 특정 라우팅 타입으로 생성된 주소는 다른 타입으로의 접근을 허용하지 않습니다.
- 2순위 (힌트 기반): 클라이언트의 프로토콜 명시. 주소가 없을 때, 클라이언트가 명확한 타입(예: JMS Queue 객체 사용)을 요구하면 브로커는 그에 맞춰 주소와 큐를 동적으로 자동 생성합니다.
- 3순위 (최후 수단): 브로커의 Default 설정. 어떠한 명시적 단서도 없을 때 브로커가 자체 정책으로 결정합니다.
충돌 시나리오 예방:
가장 빈번하게 발생하는 장애는 "클라이언트의 요청 타입"과 "브로커에 기설정된 타입"이 불일치할 때 발생합니다. 예를 들어 브로커에는 orders 주소가 Anycast로 선언되어 있는데, JMS 클라이언트가 Topic orders = session.createTopic("orders"); 로 접근하려 하면 ActiveMQIllegalStateException 에러가 발생하며 연결이 차단됩니다.
따라서 아키텍처를 설계할 때는 브로커 인프라 설정과 클라이언트 코드를 작성하는 개발팀 간에 "어떤 목적지(Address)가 어떤 라우팅 타입을 가지는지"에 대한 명확한 사전 규약 문서화가 필수적으로 선행되어야 합니다.
'1. 개발 > 1.8. ActiveMQ' 카테고리의 다른 글
| 셀렉터 사용 시 인덱스를 타지 못해 발생하는 성능 저하 정도는? (0) | 2026.03.15 |
|---|---|
| 메시지 셀렉터(Selector)의 SQL-92 구문 지원 범위는? (0) | 2026.03.15 |
| Anycast 라우팅과 Multicast 라우팅의 차이는? (0) | 2026.03.14 |
| Artemis의 'Address'와 'Queue' 관계 (1:N 매핑) 방식은? (0) | 2026.03.14 |
| OpenWire 프로토콜의 바이너리 구조 특성은? (0) | 2026.03.14 |