API Composition#
API Composition 패턴은 마이크로서비스 아키텍처(MSA)에서 디자인 패턴 중 하나이다.
이 패턴은 여러 마이크로서비스의 데이터를 조합하여 클라이언트에게 단일 응답으로 제공하는 방식이다.
API Composition은 여러 마이크로서비스의 API 응답을 집계하여 단일 API 엔드포인트로 제공하는 패턴이다.
이를 통해 클라이언트는 복잡한 데이터 요구사항을 단일 요청으로 처리할 수 있다.
API Composition 패턴은 마이크로서비스 아키텍처에서 데이터 접근을 간소화하고 클라이언트 경험을 개선하는 강력한 도구이나 구현 시 성능과 복잡성을 고려해야 하며, 시스템의 요구사항에 따라 적절히 적용해야 한다.
주요 특징#
- 통합된 응답 제공:
- 별도의 서비스(컴포지션 서비스)가 다양한 마이크로서비스의 응답을 수집하고 결합하여 하나의 응답을 생성한다. 이를 통해 클라이언트는 단일 요청으로 필요한 모든 데이터를 받을 수 있다.
- 클라이언트 복잡성 감소:
- 클라이언트가 여러 마이크로서비스에 직접 요청을 보내는 대신, 컴포지션 서비스를 통해 통합된 데이터를 얻을 수 있어 클라이언트 측의 복잡성이 감소한다.
- 서비스 간 결합도 최소화:
- 각 마이크로서비스는 독립적으로 개발되고 배포되며, 컴포지션 서비스는 이러한 서비스를 조합하여 필요한 데이터를 제공한다. 이를 통해 서비스 간의 결합도를 낮출 수 있다.
구현 방법#
- API 게이트웨이 사용: KrakenD, Kong, AWS API Gateway 등의 도구를 활용한다.
- 컴포저 서비스 구현: 데이터를 조합하는 전용 서비스를 개발한다.
- 병렬 또는 순차적 호출: 마이크로서비스 호출을 효율적으로 관리한다.
- 클라이언트 상호작용 단순화: 여러 서비스 호출을 하나로 통합한다.
- 성능 향상: 네트워크 요청 수를 줄여 응답 시간을 개선한다.
- 보안 강화: 중앙 집중식 보안 관리가 가능하다.
- 레거시 시스템 통합: 기존 시스템을 점진적으로 마이그레이션할 수 있다.
- 메모리 사용량 증가: 대규모 데이터셋의 인메모리 조인으로 인한 문제.
- 가용성 감소: 연결된 마이크로서비스 수가 증가할수록 전체 시스템의 가용성이 저하될 수 있다.
- 성능 병목: 대규모 부하 시 API 컴포저가 병목점이 될 수 있다.
사용 사례#
- 전자상거래 플랫폼: 주문, 결제, 배송 정보를 통합하여 제공.
- 소셜 미디어 피드: 사용자, 게시물, 댓글 데이터를 결합.
- 여행 예약 서비스: 항공, 호텔, 렌터카 정보를 하나의 응답으로 제공.
구현 예시#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| // API Composer 서비스
public class OrderDetailsApiComposer {
private final OrderService orderService;
private final CustomerService customerService;
private final PaymentService paymentService;
public OrderDetailsResponse getOrderDetails(String orderId) {
// 여러 서비스에서 데이터를 가져와 조합
Order order = orderService.getOrder(orderId);
Customer customer = customerService.getCustomer(order.getCustomerId());
Payment payment = paymentService.getPayment(order.getPaymentId());
return new OrderDetailsResponse(order, customer, payment);
}
}
|
비동기 방식의 구현
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
| public class AsyncOrderDetailsComposer {
private final OrderService orderService;
private final CustomerService customerService;
private final PaymentService paymentService;
public CompletableFuture<OrderDetailsResponse> getOrderDetailsAsync(String orderId) {
return orderService.getOrderAsync(orderId)
.thenCompose(order -> {
CompletableFuture<Customer> customerFuture =
customerService.getCustomerAsync(order.getCustomerId());
CompletableFuture<Payment> paymentFuture =
paymentService.getPaymentAsync(order.getPaymentId());
return CompletableFuture.allOf(customerFuture, paymentFuture)
.thenApply(v -> new OrderDetailsResponse(
order,
customerFuture.join(),
paymentFuture.join()
));
});
}
}
|
참고 및 출처#