레거시 시스템 통합의 현실
기업의 핵심 시스템 대부분은 수십 년 된 레거시입니다. 전면 재개발은 비용과 위험이 너무 크고, 그냥 두면 현대화가 불가능합니다. Camel은 레거시 시스템을 건드리지 않고 현대적인 인터페이스로 감싸는 데 탁월합니다.
Strangler Fig 패턴
나무를 감싸며 자라는 교살자 무화과나무처럼, 레거시 시스템을 새 시스템으로 점진적으로 대체합니다. Camel이 중간에서 요청을 신구 시스템에 적절히 분배합니다.
// 기능별로 신구 시스템에 라우팅
from("servlet:api/orders")
.choice()
.when(header("feature-flag").isEqualTo("new-system"))
.to("http4://new-order-service/api/orders")
.otherwise()
.to("http4://legacy-system:8080/OrderService")
.end();
Feature Flag를 활용하면 특정 사용자나 트래픽 비율만 새 시스템으로 보내 안전하게 검증합니다.
레거시 API 래핑
SOAP 기반 레거시 서비스를 REST API로 감싸는 일반적인 현대화 패턴입니다.
// 레거시 SOAP를 REST로 래핑
rest("/customers/{id}")
.get()
.to("direct:getCustomer");
from("direct:getCustomer")
.setHeader("customerId", header("id"))
.to("cxf:http://legacy-system/CustomerService?serviceClass=CustomerService")
.process(exchange -> {
// SOAP 응답을 JSON으로 변환
CustomerResponse soap = exchange.getIn().getBody(CustomerResponse.class);
CustomerDto dto = mapper.toDto(soap);
exchange.getIn().setBody(dto);
})
.marshal().json();
데이터 마이그레이션 파이프라인
레거시 DB에서 새 시스템 DB로 데이터를 점진적으로 마이그레이션합니다.
// 야간에 미마이그레이션 데이터를 배치로 이전
from("quartz2:migration?cron=0+0+3+*+*+?")
.to("sql:SELECT * FROM legacy_orders WHERE migrated=0 LIMIT 1000")
.split(body())
.process(exchange -> {
LegacyOrder legacy = exchange.getIn().getBody(LegacyOrder.class);
NewOrder newOrder = legacyMapper.convert(legacy);
exchange.getIn().setBody(newOrder);
})
.to("bean:newOrderRepository?method=save")
.to("sql:UPDATE legacy_orders SET migrated=1 WHERE id=:#${body.legacyId}")
.end()
.log("마이그레이션 배치 완료");
이벤트 기반 레거시 통합
레거시 시스템이 이벤트를 발행하지 못한다면 DB 변경을 폴링해 이벤트를 발행합니다.
// DB 변경 감지 후 이벤트 발행 (CDC 패턴)
from("sql:SELECT * FROM orders WHERE created_at > :#${header.lastCheck} "
+ "ORDER BY created_at?delay=10000")
.process(exchange -> {
exchange.getIn().setHeader("lastCheck", LocalDateTime.now().toString());
})
.split(body())
.marshal().json()
.to("kafka:order-events")
.end();