[Camel in Action] 2-4. Content-Based Router와 Message Filter EIP 구현

Enterprise Integration Patterns (EIP)

Gregor Hohpe와 Bobby Woolf가 정의한 엔터프라이즈 통합 패턴(EIP)은 메시지 기반 통합의 모범 사례들을 패턴으로 정리한 것입니다. Apache Camel은 이 패턴들을 직접 구현합니다. 이번 글에서는 가장 자주 사용되는 두 패턴을 살펴봅니다.

Content-Based Router (CBR) – 내용 기반 라우터

메시지의 내용이나 헤더 값에 따라 다른 목적지로 전달하는 패턴입니다. Camel에서는 choice()로 구현합니다.

from("direct:orderInput")
    .choice()
        .when(simple("${body.orderType} == 'VIP'"))
            .log("VIP 주문: ${body.customerId}")
            .to("direct:vipOrderProcess")
        .when(simple("${body.amount} > 1000000"))
            .log("대용량 주문")
            .to("direct:largeOrderProcess")
        .when(header("region").isEqualTo("OVERSEAS"))
            .to("direct:overseasOrderProcess")
        .otherwise()
            .to("direct:normalOrderProcess")
    .end()
    .log("라우팅 완료");

다양한 조건 표현 방법

// Simple 언어
.when(simple("${header.status} == 'APPROVED'"))

// XPath (XML 메시지)
.when(xpath("/order/status = 'approved'"))

// JSONPath (JSON 메시지)
.when(jsonpath("$.order.status == 'approved'"))

// Java Predicate
.when(exchange -> exchange.getIn().getHeader("amount", Integer.class) > 50000)

// SpEL
.when(spel("#{request.headers['priority'] == 'HIGH'"}))

// 정규식
.when(simple("${body} regex '.*URGENT.*'"))

Message Filter – 메시지 필터

조건을 만족하지 않는 메시지를 완전히 걸러내는 패턴입니다. filter()로 구현합니다.

from("jms:queue:allOrders")
    .filter(simple("${body.amount} >= 10000"))  // 1만원 이상만 처리
        .log("처리 대상 주문: ${body.orderId}")
        .to("direct:processOrder");
// 조건 불만족 메시지는 조용히 버려짐
// 복잡한 필터 조건
from("direct:events")
    .filter(exchange -> {
        String type = exchange.getIn().getHeader("eventType", String.class);
        int priority = exchange.getIn().getHeader("priority", 0, Integer.class);
        return "ORDER".equals(type) && priority > 5;
    })
    .to("direct:highPriorityOrders");

Wiretap – 메시지 복사 감청

원본 흐름을 방해하지 않고 메시지를 다른 경로로 복사해 보내는 패턴입니다. 감사 로그, 모니터링에 유용합니다.

from("direct:orders")
    .wireTap("direct:auditLog")  // 비동기로 감사 로그에 복사
    .to("direct:processOrder");  // 원본 흐름은 계속 진행

from("direct:auditLog")
    .log("감사: ${date:now:yyyy-MM-dd HH:mm:ss} - 주문 ${body.orderId}")
    .to("jms:queue:audit");

Multicast – 동일 메시지를 여러 곳으로

하나의 메시지를 여러 엔드포인트에 동시에 전달합니다.

from("direct:newOrder")
    .multicast()
        .parallelProcessing()
        .to("direct:inventory", "direct:billing", "direct:notification")
    .end()
    .log("모든 처리 완료");

CBR과 Filter 선택 기준

  • CBR 사용: 메시지를 반드시 어딘가로 보내야 할 때, 조건마다 다른 처리 필요
  • Filter 사용: 일부 메시지를 완전히 무시해도 될 때 (이벤트 필터링)
  • Wiretap 사용: 원본 흐름 유지하면서 부가 처리가 필요할 때

Leave a Comment