편집자 – 총 7부로 구성된 이 연재 기사가 이제 완결되었습니다:
- 마이크로서비스 소개
- 마이크로서비스 구축: API 게이트웨이 사용하기(이 글)
- 마이크로서비스 구축: 마이크로서비스 아키텍처의 프로세스 간 통신
- 마이크로서비스 아키텍처의 서비스 디스커버리
- 마이크로서비스를 위한 이벤트 기반 데이터 관리
- 마이크로서비스 배포 전략 선택
- 모놀리스를 마이크로서비스로 리팩터링하기
전체 아티클과 NGINX Plus를 사용한 마이크로서비스 구현 정보를 전자책으로도 다운로드할 수 있습니다. 전자책 제목은 마이크로서비스: 설계부터 배포까지입니다. 또한 새로운 마이크로서비스 솔루션 페이지도 확인해 보세요.
마이크로서비스의 설계, 구축 및 배포에 관한 이 7부작 시리즈의 첫 번째 글에서는 마이크로서비스 아키텍처 패턴을 소개했습니다. 또한 마이크로서비스 사용의 장단점과, 마이크로서비스가 복잡함에도 불구하고 일반적으로 복잡한 애플리케이션에 가장 적합한 선택인 이유를 살펴보았습니다. 시리즈의 두 번째 글인 이번 글에서는 API 게이트웨이를 사용하여 마이크로서비스를 구축하는 방법을 설명합니다.
애플리케이션을 여러 마이크로서비스로 구성하기로 했다면, 애플리케이션의 클라이언트가 마이크로서비스와 상호 작용하는 방식을 결정해야 합니다. 모놀리식 애플리케이션에는 일반적으로 복제되고 부하 분산되는 단일 엔드포인트 집합만 있습니다. 하지만 마이크로서비스 아키텍처에서는 각 마이크로서비스가 일반적으로 세분화된 엔드포인트 집합을 노출합니다. 이 글에서는 이러한 구조가 클라이언트와 애플리케이션 간 통신에 미치는 영향을 살펴보고, API 게이트웨이를 사용하는 접근 방식을 제안합니다.
소개
쇼핑 애플리케이션용 네이티브 모바일 클라이언트를 개발하고 있다고 가정해 보겠습니다. 이 경우 특정 상품에 대한 정보를 표시하는 상품 상세 페이지를 구현해야 할 가능성이 높습니다.
예를 들어, 다음 그림은 Amazon의 Android 모바일 애플리케이션에서 상품 상세 정보를 스크롤할 때 표시되는 내용을 보여줍니다.

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

