[Camel in Action] 3-1. Camel 데이터 변환 – Message Translator와 Content Enricher EIP

데이터 변환의 중요성

서로 다른 시스템은 서로 다른 데이터 형식을 사용합니다. 레거시 시스템은 XML을, 현대 API는 JSON을, 배치 시스템은 CSV를 사용할 수 있습니다. Camel은 이런 데이터 변환을 라우트 중간에 자연스럽게 처리합니다.

Message Translator EIP

메시지의 본문이나 구조를 다른 형식으로 변환하는 패턴입니다. 다양한 방법으로 구현할 수 있습니다.

방법 1: transform()과 simple 언어

from("direct:input")
    .setBody(simple("주문번호: ${header.orderId}, 고객: ${body.customerName}"))
    .log("변환 결과: ${body}");

방법 2: process()로 직접 변환

from("file:inbox?noop=true")
    .process(exchange -> {
        String csv = exchange.getIn().getBody(String.class);
        Order order = csvToOrder(csv);  // CSV → Java 객체 변환
        exchange.getIn().setBody(order);
    })
    .to("jms:queue:orders");

방법 3: Bean 메서드 활용

@Component
public class OrderTransformer {
    public Order transform(String csvLine) {
        String[] parts = csvLine.split(",");
        return new Order(parts[0], parts[1], Double.parseDouble(parts[2]));
    }
}

// 라우트
from("direct:csvInput")
    .bean(OrderTransformer.class, "transform")
    .log("변환된 주문: ${body}");

Content Enricher EIP – 메시지 보강

외부 소스에서 추가 데이터를 가져와 메시지를 보강하는 패턴입니다. 두 가지 구현 방법이 있습니다.

pollEnrich() – 소비자로 보강

from("direct:newOrder")
    // 고객 정보 파일에서 추가 정보 가져오기
    .enrich("file:customer-data?fileName=${header.customerId}.xml",
            new CustomerEnricher())
    .to("direct:processEnrichedOrder");

public class CustomerEnricher implements AggregationStrategy {
    @Override
    public Exchange aggregate(Exchange original, Exchange resource) {
        Order order = original.getIn().getBody(Order.class);
        String customerXml = resource.getIn().getBody(String.class);
        order.setCustomerDetails(parseCustomer(customerXml));
        original.getIn().setBody(order);
        return original;
    }
}

enrich() – 생산자로 보강

from("direct:checkInventory")
    .enrich("http://inventory-service/api/stock/${header.productId}",
            (original, enriched) -> {
                Order order = original.getIn().getBody(Order.class);
                int stock = enriched.getIn().getBody(Integer.class);
                order.setAvailableStock(stock);
                original.getIn().setBody(order);
                return original;
            })
    .choice()
        .when(simple("${body.availableStock} > 0"))
            .to("direct:confirmOrder")
        .otherwise()
            .to("direct:backOrderProcess")
    .end();

transform() vs setBody() 차이

  • setBody(): In 메시지의 본문만 변경. 헤더는 유지됨.
  • transform(): Exchange에 새 Out 메시지를 생성. InOut 패턴에서 응답 설정 시 사용.

헤더 조작

from("direct:order")
    .setHeader("timestamp", simple("${date:now:yyyy-MM-dd'T'HH:mm:ss}"))
    .setHeader("source", constant("web-order"))
    .removeHeader("sensitiveData")
    .removeHeaders("temp.*")  // 정규식으로 여러 헤더 제거
    .to("jms:queue:orders");

Leave a Comment