왜 메시지 큐가 필요한가?
시스템 간 직접 통신은 한쪽이 느려지거나 다운되면 전체가 영향을 받습니다. 메시지 큐를 중간에 두면 생산자와 소비자를 완전히 분리할 수 있습니다. Camel의 JMS 컴포넌트는 ActiveMQ, RabbitMQ, IBM MQ 등 어떤 JMS 브로커와도 동일한 코드로 연동됩니다.
ActiveMQ 기본 연동
Maven에 camel-activemq 의존성을 추가하고 ConnectionFactory를 설정하면 바로 사용할 수 있습니다.
// Spring XML 설정
<bean id="activemq" class="org.apache.activemq.camel.component.ActiveMQComponent">
<property name="brokerURL" value="tcp://localhost:61616"/>
</bean>
// 라우트
from("activemq:queue:orders")
.log("주문 수신: ${body}")
.to("activemq:queue:processed-orders");
큐(Queue)는 한 소비자만 메시지를 받고, 토픽(Topic)은 구독한 모든 소비자가 받습니다. activemq:queue:이름 vs activemq:topic:이름으로 구분합니다.
트랜잭션과 메시지 신뢰성
중요한 메시지는 반드시 트랜잭션 처리가 필요합니다. JMS 컴포넌트는 acknowledgment 모드를 통해 메시지 유실을 방지합니다.
- AUTO_ACKNOWLEDGE: 메시지를 받자마자 확인 (기본값, 빠르지만 처리 중 오류 시 유실 가능)
- CLIENT_ACKNOWLEDGE: 처리 완료 후 직접 확인 (안전)
- transacted=true: JMS 트랜잭션으로 롤백 지원
from("activemq:queue:orders?transacted=true")
.process(exchange -> {
// 처리 중 예외 발생 시 자동 롤백, 메시지 재전송
processOrder(exchange.getIn().getBody(String.class));
});
Dead Letter Queue 패턴
반복해서 실패하는 메시지는 무한 재시도를 막기 위해 Dead Letter Queue(DLQ)로 이동시킵니다. ActiveMQ는 기본적으로 6번 재시도 후 ActiveMQ.DLQ로 보냅니다.
// ActiveMQ 재시도 정책 커스터마이징
<redeliveryPolicy maximumRedeliveries="3" redeliveryDelay="1000"/>
DLQ를 모니터링하면 처리 실패한 메시지를 나중에 수동으로 재처리하거나 원인을 분석할 수 있습니다.
Request-Reply 패턴
동기식 처리가 필요할 때는 JMS의 Request-Reply 패턴을 사용합니다. Camel이 임시 응답 큐를 자동으로 생성해서 관리해 줍니다.
// 요청자
Object response = template.requestBody("activemq:queue:calculate", "10+20");
// 처리자
from("activemq:queue:calculate")
.bean(CalculatorBean.class);
내부적으로 JMS의 replyTo 헤더와 correlationId를 활용하므로, 개발자는 복잡한 메시지 매칭 로직을 직접 구현할 필요가 없습니다.