모바일 클라이언트가 이러한 서비스에 액세스하는 방식을 결정해야 합니다. 어떤 옵션이 있는지 살펴보겠습니다.
클라이언트와 마이크로서비스 간 직접 통신
이론적으로 클라이언트는 각 마이크로서비스에 직접 요청을 보낼 수 있습니다. 각 마이크로서비스에는 공개 엔드포인트(https://serviceName.api.company.name)가 있습니다. 이 URL은 사용 가능한 인스턴스에 요청을 분산하는 마이크로서비스의 로드 밸런서에 매핑됩니다. 제품 세부 정보를 가져오기 위해 모바일 클라이언트는 위에 나열된 각 서비스에 요청을 보냅니다.
안타깝게도 이 옵션에는 몇 가지 문제와 한계가 있습니다. 그중 하나는 클라이언트의 요구 사항과 각 마이크로서비스가 제공하는 세분화된 API가 서로 맞지 않는다는 점입니다. 이 예시에서 클라이언트는 일곱 번의 개별 요청을 보내야 합니다. 더 복잡한 애플리케이션에서는 훨씬 더 많은 요청을 보내야 할 수도 있습니다. 예를 들어 Amazon은 자사 상품 페이지를 렌더링하는 데 수백 개의 서비스가 관여한다고 설명합니다. 클라이언트가 LAN을 통해서는 이처럼 많은 요청을 보낼 수 있겠지만, 공용 인터넷에서는 효율성이 지나치게 떨어질 가능성이 크며 모바일 네트워크에서는 분명 비현실적일 것입니다. 또한 이 접근 방식은 클라이언트 코드를 훨씬 더 복잡하게 만듭니다.
클라이언트가 마이크로서비스를 직접 호출할 때 발생하는 또 다른 문제는 일부 마이크로서비스가 웹 환경에 적합하지 않은 프로토콜을 사용할 수 있다는 점입니다. 한 서비스는 Thrift 바이너리 RPC를 사용하고 다른 서비스는 AMQP 메시징 프로토콜을 사용할 수 있습니다. 두 프로토콜 모두 브라우저나 방화벽 환경에 적합하지 않으므로 내부에서 사용하는 것이 가장 좋습니다. 애플리케이션은 방화벽 외부에서 HTTP 및 WebSocket과 같은 프로토콜을 사용해야 합니다.
이 접근 방식의 또 다른 단점은 마이크로서비스를 리팩터링하기 어렵게 만든다는 것입니다. 시간이 지나면서 시스템을 서비스 단위로 분할하는 방식을 변경하고 싶을 수 있습니다. 예를 들어 두 서비스를 하나로 통합하거나, 하나의 서비스를 둘 이상의 서비스로 분할할 수 있습니다. 하지만 클라이언트가 서비스와 직접 통신한다면 이러한 리팩터링을 수행하기가 매우 어려울 수 있습니다.
이러한 문제들 때문에 클라이언트가 마이크로서비스와 직접 통신하도록 하는 것은 적절한 경우가 거의 없습니다.
API 게이트웨이 사용
일반적으로 훨씬 더 나은 접근 방식은 이른바 API 게이트웨이를 사용하는 것입니다. API 게이트웨이는 시스템으로 들어가는 단일 진입점 역할을 하는 서버입니다. 객체 지향 설계의 퍼사드 패턴과 유사합니다. API 게이트웨이는 내부 시스템 아키텍처를 캡슐화하고 각 클라이언트에 맞춤화된 API를 제공합니다. 또한 인증, 모니터링, 부하 분산, 캐싱, 요청 조정 및 관리, 정적 응답 처리 등의 역할을 담당할 수도 있습니다.
다음 다이어그램은 일반적으로 API Gateway가 아키텍처에 어떻게 통합되는지를 보여줍니다:

API 게이트웨이는 요청 라우팅, 조합 및 프로토콜 변환을 담당합니다. 클라이언트의 모든 요청은 먼저 API 게이트웨이를 거칩니다. 그런 다음 요청을 적절한 마이크로서비스로 라우팅합니다. API 게이트웨이는 여러 마이크로서비스를 호출하고 그 결과를 집계하여 요청을 처리하는 경우가 많습니다. 또한 HTTP 및 WebSocket과 같은 웹 프로토콜과 내부적으로 사용되는 웹 비호환 프로토콜 간의 변환을 수행할 수 있습니다.
API 게이트웨이는 각 클라이언트에 맞춤형 API를 제공할 수도 있습니다. 일반적으로 모바일 클라이언트에는 대단위 API를 제공합니다. 예를 들어 제품 상세 정보 시나리오를 살펴보겠습니다. API 게이트웨이는 모바일 클라이언트가 한 번의 요청으로 제품의 모든 상세 정보를 가져올 수 있도록 엔드포인트(/productdetails?productid=xxx)를 제공할 수 있습니다. API 게이트웨이는 제품 정보, 추천, 리뷰 등 다양한 서비스를 호출하고 그 결과를 결합하여 요청을 처리합니다.
API 게이트웨이의 훌륭한 사례로는 Netflix API 게이트웨이가 있습니다. Netflix 스트리밍 서비스는 TV, 셋톱박스, 스마트폰, 게임기, 태블릿 등 수백 가지 유형의 기기에서 이용할 수 있습니다. 처음에 Netflix는 스트리밍 서비스에 모든 환경에 두루 적용되는 API를 제공하려고 했습니다. 하지만 기기의 종류가 다양하고 각 기기마다 요구 사항이 달라 제대로 작동하지 않는다는 사실을 알게 되었습니다. 현재는 기기별 어댑터 코드를 실행하여 각 기기에 맞춤화된 API를 제공하는 API 게이트웨이를 사용합니다. 일반적으로 어댑터는 요청 하나를 처리할 때 평균 6~7개의 백엔드 서비스를 호출합니다. Netflix API 게이트웨이는 하루에 수십억 건의 요청을 처리합니다.
API 게이트웨이의 장점과 단점
예상할 수 있듯이 API 게이트웨이를 사용하면 장점과 단점이 모두 있습니다. API 게이트웨이의 주요 장점은 애플리케이션의 내부 구조를 캡슐화한다는 것입니다. 클라이언트는 특정 서비스를 직접 호출할 필요 없이 게이트웨이와 통신하기만 하면 됩니다. API 게이트웨이는 각 클라이언트 유형에 맞는 전용 API를 제공합니다. 이를 통해 클라이언트와 애플리케이션 간의 왕복 통신 횟수가 줄어들고 클라이언트 코드도 간소화됩니다.
API 게이트웨이에도 몇 가지 단점이 있습니다. API 게이트웨이는 개발, 배포 및 관리가 필요한 또 하나의 고가용성 구성 요소입니다. 또한 API 게이트웨이가 개발 병목 지점이 될 위험도 있습니다. 개발자는 각 마이크로서비스의 엔드포인트를 외부에 공개하려면 API 게이트웨이를 업데이트해야 합니다. 따라서 API 게이트웨이 업데이트 절차를 최대한 간소화하는 것이 중요합니다. 그렇지 않으면 개발자들은 게이트웨이를 업데이트하기 위해 차례를 기다려야 합니다. 하지만 이러한 단점에도 불구하고 대부분의 실제 애플리케이션에서는 API 게이트웨이를 사용하는 것이 합리적입니다.
API 게이트웨이 구현
지금까지 API 게이트웨이를 사용하는 이유와 그에 따른 장단점을 살펴보았으니, 이제 고려해야 할 다양한 설계 문제를 살펴보겠습니다.
성능 및 확장성
Netflix와 같은 규모로 운영되며 하루에 수십억 건의 요청을 처리해야 하는 기업은 극소수에 불과합니다. 하지만 대부분의 애플리케이션에서 API Gateway의 성능과 확장성은 대개 매우 중요합니다. 따라서 비동기식 논블로킹 I/O를 지원하는 플랫폼을 기반으로 API Gateway를 구축하는 것이 합리적입니다. 확장 가능한 API Gateway를 구현하는 데 사용할 수 있는 기술은 다양합니다. JVM에서는 Netty, Vertx, Spring Reactor 또는 JBoss Undertow와 같은 NIO 기반 프레임워크 중 하나를 사용할 수 있습니다. 널리 사용되는 비 JVM 옵션으로는 Chrome의 JavaScript 엔진을 기반으로 구축된 플랫폼인 Node.js가 있습니다. 또 다른 방법은 NGINX Plus를 사용하는 것입니다. NGINX Plus는 배포, 구성 및 프로그래밍이 간편한 성숙하고 확장 가능하며 고성능인 웹 서버와 리버스 프록시를 제공합니다. NGINX Plus는 인증, 액세스 제어, 요청 부하 분산, 응답 캐싱을 관리할 수 있으며, 애플리케이션을 인식하는 상태 점검 및 모니터링 기능도 제공합니다.
리액티브 프로그래밍 모델 사용
API 게이트웨이는 일부 요청을 적절한 백엔드 서비스로 단순히 라우팅하여 처리합니다. 다른 요청은 여러 백엔드 서비스를 호출하고 그 결과를 집계하여 처리합니다. 제품 상세 정보 요청과 같은 일부 요청에서는 백엔드 서비스에 대한 요청들이 서로 독립적입니다. 응답 시간을 최소화하려면 API 게이트웨이가 독립적인 요청들을 동시에 수행해야 합니다. 하지만 요청 간에 종속성이 있는 경우도 있습니다. API 게이트웨이는 요청을 백엔드 서비스로 라우팅하기 전에 인증 서비스를 호출하여 먼저 요청을 검증해야 할 수 있습니다. 마찬가지로 고객의 위시리스트에 있는 제품 정보를 가져오려면 API 게이트웨이는 먼저 해당 정보가 포함된 고객 프로필을 조회한 다음, 각 제품의 정보를 조회해야 합니다. API 조합의 또 다른 흥미로운 예는 Netflix 비디오 그리드입니다.
기존의 비동기 콜백 방식으로 API 컴포지션 코드를 작성하면 금세 콜백 지옥에 빠지게 됩니다. 코드는 복잡하게 얽혀 이해하기 어렵고 오류가 발생하기 쉬워집니다. 훨씬 더 나은 방법은 리액티브 방식을 사용하여 API Gateway 코드를 선언적 스타일로 작성하는 것입니다. 리액티브 추상화의 예로는 Scala의 Future, Java 8의 CompletableFuture, JavaScript의 Promise가 있습니다. 또한 Microsoft가 원래 .NET 플랫폼용으로 개발한 Reactive Extensions(Rx 또는 ReactiveX라고도 함)도 있습니다. Netflix는 자사의 API Gateway에서 사용하기 위해 JVM용 RxJava를 만들었습니다. JavaScript용 RxJS도 있으며 브라우저와 Node.js 모두에서 실행됩니다. 리액티브 방식을 사용하면 간결하면서도 효율적인 API Gateway 코드를 작성할 수 있습니다.
서비스 호출
마이크로서비스 기반 애플리케이션은 분산 시스템이므로 프로세스 간 통신 메커니즘을 사용해야 합니다. 프로세스 간 통신 방식에는 두 가지가 있습니다. 한 가지는 비동기 메시징 기반 메커니즘을 사용하는 것입니다. 일부 구현에서는 JMS나 AMQP와 같은 메시지 브로커를 사용합니다. Zeromq와 같은 다른 구현은 브로커 없이 서비스 간에 직접 통신합니다. 또 다른 프로세스 간 통신 방식은 HTTP나 Thrift와 같은 동기식 메커니즘입니다. 일반적으로 시스템은 비동기 방식과 동기 방식을 모두 사용합니다. 각 방식에 대해 여러 구현을 사용할 수도 있습니다. 따라서 API Gateway는 다양한 통신 메커니즘을 지원해야 합니다.
서비스 디스커버리
API 게이트웨이는 통신하는 각 마이크로서비스의 위치(IP 주소 및 포트)를 알아야 합니다. 기존 애플리케이션에서는 위치를 하드코딩할 수도 있겠지만, 최신 클라우드 기반 마이크로서비스 애플리케이션에서는 간단하지 않은 문제입니다. 메시지 브로커와 같은 인프라 서비스는 일반적으로 위치가 고정되어 있어 OS 환경 변수를 통해 지정할 수 있습니다. 하지만 애플리케이션 서비스의 위치를 파악하는 일은 그리 쉽지 않습니다. 애플리케이션 서비스의 위치는 동적으로 할당됩니다. 또한 자동 확장과 업그레이드로 인해 서비스 인스턴스 집합도 동적으로 변경됩니다. 따라서 API 게이트웨이는 시스템의 다른 서비스 클라이언트와 마찬가지로 시스템의 서비스 디스커버리 메커니즘, 즉 서버 측 디스커버리 또는 클라이언트 측 디스커버리를 사용해야 합니다. 후속 글에서는 서비스 디스커버리를 더 자세히 설명합니다. 지금은 시스템에서 클라이언트 측 디스커버리를 사용하는 경우 API 게이트웨이가 서비스 레지스트리를 조회할 수 있어야 한다는 점에 주목할 필요가 있습니다. 서비스 레지스트리는 모든 마이크로서비스 인스턴스와 해당 위치를 저장하는 데이터베이스입니다.
부분 장애 처리
API 게이트웨이를 구현할 때 해결해야 할 또 다른 문제는 부분 장애입니다. 이 문제는 모든 분산 시스템에서 한 서비스가 응답이 느리거나 사용할 수 없는 다른 서비스를 호출할 때 발생합니다. API 게이트웨이는 다운스트림 서비스를 기다리며 무기한 차단되어서는 안 됩니다. 다만 장애를 처리하는 방식은 구체적인 상황과 장애가 발생한 서비스에 따라 달라집니다. 예를 들어 상품 상세 정보 시나리오에서 추천 서비스가 응답하지 않더라도 나머지 상품 상세 정보는 여전히 사용자에게 유용하므로 API 게이트웨이는 이를 클라이언트에 반환해야 합니다. 추천 항목은 비워 두거나, 예를 들어 미리 정해 둔 상위 10개 목록으로 대체할 수 있습니다. 반면 상품 정보 서비스가 응답하지 않는다면 API 게이트웨이는 클라이언트에 오류를 반환해야 합니다.
캐시된 데이터를 사용할 수 있다면 API 게이트웨이가 이를 반환할 수도 있습니다. 예를 들어 제품 가격은 자주 변경되지 않으므로, 가격 서비스가 중단된 경우 API 게이트웨이는 캐시된 가격 데이터를 반환할 수 있습니다. 데이터는 API 게이트웨이 자체에 캐시하거나 Redis 또는 Memcached와 같은 외부 캐시에 저장할 수 있습니다. API 게이트웨이는 기본 데이터나 캐시된 데이터를 반환함으로써 시스템 장애가 사용자 경험에 영향을 미치지 않도록 합니다.
Netflix Hystrix는 원격 서비스를 호출하는 코드를 작성할 때 매우 유용한 라이브러리입니다. Hystrix는 지정된 임계 시간을 초과하는 호출을 타임아웃 처리합니다. 또한 서킷 브레이커 패턴을 구현하여 응답하지 않는 서비스를 클라이언트가 불필요하게 기다리지 않도록 합니다. 서비스의 오류율이 지정된 임계값을 초과하면 Hystrix가 서킷 브레이커를 작동시키며, 지정된 시간 동안 모든 요청이 즉시 실패합니다. Hystrix를 사용하면 요청 실패 시 캐시에서 데이터를 읽거나 기본값을 반환하는 등의 대체 동작을 정의할 수 있습니다. JVM을 사용한다면 Hystrix 사용을 적극적으로 고려해야 합니다. JVM이 아닌 환경에서 실행 중이라면 이와 동등한 라이브러리를 사용해야 합니다.
요약
대부분의 마이크로서비스 기반 애플리케이션에서는 시스템의 단일 진입점 역할을 하는 API Gateway를 구현하는 것이 적절합니다. API Gateway는 요청 라우팅, 조합 및 프로토콜 변환을 담당합니다. 또한 애플리케이션의 각 클라이언트에 맞춤형 API를 제공합니다. API Gateway는 캐시된 데이터나 기본 데이터를 반환하여 백엔드 서비스의 장애를 감출 수도 있습니다. 이 시리즈의 다음 글에서는 서비스 간 통신을 살펴보겠습니다.
편집자 – 총 7부로 구성된 이 연재 기사가 이제 완결되었습니다:
- 마이크로서비스 소개
- 마이크로서비스 구축: API 게이트웨이 사용하기(이 글)
- 마이크로서비스 구축: 마이크로서비스 아키텍처의 프로세스 간 통신
- 마이크로서비스 아키텍처의 서비스 디스커버리
- 마이크로서비스를 위한 이벤트 기반 데이터 관리
- 마이크로서비스 배포 전략 선택
- 모놀리스를 마이크로서비스로 리팩터링하기
전체 아티클과 NGINX Plus를 사용한 마이크로서비스 구현 정보를 전자책으로도 다운로드할 수 있습니다. 전자책 제목은 마이크로서비스: 설계부터 배포까지입니다.
추가 사용 사례에 대한 자세한 내용은 3부작 블로그 시리즈인 NGINX Plus를 API 게이트웨이로 배포하기:
- 1부에서는 여러 사용 사례에 대한 자세한 구성 지침을 제공합니다.
- 2부에서는 이러한 사용 사례를 확장하고, 프로덕션 환경의 백엔드 API 서비스를 보호하고 안전하게 유지하기 위해 적용할 수 있는 다양한 보안 조치를 살펴봅니다.
- 3부에서는 NGINX Plus를 gRPC 서비스용 API 게이트웨이로 배포하는 방법을 설명합니다.
게스트 블로거 Chris Richardson은 최초의 CloudFoundry.com을 설립했습니다. CloudFoundry.com은 Amazon EC2용 초기 Java PaaS(서비스형 플랫폼)입니다. 현재 그는 여러 조직을 대상으로 애플리케이션 개발 및 배포 방식을 개선할 수 있도록 컨설팅하고 있습니다. 또한 http://microservices.io에서 마이크로서비스에 관한 글을 정기적으로 게시합니다.
관련 블로그 게시물
시청하기: KubeCon North America 2023에서의 NGINX Gateway Fabric
이 영상에서는 KubeCon의 NGINX 부스를 찾아가, 저희가 공개한 Kubernetes Gateway API 구현을 살펴봅니다.
F5 NGINX로 대규모 WAF 플릿을 확인하고 관리하는 2가지 방법
앱 보안을 강화하는 두 가지 방법을 소개합니다. NGINX Management Suite를 통해 WAF 운영에 대한 가시성을 높이고, NGINX App Protect WAF를 활용해 코드형 보안을 구현하는 것입니다.
Ingress 컨트롤러 선택 가이드, 4부: NGINX Ingress Controller 옵션
개발 주체, 개발 철학, 프로덕션 환경 준비도, 보안 및 지원을 기준으로 어떤 NGINX Ingress 컨트롤러가 가장 적합한지 알아보세요.
진화하는 공격 환경에 NGINX App Protect Denial of Service가 적응하는 방법
NGINX App Protect Denial of Service(DoS)가 계층 7 DoS 공격을 방어하기 위해 완화 방법을 실시간으로 조정하는 방식을 설명합니다. 정상적인 사용자 행동과 서버 상태에 대한 모델을 생성하여 공격을 나타내는 이상 징후를 감지하고 맞춤형 완화 시그니처를 적용할 수 있습니다.
NGINX Instance Manager를 활용한 대규모 구성 업데이트 및 인증서 관리
NGINX Instance Manager 버전 1.0에는 두 가지 새로운 기능이 도입되었습니다. NGINX 인스턴스에 태그와 사용자 역할을 지정하면 전체 그룹에 구성을 한 번에 적용할 수 있습니다. 인증서 검사는 만료 예정인 인증서를 감지하여 서비스 중단을 방지할 수 있도록 인증서를 교체할 수 있게 해줍니다.
Netflix가 자사 CDN의 핵심으로 NGINX를 선택한 이유
Netflix가 글로벌 콘텐츠 전송 네트워크인 Open Connect의 스트리밍 미디어 기술로 NGINX를 선택한 이유를 NGINX 개발자 Gleb Smirnoff에게서 알아보세요.