API 조합 패턴

임태환·2025년 2월 18일

study

목록 보기
8/10

모놀리식 아키텍처는 하나의 DB에 여러 데이터를 저장하므로
단일 DB에서 SQL 조인으로 데이터를 쉽게 조회가 가능했다

반면 마이크로서비스 아키텍처에서는 여러 서비스, 여러 DB에 분산된 데이터를 조회해야하는데
API 조합 패턴과 CQRS 패턴으로 쿼리를 구현한다.

API 조합 패턴이란?

서비스 클라이언트가 데이터를 가진 여러 서비스를 직접 호출하여 그 결과를 조합하는 패턴이다.

example image

API 조합 패턴의 빌딩 블록

프로바이더 서비스

  • 최종 결과로 반환할 데이터의 일부를 갖고 있는 서비스

API 조합기

  • 여러 프로바이더 서비스를 쿼리하여 데이터를 조회한 후 결과를 조합
    • 웹 페이지에 렌더링하는 클라이언트 또는 API 게이트웨이나
      프론트엔드를 위한 백엔드 패턴의 변형일 수도 있다.

프로세스 흐름 예시

  1. 클라이언트 요청 - 단일 API 엔드포인트를 요청하여 필요한 데이터를 요청
  • GET /order-details/{orderId}
  1. API 조합기에서 데이터 요청 수신

  2. API 조합기에서 필요한 데이터를 제공하는 프로바이더 서비스 호출

  • 프로바이더 서비스는 독립적으로 데이터를 관리, API 조합기는 병렬 또는 순차적으로 서비스 호출
  1. 데이터 수집
  • 각 프로바이더 서비스 (주문 서비스, 결제 서비스, 배송 서비스)가 자신이 소유한 데이터 반환
  1. 데이터 병합 및 로직 처리
  • API 조합기가 반환된 데이터를 메모리 내에서 병합하거나 추가적인 비즈니스 로직 적용
    • EX) 주문 상태, 결제 상태 기반으로 배송 가능 여부 계산
  1. 최종 응답 반환
  • API 조합기에서 병합된 데이터를 클라이언트에 반환한다.

API 조합 설계 이슈

API 조합 패턴에는 두 가지 설계 이슈가 존재한다.

  1. 어느 컴포넌트를 쿼리 작업의 API 조합기로 선정할 것인가?
  2. 어떻게 해야 효율적으로 취합 로직을 작성할 것인가?

1-1 서비스 클라이언트를 API 조합기로 임명

  • 클라이언트가 직접 여러 서비스를 호출하고 데이터를 병합하는 방식

    • 클라이언트와 서비스의 네트워크 환경에 따라 달라짐

동일한 LAN(Local Area Network)에서 실행 중인 경우

항목장점단점
네트워크 성능낮은 레이턴시와 높은 대역폭으로 효율적인 데이터 조회 가능-
아키텍처 단순성별도의 중간 계층(API Gateway, Aggregator 서비스) 없이 간단히 구현 가능-
개발 및 유지보수중간 계층이 없으므로 추가적인 인프라 관리가 필요하지 않음클라이언트 코드가 복잡해지고, 병합 로직이 클라이언트에 포함됨
서비스 의존성서비스 간 통신이 빠르고 안정적이며, 방화벽/NAT 변환 없이 직접 통신 가능서비스 API 변경 시 모든 클라이언트를 수정해야 하므로 유지보수 부담 증가

클라이언트가 방화벽 외부에 있고, 서비스 네트워크가 느린 경우

항목장점단점
네트워크 성능-WAN 환경에서 네트워크 병목 현상 발생: 레이턴시 증가 및 패킷 손실 가능성
아키텍처 단순성-여러 서비스 호출로 인해 네트워크 왕복 시간(RTT)이 누적되어 성능 저하
보안성-모든 서비스가 외부에 노출되므로 보안 취약성이 증가하며, 공격 표면이 넓어짐
개발 및 유지보수-클라이언트 코드 복잡성 증가: 병합 로직과 다중 호출 로직을 모두 포함해야 함

