Categories: Camel프레임워크

[Camel in Action] 2-5. Recipient List와 동적 라우팅 패턴

Recipient List – 동적 수신자 목록

Recipient List 패턴은 메시지를 받아야 할 대상 목록을 런타임에 동적으로 결정합니다. 발행/구독 패턴의 유연한 변형으로, 각 메시지마다 다른 수신자 집합을 가질 수 있습니다.

기본 Recipient List 구현

from("direct:distribute")
    // 헤더에서 수신자 목록 읽기 (콤마로 구분)
    .recipientList(header("recipients"))
    .delimiter(",");  // 기본값은 콤마

// 예: header("recipients") = "direct:billing,direct:inventory,direct:crm"
// → 세 곳 모두에 메시지 전달

Bean으로 수신자 목록 계산

@Component
public class RecipientCalculator {
    public List<String> calculateRecipients(Exchange exchange) {
        Order order = exchange.getIn().getBody(Order.class);
        List<String> recipients = new ArrayList<>();

        recipients.add("direct:inventory");    // 항상 재고 확인
        if (order.getAmount() > 500000) {
            recipients.add("direct:fraudCheck");   // 고액 주문 사기 검사
        }
        if (order.isOverseas()) {
            recipients.add("direct:customsClearance"); // 해외 통관
        }
        return recipients;
    }
}

// 라우트에서 사용
from("direct:newOrder")
    .recipientList(bean(RecipientCalculator.class, "calculateRecipients"))
    .parallelProcessing();

병렬 처리와 집계

from("direct:orderCheck")
    .recipientList(constant("direct:inventoryCheck,direct:creditCheck,direct:addressCheck"))
    .parallelProcessing()           // 병렬 실행
    .aggregationStrategy(new OrderCheckAggregator())  // 결과 집계
    .timeout(5000);                 // 5초 타임아웃

// 집계 전략
public class OrderCheckAggregator implements AggregationStrategy {
    @Override
    public Exchange aggregate(Exchange oldEx, Exchange newEx) {
        if (oldEx == null) return newEx;
        // 결과 합치기
        String combined = oldEx.getIn().getBody(String.class)
            + "," + newEx.getIn().getBody(String.class);
        oldEx.getIn().setBody(combined);
        return oldEx;
    }
}

@RecipientList 어노테이션

Bean 메서드에 어노테이션을 달아 더 간결하게 구현할 수 있습니다.

@Component
public class OrderRouter {

    @RecipientList
    public String[] route(@Header("orderType") String type,
                          @Body Order order) {
        if ("EXPRESS".equals(type)) {
            return new String[]{"direct:express", "direct:notify"};
        }
        return new String[]{"direct:standard"};
    }
}

// 라우트
from("direct:order")
    .bean(OrderRouter.class);

stopOnException 옵션

from("direct:notify")
    .recipientList(header("subscribers"))
    .stopOnException()   // 하나라도 실패하면 중단
    .ignoreInvalidEndpoints();  // 잘못된 URI는 무시

Recipient List vs Multicast 차이점

  • Multicast: 컴파일 시점에 수신자가 고정됨
  • Recipient List: 런타임에 메시지 내용을 보고 수신자 결정
  • Dynamic Router: 각 수신자 처리 후 다음 수신자를 동적으로 결정 (상태 기반)

Wire Tap으로 감사 추적

from("direct:processPayment")
    .wireTap("direct:auditTrail")   // 감사 로그 비동기 복사
        .newExchangeBody(simple("결제 요청: ${body.paymentId} 금액: ${body.amount}"))
    .to("direct:executePayment")

from("direct:auditTrail")
    .to("jms:queue:audit-log");

zerg96

Share
Published by
zerg96

Recent Posts

[Apache Camel] 2025년 최신 트렌드 – AI 통합과 서버리스 Camel의 미래

2025년 Apache Camel의 최신 트렌드를 분석합니다. AI/LLM 통합 컴포넌트, 서버리스 배포, Camel K 진화, WebAssembly…

11시간 ago

[Camel in Action] 완결편 – Apache Camel 전체 여정 회고와 다음 단계

Camel in Action을 완독한 후 Apache Camel의 전체 그림을 다시 정리합니다. 핵심 철학, 학습 경로,…

11시간 ago

[Camel in Action] 실전편 – Camel 마이그레이션 가이드 2.x에서 4.x까지

Apache Camel 2.x에서 3.x, 4.x로 마이그레이션하는 단계별 가이드입니다. 주요 API 변경사항, 제거된 컴포넌트, 자동화 도구…

11시간 ago

[Camel in Action] 실전편 – Camel 라우트 디버깅 기법과 문제 해결 가이드

Apache Camel 라우트에서 발생하는 문제를 디버깅하고 해결하는 실전 기법을 설명합니다. 로그 분석, breakpoint 디버깅, Tracer,…

11시간 ago

[Camel in Action] 실전편 – Camel 도입 전 반드시 알아야 할 것들

Apache Camel을 프로젝트에 도입하기 전 알아야 할 핵심 사항을 정리합니다. 학습 곡선, 도입 비용, 적합한…

11시간 ago

[Camel in Action] 실전편 – Enterprise Integration Patterns 20가지 핵심 정리

엔터프라이즈 통합 패턴(EIP) 20가지를 Apache Camel 코드와 함께 한 번에 정리합니다. 메시징 채널, 메시지 라우팅,…

11시간 ago