마이크로서비스 구축을 위한 API Gateway 패턴 사용하기
마이크로서비스 에서 API Gateway를 사용하는 방법에 대해 설명합니다.
애플리케이션을 마이크로서비스 세트(Set)로 빌드하기로 선택한 경우 애플리케이션의 클라이언트가 마이크로서비스와 상호 작용하는 방식을 결정해야 합니다. 모놀리식 애플리케이션에는 (일반적으로 복제되고 로드 밸런싱된) endpoint set가 하나만 있습니다. 그러나 마이크로서비스 아키텍처에서 각 마이크로서비스는 일반적으로 세분화된 Endpoint 집합을 노출합니다. 해당 사례에서는 클라이언트와 애플리케이션 간의 Communication에 어떤 영향을 미치는지 살펴보고 API Gateway를 사용하는 접근 방식을 제안합니다.
목차
1. 마이크로서비스 소개
2. 클라이언트-마이크로서비스 Direct Communication
3. 마이크로서비스 API Gateway 사용
4. API Gateway의 장점과 단점
5. API Gateway 구현
5-1. 성능 및 확장성
5-2. 반응형(Reactive) 프로그래밍 모델 사용
5-3. Service Invocation
5-4. Service Discovery
5-5. Handling Partial Failures
6. 요약
1. 마이크로서비스 소개
쇼핑 애플리케이션을 위한 기본 모바일 클라이언트를 개발 중이라고 가정해 보겠습니다. 주어진 제품에 대한 정보를 표시하는 제품 세부 정보 페이지를 구현해야 할 수 있습니다.
예를 들어 다음 다이어그램은 Amazon의 Android 모바일 애플리케이션에서 제품 세부 정보를 스크롤할 때 표시되는 내용을 보여줍니다.

스마트폰 어플리케이션임에도 불구하고 상품 상세페이지에 많은 정보가 표시됩니다. 예를 들어, 기본 제품 정보(예: 이름, 설명 및 가격)가 있을 뿐만 아니라 이 페이지에는 다음도 표시됩니다.
- 장바구니에 담긴 상품 수
- 주문 내역
- 사용자 리뷰
- 재고 부족 경고
- 배송 옵션
- 이 제품을 자주 구매하는 다른 제품, 이 제품을 구매한 고객이 구매한 다른 제품, 이 제품을 구매한 고객이 본 다른 제품 등 다양한 추천
- 대체 구매 옵션
모놀리식 애플리케이션 아키텍처를 사용할 때 모바일 클라이언트는 애플리케이션에 대한 단일 REST 호출(GET api.company.com/productdetails/productId)을 만들어 이 데이터를 검색합니다. Load Balancer는 N개의 동일한 애플리케이션 인스턴스 중 하나로 요청을 라우팅합니다. 그런 다음 응용 프로그램은 다양한 데이터베이스 테이블을 쿼리하고 클라이언트에 응답을 반환합니다.
대조적으로, 마이크로서비스 아키텍처를 사용할 때 제품 세부정보 페이지에 표시되는 데이터는 여러 마이크로서비스에서 소유합니다. 다음은 예제 제품 세부 정보 페이지에 표시된 데이터를 소유한 잠재적인 마이크로서비스 중 일부입니다.
- 장바구니 서비스 – 장바구니에 담긴 상품 수
- 주문 서비스 – 주문 내역
- 카탈로그 서비스 – 이름, 이미지, 가격과 같은 기본 제품 정보
- 리뷰 서비스 – 고객 리뷰
- 재고 서비스 – 재고 부족 경고
- 배송 서비스 – 배송 제공업체의 API에서 별도로 도출한 배송 옵션, 기한 및 비용
- 추천 서비스 – 제안 항목

