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

정보보안기사 필기 핵심 개념, 접근통제·인증 8문제로 정리

필기 시험의 접근통제 영역은 용어 하나만 알아도 풀리는 문제와 개념을 뒤집어 묻는 문제가 섞여 나옵니다.…

2시간 ago

유튜브 AI 영상 범람, 진짜 크리에이터는 어떻게 살아남나

유튜브에 AI 자동 생성 영상이 넘쳐납니다. 진짜 크리에이터들은 어떻게 살아남아야 할까요? AI와 경쟁하는 3가지 생존…

3시간 ago

코스피 사이드카 이틀 만에 또 발동, 올해만 27번째…5분간 멈추는 건 ‘프로그램 매도’뿐입니다

이틀 전에 사이드카가 걸렸을 때만 해도 "한 번 놀란 장"으로 끝날 줄 알았는데요. 15일 아침…

4시간 ago

코스피 낙폭 7%로 확대, 외국인 1.7조 순매도: 10월 15일 오전 10시 시황

오전 시황 글에 이어 장중 후속 정리입니다. 코스피는 개장 직후 5%대였던 낙폭이 오전 10시 전후에…

7시간 ago

코스피 5.59% 급락 출발, 개장 7분 만에 매도 사이드카: 10월 15일 오전 시황

10월 15일 목요일 아침, 코스피가 전날 종가보다 5.59% 낮은 5,673.01로 출발했습니다. 장 시작 7분 만에…

7시간 ago

삼성 갤럭시 AI, 솔직히 기대 이하였다 — 실망스러운 이유 TOP 5

삼성 갤럭시 AI, 써보니 실망스러웠다. 온디바이스 한계, 지역 제한, 낮은 일상 활용도 등 현실적인 문제점…

8시간 ago