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 사용: 원본 흐름 유지하면서 부가 처리가 필요할 때