모바일 클라이언트가 이러한 서비스에 액세스하는 방법을 결정해야 합니다. 옵션을 살펴보겠습니다.
2. 클라이언트-마이크로서비스 Direct Communication
이론적으로 클라이언트는 각 마이크로 서비스에 직접 요청할 수 있습니다. 각 마이크로 서비스에는 Public Endpoint(https://serviceName.api.company.name)가 있습니다. 이 URL은 사용 가능한 인스턴스에 요청을 분산하는 마이크로 서비스의 Load Balancer에 매핑됩니다. 제품 세부 정보를 검색하기 위해 모바일 클라이언트는 위에 나열된 각 서비스에 요청합니다.
불행히도 이 옵션에는 문제와 제한 사항이 있습니다. 한 가지 문제는 클라이언트의 요구 사항과 각 마이크로 서비스에서 노출되는 세분화된 API 간의 불일치입니다. 이 예에서 클라이언트는 7개의 개별 요청을 해야 합니다. 더 복잡한 응용 프로그램에서는 더 많이 만들어야 할 수도 있습니다. 예를 들어 Amazon은 수백 개의 서비스가 제품 페이지를 렌더링하는 데 어떻게 관련되어 있는지 설명합니다. 클라이언트가 LAN을 통해 많은 요청을 할 수 있지만 공용 인터넷에서는 너무 비효율적이며 모바일 네트워크에서는 확실히 비실용적입니다. 또한 이 접근 방식은 클라이언트 코드를 훨씬 더 복잡하게 만듭니다.
마이크로서비스를 직접 호출하는 클라이언트의 또 다른 문제는 일부가 웹 친화적이지 않은 프로토콜을 사용할 수 있다는 점입니다. 한 서비스는 Thrift 바이너리 RPC를 사용하고 다른 서비스는 AMQP 메시징 프로토콜을 사용할 수 있습니다. 두 프로토콜 모두 특히 브라우저 또는 방화벽 친화적이지 않으며 내부적으로 사용하는 것이 가장 좋습니다. 애플리케이션은 방화벽 외부에서 HTTP 및 WebSocket과 같은 프로토콜을 사용해야 합니다.
이 접근 방식의 또 다른 단점은 마이크로서비스를 리팩토링하기 어렵게 만든다는 것입니다. 시간이 지남에 따라 시스템이 서비스로 분할되는 방식을 변경하고 싶을 수 있습니다. 예를 들어, 두 개의 서비스를 병합하거나 서비스를 둘 이상의 서비스로 분할할 수 있습니다. 그러나 클라이언트가 서비스와 직접 통신하는 경우 이러한 종류의 리팩토링을 수행하는 것이 매우 어려울 수 있습니다.
이러한 종류의 문제 때문에 클라이언트가 마이크로서비스와 Direct Communication하는 것은 거의 의미가 없습니다.
3. 마이크로서비스 API Gateway 사용
일반적으로 훨씬 더 나은 접근 방식은 API Gateway로 알려진 것을 사용하는 것입니다. API Gateway는 시스템의 단일 진입점인(Single Entry Point) 서버입니다. 객체 지향 디자인의 Facade 패턴과 유사합니다. API Gateway는 내부 시스템 아키텍처를 캡슐화하여 각 클라이언트에 맞는 API를 제공합니다. 인증, 모니터링, Load Balancing, 캐싱, 요청 셰이핑 및 관리, 정적 응답 처리와 같은 다른 책임이 있을 수 있습니다.
다음 다이어그램은 API Gateway가 일반적으로 아키텍처에 어떻게 맞는지 보여줍니다.

API Gateway는 요청 라우팅, 구성 및 프로토콜 변환을 담당합니다. 클라이언트의 모든 요청은 먼저 API Gateway를 거칩니다. 그런 다음 요청을 적절한 마이크로서비스로 라우팅합니다. API Gateway는 종종 여러 마이크로 서비스를 호출하고 결과를 집계하여 요청을 처리합니다. HTTP 및 WebSocket과 같은 웹 프로토콜과 내부적으로 사용되는 웹 친화적이지 않은 프로토콜 간에 변환할 수 있습니다.
API Gateway는 또한 각 클라이언트에 사용자 지정 API를 제공할 수 있습니다. 일반적으로 모바일 클라이언트를 위한 대략적인 API를 노출합니다. 예를 들어 제품 세부 정보 시나리오를 고려하십시오. API Gateway는 모바일 클라이언트가 단일 요청(Single Request)으로 모든 제품 세부 정보를 검색할 수 있도록 하는 Endpoint(/productdetails?productid=xxx)를 제공할 수 있습니다. API Gateway는 제품 정보, 추천, 리뷰 등 다양한 서비스를 호출하고 결과를 결합하여 요청을 처리합니다.
API Gateway의 좋은 예는 Netflix API Gateway입니다. Netflix 스트리밍 서비스는 TV, 셋톱 박스, 스마트폰, 게임 시스템, 태블릿 등을 포함한 수백 가지 종류의 장치에서 사용할 수 있습니다. 처음에 Netflix는 스트리밍 서비스를 위한 만능 API를 제공하려고 했습니다. 그러나 그들은 다양한 장치와 고유한 요구 사항으로 인해 제대로 작동하지 않는다는 것을 발견했습니다. 오늘날 그들은 장치별 어댑터 코드를 실행하여 각 장치에 맞는 API를 제공하는 API Gateway를 사용합니다. 어댑터는 일반적으로 평균 6~7개의 Backend 서비스를 호출하여 각 요청을 처리합니다. Netflix API Gateway는 하루에 수십억 건의 요청을 처리합니다.
4. API Gateway의 장점과 단점
예상대로 API Gateway를 사용하면 장점과 단점이 모두 있습니다. API Gateway 사용의 주요 이점은 애플리케이션의 내부 구조를 캡슐화한다는 것입니다. 클라이언트는 특정 서비스를 호출하지 않고 단순히 게이트웨이와 통신합니다. API Gateway는 각 종류의 클라이언트에 특정 API를 제공합니다. 이렇게 하면 클라이언트와 애플리케이션 간의 왕복 횟수가 줄어듭니다. 또한 클라이언트 코드를 단순화합니다.
API Gateway에도 몇 가지 단점이 있습니다. 개발, 배포 및 관리해야 하는 또 다른 고가용성 구성 요소입니다. API Gateway가 개발 병목 현상이 될 위험도 있습니다. 개발자는 각 마이크로 서비스의 Endpoint를 노출하기 위해 API Gateway를 업데이트해야 합니다. API Gateway 업데이트 프로세스는 가능한 한 가볍게 하는 것이 중요합니다. 그렇지 않으면 개발자는 게이트웨이를 업데이트하기 위해 줄을 서서 기다려야 합니다. 그러나 이러한 단점에도 불구하고 대부분의 실제 애플리케이션에서는 API Gateway를 사용하는 것이 합리적입니다.
5. API Gateway 구현
이제 API Gateway를 사용하는 동기와 장단점을 살펴보았으므로 고려해야 할 다양한 설계 문제를 살펴보겠습니다.
5-1. 성능 및 확장성
소수의 회사만이 Netflix 규모로 운영되며 하루에 수십억 건의 요청을 처리해야 합니다. 그러나 대부분의 애플리케이션에서 API Gateway의 성능과 확장성은 일반적으로 매우 중요합니다. 따라서 비동기식(asynchronous) nonblocking I/O를 지원하는 플랫폼에서 API Gateway를 구축하는 것이 합리적입니다. 확장 가능한 API Gateway를 구현하는 데 사용할 수 있는 다양한 기술이 있습니다. JVM에서는 Netty, Vertx, Spring Reactor 또는 JBoss Undertow와 같은 NIO 기반 프레임워크 중 하나를 사용할 수 있습니다. 인기 있는 비 JVM 옵션 중 하나는 Chrome의 JavaScript 엔진을 기반으로 하는 플랫폼인 Node.js입니다. 또 다른 옵션은 NGINX Plus를 사용하는 것입니다. NGINX Plus는 쉽게 배포, 구성 및 프로그래밍할 수 있는 성숙하고 확장 가능한 고성능 웹 서버 및 Reverse Proxy를 제공합니다. NGINX Plus는 인증, 액세스 제어, 로드 밸런싱 요청, 캐싱 응답을 관리하고 애플리케이션 인식 상태 확인 및 모니터링을 제공합니다.
5-2. 반응형(Reactive) 프로그래밍 모델 사용
API Gateway는 일부 요청을 적절한 Backend 서비스로 간단히 라우팅하여 처리합니다. 여러 Backend 서비스를 호출하고 결과를 집계하여 다른 요청을 처리합니다. 제품 세부 정보 요청과 같은 일부 요청의 경우 Backend 서비스에 대한 요청은 서로 독립적입니다. 응답 시간을 최소화하기 위해 API Gateway는 독립적인 요청을 동시에 수행해야 합니다. 그러나 때때로 요청 간에 종속성이 있습니다. API Gateway는 요청을 Backend 서비스로 라우팅하기 전에 먼저 인증 서비스를 호출하여 요청을 검증해야 할 수 있습니다. 마찬가지로, 고객의 위시리스트에 있는 제품에 대한 정보를 가져오려면 API Gateway가 먼저 해당 정보가 포함된 고객의 프로필을 검색한 다음 각 제품에 대한 정보를 검색해야 합니다. API 구성의 또 다른 흥미로운 예는 Netflix Video Grid입니다.
기존의 비동기 콜백(asynchronous callback) 접근 방식을 사용하여 API 구성 코드를 작성하면 빠르게 콜백 지옥으로 이동합니다. 코드가 엉키고 이해하기 어려우며 오류가 발생하기 쉽습니다. 훨씬 더 나은 접근 방식은 반응적 접근 방식을 사용하여 선언적 스타일로 API Gateway 코드를 작성하는 것입니다. 반응적 추상화의 예로는 Scala의 Future, Java 8의 CompletableFuture, JavaScript의 Promise가 있습니다. Microsoft에서 원래 .NET 플랫폼용으로 개발한 Reactive Extensions(Rx 또는 ReactiveX라고도 함)도 있습니다. Netflix는 특히 API Gateway에서 사용하기 위해 JVM용 RxJava를 만들었습니다. 브라우저와 Node.js 모두에서 실행되는 JavaScript용 RxJS도 있습니다. 반응적 접근 방식을 사용하면 간단하면서도 효율적인 API Gateway 코드를 작성할 수 있습니다.
5-3. Service Invocation
마이크로서비스 기반 애플리케이션은 분산 시스템이며 프로세스 간 통신 메커니즘을 사용해야 합니다. 프로세스 간 통신에는 두 가지 스타일이 있습니다. 한 가지 옵션은 비동기식 메시징 기반 메커니즘을 사용하는 것입니다. 일부 구현에서는 JMS 또는 AMQP와 같은 메시지 브로커를 사용합니다. Zeromq와 같은 다른 것들은 브로커리스이며 서비스는 직접 통신합니다. 프로세스 간 통신의 다른 스타일은 HTTP 또는 Thrift와 같은 동기 메커니즘입니다. 시스템은 일반적으로 비동기 및 동기 스타일을 모두 사용합니다. 각 스타일의 여러 구현을 사용할 수도 있습니다. 따라서 API Gateway는 다양한 통신 메커니즘을 지원해야 합니다.
5-4. Service Discovery
API Gateway는 통신하는 각 마이크로 서비스의 위치(IP 주소 및 포트)를 알아야 합니다. 기존 애플리케이션에서는 위치를 하드와이어링할 수 있지만 최신 클라우드 기반 마이크로서비스 애플리케이션에서는 이는 사소한 문제가 아닙니다. 메시지 브로커와 같은 인프라 서비스는 일반적으로 OS 환경 변수를 통해 지정할 수 있는 정적 위치를 갖습니다. 그러나 응용 서비스의 위치를 결정하는 것은 그리 쉬운 일이 아닙니다. 응용 프로그램 서비스에는 동적으로 할당된 위치가 있습니다. 또한 자동 크기 조정 및 업그레이드로 인해 서비스 인스턴스 집합이 동적으로 변경됩니다. 결과적으로 API Gateway는 시스템의 다른 서비스 클라이언트와 마찬가지로 서버 측 탐색 또는 클라이언트 측 탐색과 같은 시스템의 서비스 탐색 메커니즘을 사용해야 합니다. 이후 기사에서는 서비스 검색에 대해 더 자세히 설명합니다. 현재로서는 시스템이 클라이언트 측 검색을 사용하는 경우 API Gateway가 모든 마이크로서비스 인스턴스 및 해당 위치의 데이터베이스인 서비스 레지스트리를 쿼리할 수 있어야 한다는 점에 유의할 가치가 있습니다.
5-5. Handling Partial Failures
API Gateway를 구현할 때 해결해야 하는 또 다른 문제는 부분 실패 문제입니다. 이 문제는 한 서비스가 느리게 응답하거나 사용할 수 없는 다른 서비스를 호출할 때마다 모든 분산 시스템에서 발생합니다. API Gateway는 downstream 서비스를 무기한으로 차단해서는 안 됩니다. 그러나 실패를 처리하는 방법은 특정 시나리오와 실패하는 서비스에 따라 다릅니다. 예를 들어 제품 세부 정보 시나리오에서 추천 서비스가 응답하지 않는 경우 API Gateway는 나머지 제품 세부 정보가 여전히 사용자에게 유용하기 때문에 클라이언트에 반환해야 합니다. 권장 사항은 비어 있거나 예를 들어 고정된 상위 10개 목록으로 대체될 수 있습니다. 그러나 제품 정보 서비스가 응답하지 않으면 API Gateway는 클라이언트에 오류를 반환해야 합니다.
API Gateway는 사용 가능한 경우 캐시된 데이터를 반환할 수도 있습니다. 예를 들어 제품 가격이 자주 변경되지 않기 때문에 API Gateway는 가격 서비스를 사용할 수 없는 경우 캐시된 가격 데이터를 반환할 수 있습니다. 데이터는 API Gateway 자체에서 캐시하거나 Redis 또는 Memcached와 같은 외부 캐시에 저장할 수 있습니다. API Gateway는 기본 데이터 또는 캐시된 데이터를 반환하여 시스템 오류가 사용자 경험에 영향을 미치지 않도록 합니다.
Netflix Hystrix는 원격 서비스를 호출하는 코드를 작성하는 데 매우 유용한 라이브러리입니다. Hystrix는 지정된 임계값을 초과하는 호출 시간을 초과합니다. 클라이언트가 응답하지 않는 서비스를 불필요하게 기다리지 않도록 하는 회로 차단기 패턴을 구현합니다. 서비스에 대한 오류율이 지정된 임계값을 초과하면 Hystrix는 회로 차단기를 트립하고 모든 요청은 지정된 시간 동안 즉시 실패합니다. Hystrix를 사용하면 캐시에서 읽거나 기본값을 반환하는 것과 같이 요청이 실패할 때 대체 작업을 정의할 수 있습니다. JVM을 사용하는 경우 Hystrix 사용을 반드시 고려해야 합니다. 그리고 JVM이 아닌 환경에서 실행 중인 경우 동등한 라이브러리를 사용해야 합니다.
6. 요약
대부분의 마이크로서비스 기반 애플리케이션의 경우 시스템에 대한 단일 진입점 역할을 하는 API Gateway를 구현하는 것이 좋습니다. API Gateway는 요청 라우팅, 구성 및 프로토콜 변환을 담당합니다. 애플리케이션의 각 클라이언트에 맞춤형 API를 제공합니다. API Gateway는 캐시된 데이터나 기본 데이터를 반환하여 Backend 서비스의 오류를 마스킹할 수도 있습니다.
댓글을 달려면 로그인해야 합니다.