1-2 애플리케이션 외부 API가 구현된 API 게이트웨이를 API 조합기로 만들기

  • 클라이언트가 여러 외부 API를 호출하지 않고, 게이트웨이가 대신 여러 서비스를 호출해 데이터 조합
    • 쿼리 작업(데이터 조회)이 주요 작업일 때 적합하다.

프로세스 흐름

  1. 클라이언트 요청 - 단일 API 엔드포인트를 호출
    ex) GET /order-details/1234

  2. API 게이트웨이 - 요청을 분석하고 필요한 데이터를 제공하는 여러 백엔드 서비스를 호출

  • 주문 서비스 : GET /orders/1234
  • 결제 서비스 : GET /payments/1234
  • 배송 서비스 : GET /shipping/1234
  1. 데이터 병합 및 응답 생성 - 게이트웨이가 각 서비스에서 받은 데이터를 병합하여 단일 응답 생성

  2. 최종 응답 반환 - 병합된 데이터를 클라이언트에 반환

장점단점
클라이언트가 단일 API만 호출하면 되므로 복잡성이 감소복잡한 비즈니스 로직에는 적합하지 않음 (게이트웨이에서 처리하기 어렵기 때문)
네트워크 왕복 횟수를 줄여 성능 최적화 가능게이트웨이에 과도한 로직 추가 시 성능 저하 가능
기존 게이트웨이 기능(라우팅, 인증 등)과 통합 가능단일 장애점(Single Point of Failure) 발생 가능
간단한 데이터 조회 및 병합 작업에 적합대규모 데이터 변환이나 계산에는 별도의 Aggregator 서비스 필요

1-3 API 조합기를 스탠드얼론 서비스로 구현하기

  • 데이터 병합 및 로직 처리를 전담하는 독립적인 마이크로서비스 구축
    • 복잡한 비즈니스 로직이 필요한 경우
    • 대규모 데이터 변환 및 병합 작업이 요구되는 경우

프로세스 흐름은 API 게이트웨이를 API 조합기로 사용하는 방식과 유사하지만
아래와 같은 차이점이 존재한다

특징API 게이트웨이를 API 조합기로 사용하는 경우스탠드얼론 API 조합기를 구현하는 경우
역할게이트웨이가 데이터 병합과 라우팅을 동시에 처리.데이터 병합과 로직 처리를 전담하는 독립적인 마이크로서비스.
책임 분리게이트웨이가 데이터 병합 외에도 인증/인가, 로깅, 라우팅 등 다양한 역할 수행.API 조합기가 오직 데이터 병합 및 복잡한 비즈니스 로직 처리를 담당.
복잡한 로직 처리 가능 여부제한적: 간단한 데이터 병합 작업에 적합.가능: 고도화된 데이터 변환 및 계산 작업도 처리 가능.
확장성제한적: 게이트웨이는 라우팅과 병합 작업을 동시에 처리하므로 확장성에 한계가 있음.높음: 스탠드얼론 서비스로 독립적으로 확장 가능.
적용 사례단순한 데이터 조회 및 병합 작업(예: 쿼리 작업).복잡한 데이터 변환, 대규모 트래픽 처리, 캐싱 및 성능 최적화가 필요한 경우.

즉 내부적으로 여러 서비스가 사용하는 쿼리 작업이나 취합 로직이 너무 복잡해서 API 게이트웨이 일부로 만들기는 곤란하고 외부에서 접근 가능한 쿼리 작업을 구현할 경우 좋은 방법이다.

API 조합기는 리엑티브 프로그래밍 모델을 사용해야 한다.

분산 시스템 개발 시 지연 시간을 최소화하는 문제가 존재한다.
쿼리 작업의 반응 시간을 최대한 줄이려면 API 조합기가 프로바이더 서비스를 병렬 호출해야 한다.

