Categories: Camel프레임워크

[Camel in Action] 10-2. Camel REST 클라이언트 – 외부 API 호출과 응답 처리

Camel을 REST 클라이언트로 사용하기

Camel은 REST 서버뿐 아니라 클라이언트로도 탁월합니다. 외부 API를 호출하고 응답을 처리하는 복잡한 로직을 라우트로 표현하면 유지보수가 훨씬 쉬워집니다.

기본 REST API 호출

// GET 요청
from("timer:apiCall?period=60000")
  .to("rest:get:https://api.example.com/users?bridgeEndpoint=true")
  .unmarshal().json(JsonNode.class)
  .process(exchange -> {
    JsonNode users = exchange.getIn().getBody(JsonNode.class);
    // 응답 처리
  });

// POST 요청
from("direct:createUser")
  .marshal().json()
  .setHeader(Exchange.HTTP_METHOD, constant("POST"))
  .setHeader(Exchange.CONTENT_TYPE, constant("application/json"))
  .to("http4://api.example.com/users?bridgeEndpoint=true")
  .unmarshal().json(UserResponse.class);

OAuth 2.0 인증 처리

현대 API는 대부분 OAuth 토큰 인증이 필요합니다. Camel에서 토큰을 자동으로 갱신하는 패턴입니다.

// 토큰 캐싱 빈
@Component
public class TokenCache {
  private String token;
  private Instant expiry;

  public String getValidToken() {
    if (token == null || Instant.now().isAfter(expiry)) {
      refreshToken();
    }
    return token;
  }
}

// 라우트에서 토큰 주입
from("direct:secureApiCall")
  .process(exchange -> {
    String token = tokenCache.getValidToken();
    exchange.getIn().setHeader("Authorization", "Bearer " + token);
  })
  .to("http4://secure-api.example.com/data?bridgeEndpoint=true");

응답 코드별 처리 분기

API 응답 코드에 따라 다른 처리가 필요할 때는 Choice EIP를 활용합니다.

from("direct:apiCall")
  .to("http4://api.example.com/resource?bridgeEndpoint=true&throwExceptionOnFailure=false")
  .choice()
    .when(header(Exchange.HTTP_RESPONSE_CODE).isEqualTo(200))
      .to("bean:successHandler")
    .when(header(Exchange.HTTP_RESPONSE_CODE).isEqualTo(404))
      .log("리소스 없음")
      .stop()
    .when(header(Exchange.HTTP_RESPONSE_CODE).isEqualTo(429))
      .log("요청 한도 초과, 재시도")
      .delay(60000)
      .to("direct:apiCall") // 재귀 호출로 재시도
    .otherwise()
      .to("direct:errorHandler")
  .end();

재시도와 폴백 패턴

외부 API는 일시적으로 실패할 수 있습니다. Camel의 Retry와 Circuit Breaker로 복원력 있는 클라이언트를 구현합니다.

from("direct:resilientApiCall")
  .circuitBreaker()
    .resilience4jConfiguration()
      .slidingWindowSize(10)
      .failureRateThreshold(50)
      .waitDurationInOpenState(30)
    .end()
    .to("http4://flaky-api.example.com/data")
  .onFallback()
    .setBody(simple("{"source":"cache","data":${bean:cacheService.getLatest}}"))
  .end();

페이지네이션 자동 처리

대용량 데이터를 페이지 단위로 가져오는 API를 처리할 때는 동적 라우팅으로 반복 호출을 자동화합니다.

from("direct:fetchAllPages")
  .setHeader("page", constant(1))
  .loopDoWhile(simple("${header.hasMore} == 'true' || ${header.page} == 1"))
    .toD("http4://api.example.com/items?page=${header.page}&bridgeEndpoint=true")
    .process(exchange -> {
      PagedResponse resp = exchange.getIn().getBody(PagedResponse.class);
      exchange.getIn().setHeader("hasMore", resp.hasNextPage());
      exchange.getIn().setHeader("page", resp.getPage() + 1);
    })
    .to("direct:processPage")
  .end();

zerg96

Share
Published by
zerg96

Recent Posts

[Apache Camel] 2025년 최신 트렌드 – AI 통합과 서버리스 Camel의 미래

2025년 Apache Camel의 최신 트렌드를 분석합니다. AI/LLM 통합 컴포넌트, 서버리스 배포, Camel K 진화, WebAssembly…

11시간 ago

[Camel in Action] 완결편 – Apache Camel 전체 여정 회고와 다음 단계

Camel in Action을 완독한 후 Apache Camel의 전체 그림을 다시 정리합니다. 핵심 철학, 학습 경로,…

11시간 ago

[Camel in Action] 실전편 – Camel 마이그레이션 가이드 2.x에서 4.x까지

Apache Camel 2.x에서 3.x, 4.x로 마이그레이션하는 단계별 가이드입니다. 주요 API 변경사항, 제거된 컴포넌트, 자동화 도구…

11시간 ago

[Camel in Action] 실전편 – Camel 라우트 디버깅 기법과 문제 해결 가이드

Apache Camel 라우트에서 발생하는 문제를 디버깅하고 해결하는 실전 기법을 설명합니다. 로그 분석, breakpoint 디버깅, Tracer,…

11시간 ago

[Camel in Action] 실전편 – Camel 도입 전 반드시 알아야 할 것들

Apache Camel을 프로젝트에 도입하기 전 알아야 할 핵심 사항을 정리합니다. 학습 곡선, 도입 비용, 적합한…

11시간 ago

[Camel in Action] 실전편 – Enterprise Integration Patterns 20가지 핵심 정리

엔터프라이즈 통합 패턴(EIP) 20가지를 Apache Camel 코드와 함께 한 번에 정리합니다. 메시징 채널, 메시지 라우팅,…

11시간 ago