특징설명
병렬 처리여러 서비스를 동시에 호출하여 응답 시간을 단축 가능.
순차 처리의존성이 있는 작업을 순서대로 실행 가능(예: 주문 상태 확인 후 결제 정보 가져오기).
비동기 및 논블로킹쓰레드 블로킹 없이 동시에 여러 요청 처리 가능.
복잡한 데이터 병합 지원데이터 스트림과 연산자를 활용해 간결하고 효율적인 병합 로직 구현 가능.
백프레셔 지원대량의 데이터 흐름을 제어하여 안정성을 유지.
효율적인 에러 처리스트림 내에서 에러를 우아하게 처리하여 시스템 안정성 향상.

주의점
순차/병렬 서비스 호출이 뒤섞인 실행 로직은 복잡해질 수 있어
관리성이 용이하고 성능/확정성이 우수한 API 조합기를 작성하려면
CompletableFuture, RxJava의 옵저버블 등 추상체에 기반한 리엑티브 설계 기법을 동원해야함

API 조합 패턴의 단점

MSA에서 쉽고 단순하게 쿼리 작업을 구현할 수 있지만
아래와 같은 단점들도 존재한다.

오버헤드 증가

여러 서비스를 호출하고 여러 DB를 쿼리하는 오버헤드는 불가피하다
그만큼 컴퓨팅/네트워크 리소스가 더 많이 소모되고 애플리케이션 운영 비용도 증가한다.

가용성이 저하될 우려 존재

  • 어떤 작업의 가용성은 더 많은 서비스가 개입할수록 감소하는 경우가 존재한다.

이러한 가용성 저하에 대한 가용성을 높이는 전략이 2가지 존재한다.

  1. 프로바이더 서비스가 불능일 경우 API 조합기가 이전에 캐시한 데이터 반환

    프로바이더가 내려가더라도 API 조합기는 (시간 경과에 따라 안 맞는 데이터 존재)
    캐시 데이터를 반환할 수 있다.

  2. API 조합기가 미완성된 데이터를 반환

    하나의 서비스가 중단되어도 해당 서비스의 데이터만 제외한 나머지 데이터를 반환
    UI에서 유용한 정보를 표시하는 데 별 지장이 없을 수 있음

데이터 일관성 결여

  • 모놀리식 애플리케이션은 대부분 한 트랜잭션으로 쿼리를 수행하여 ACID가 보장된다
    • API 조합 패턴은 여러 DB에 여러 쿼리를 수행하여 일관된지 않은 데이터가 반환될 수 있다.
해결 방법설명장점단점
Eventual Consistency시간이 지나면 모든 서비스가 동일한 상태로 동기화됨.높은 가용성과 확장성 제공임시적인 불일치 상태 허용 필요
Saga Pattern분산 트랜잭션을 순차적으로 처리하고 실패 시 롤백 수행.분산 환경에서도 데이터 일관성 유지 가능구현 복잡성 증가
Event-Driven Architecture이벤트 브로커를 통해 비동기로 데이터 변경 사항 전달.높은 성능과 확장성 제공즉각적인 동기화 어려움
Data Partitioning & Contextual Boundaries각 서비스가 자신의 데이터만 관리하도록 경계 설정.마이크로서비스 간 의존성 감소교차 참조 시 추가적인 API 호출 필요
Caching & Read Models캐싱 또는 읽기 전용 모델을 활용해 최신 데이터를 빠르게 제공.빠른 응답 시간 제공캐시 갱신 주기에 따라 최신성과 불일치 가능성 존재

정리

APi 조합 패턴은 꽤 많은 쿼리 기능을 쉽게 구현할 수 있는 수단이다
하지만 효율적으로 구현하기 어려운 쿼리 작업은 CQRS 패턴으로 구현하는 것이 좋다.

profile
웹 개발자

0개의 댓글