The version of the NGINX JavaScript 모듈과 함께 출시된 NGINX Plus R15 버전에서는 이제 하위 요청을 실행할 수 있습니다. 즉, JavaScript 코드에서 요청을 시작할 수 있습니다. 이를 통해 완전히 새로운 사용 사례를 처리할 수 있습니다.
이러한 사용 사례 중 하나는 API 요청을 일괄 처리하는 것입니다. 즉, 클라이언트의 단일 API 요청을 여러 백엔드 서버에 대한 복수의 API 요청으로 변환하고, 각 응답을 하나로 취합하여 클라이언트에 반환합니다. 이 블로그에서는 전자상거래 사이트를 예로 듭니다. 클라이언트가 특정 제품에 대한 정보를 요청하면 카탈로그, 재고, 고객 리뷰라는 세 가지 백엔드 서비스로 하위 요청이 전송됩니다.
이 게시물에서는 NGINX Plus R15 발표에서 소개한 하위 요청 예제를 확장합니다. 이 예제에서는 하위 요청을 사용하여 동일한 요청을 두 백엔드 서버로 보내고, 먼저 도착한 응답만 클라이언트에 반환하는 방법을 보여줍니다.
[편집자 – 이 게시물은 NGINX JavaScript 모듈의 사용 사례를 살펴보는 여러 게시물 중 하나입니다. 전체 목록은 NGINX JavaScript 모듈 사용 사례를 참조하세요.
이 게시물은 다음을 사용하도록 업데이트되었습니다. js_import 지시문은 js_include 지시문을 대체하며 NGINX Plus R23 이상에서 사용됩니다. 자세한 내용은 NGINX JavaScript 모듈의 참조 문서를 확인하세요. 구성 예시 섹션에서는 NGINX 구성 파일과 JavaScript 파일의 올바른 구문을 보여 줍니다.]
소개
이 글의 목적은 간단하고 이해하기 쉬우며 실제로 작동하는 API 요청 일괄 처리 예제를 제공하는 것입니다. 이 예제들은 다음 요구 사항을 모두 충족합니다:
- 모든 요청에 HTTP
GET메서드가 사용됩니다. - 모든 응답은 JSON 형식입니다.
- 두 가지 형식의 API 요청이 지원됩니다. 어느 형식을 사용하든 쿼리 문자열에 추가 인수를 포함할 수 있습니다.
- API 프로그램에 대한 인수는 URI의 마지막 요소입니다. 이를 최종 요소 요청 방식이라고 합니다. 이 예에서 /batch-api/product/14286에 대한 클라이언트 요청은 /myapi/catalog/14286, /myapi/inventory/14286, /myapi/review/14286에 대한 요청을 생성합니다.
- 인수는 URI의 쿼리 문자열에서 식별됩니다. 이를 쿼리 문자열 요청 방식이라고 합니다. 이 예에서 /batch-api2/product?item=14286에 대한 요청은 /myapi/catalog.php?item=14286, /myapi/inventory.php?item=14286, 그리고 /myapi/review.php?item=14286에 대한 요청을 생성합니다.
- 클라이언트 요청에 의해 트리거되는 하위 요청 집합은 동적으로 구성할 수 있으므로, NGINX Plus 구성을 직접 편집하고 다시 로드하지 않고도 변경할 수 있습니다.
- 백엔드 서버에 대한 API 요청은 서로 독립적입니다.
솔루션 개요
이 솔루션은 NGINX JavaScript의 새로운 하위 요청 기능을 사용할 뿐만 아니라 NGINX Plus의 키-값 저장소 기능을 활용하여 NGINX Plus API를 통해 구성을 동적으로 변경할 수 있도록 합니다.
다음 그림은 지원되는 두 가지 요청 방식을 보여 줍니다.
최종 요소 요청 방식:

쿼리 문자열 요청 방식:

두 예시 모두에서 클라이언트는 카탈로그, 재고 및 리뷰 서비스로부터 제품 정보를 가져와야 합니다. 클라이언트는 품목 번호를 URI의 일부 또는 쿼리 문자열로 전달하여 NGINX Plus에 요청 하나를 보냅니다. 그러면 세 서비스로 요청이 전송되고, 각 응답이 하나로 집계되어 클라이언트에 반환됩니다.
NGINX Plus에서 이를 작동시키려면 두 가지 구성 요소가 필요합니다. 바로 JavaScript 프로그램과 NGINX Plus 구성.
JavaScript 프로그램
JavaScript 함수 batchAPI()는 각 클라이언트 요청마다 호출됩니다. 이 함수는 키-값 저장소에서 쉼표로 구분된 API URI 목록을 가져와 순회하면서 각각에 대해 하위 요청을 생성하고, 각 응답을 처리할 콜백 함수로 done()을 지정합니다. 최종 요소 스타일 요청의 경우 NGINX 변수 $uri_suffix에 저장된 URI의 마지막 요소가 원래 클라이언트 URI의 다른 쿼리 문자열 인수와 함께 각 하위 요청의 쿼리 문자열로 전달됩니다. 쿼리 문자열 스타일 요청의 경우 클라이언트 요청의 쿼리 문자열이 각 하위 요청의 쿼리 문자열로 전달됩니다.
호출은 키-값 저장소에 나열된 순서대로 이루어지지만 비동기식이므로 응답은 어떤 순서로든 반환될 수 있습니다. 응답은 수신된 순서대로 집계되어 클라이언트에 하나의 응답으로 전송됩니다. 다음은 JavaScript 프로그램의 최소 버전입니다:
코드 예제를 로드하는 중…
더욱 광범위한 오류 처리, 로깅 및 주석이 포함된 JavaScript 프로그램 버전은 GitHub Gist 리포지토리에서 batch-api.js라는 이름으로 제공됩니다.
최소 NGINX Plus 구성
다음 NGINX Plus 구성은 업스트림 서버 그룹을 사용하여 위에서 설명한 두 가지 요청 방식을 구현합니다. 간단히 하기 위해 이 구성에서는 업스트림 서버가 /myapi/service/item# 형식(마지막 요소 방식)의 호출을 /myapi/service.php/?item=item# 형식(쿼리 문자열 방식)으로 변환할 수 있다고 가정합니다. 이는 샘플 카탈로그, 인벤토리 및 리뷰 서비스에 사용된 언어인 PHP의 “네이티브” URI 형식입니다.
URI 변환을 자체적으로 수행하는 보다 확장된 NGINX Plus 구성에 대해서는 아래의 「URI 변환을 위한 NGINX 구성 확장」을 참조하세요.
구성 파일을 섹션별로 살펴보면서 각 부분의 역할을 설명하겠습니다:
- Import the JavaScript 파일을 가져옵니다.
코드 예제를 로드하는 중…
- Define a 키-값 저장소를 정의하여 URI의 마지막 요소가 API 프로그램의 인수를 식별하는 API 요청 목록을 저장합니다. 키는
$uri_prefix변수를 사용하여 URI에서 마지막 / 앞부분을 캡처합니다.코드 예제를 로드하는 중…
NGINX Plus R16 이상에서는 두 가지 추가 키-값 기능을 활용할 수 있습니다. 키-값 저장소의 동기화 설정 방법은 NGINX Plus 관리 가이드를 참조하세요.- 키-값 저장소의 항목에 만료 시간을 설정하려면
timeout매개변수를keyval_zone지시문에 추가합니다. 예를 들어 일괄 처리된 각 URI가 매일 만료되도록 하려면timeout=1d를 추가합니다. - Synchronize the key‑value store across a cluster of NGINX Plus instances, by adding the
sync매개변수를keyval_zone지시문에 추가하여 NGINX Plus 인스턴스 클러스터 전체에서 키-값 저장소를 동기화합니다. 이 경우timeout매개변수도 포함해야 합니다.
- 키-값 저장소의 항목에 만료 시간을 설정하려면
- 쿼리 문자열에서 인수가 식별되는 API를 위해 또 다른 키-값 저장소를 정의합니다. 여기서 키(
$uri)는 쿼리 문자열을 제외한 전체 URI를 캡처합니다.코드 예제를 로드하는 중…
- 인수가 URI의 마지막 요소인 요청을 수락하는 API를 위해 URI를 두 부분으로 분할하는 두 개의 맵을 정의합니다.
$uri_prefix변수는 마지막 / 앞의 URI 요소를 캡처하고,$uri_suffix변수는 마지막 요소를 캡처합니다.코드 예제를 로드하는 중…
- API 서버의 업스트림 그룹을 정의합니다(여기서는 NGINX Plus와 함께 localhost에서 실행됨).
코드 예제를 로드하는 중…
- 클라이언트 요청과 하위 요청을 처리하는 가상 서버를 정의합니다.
코드 예제를 로드하는 중…
- Define a location to handle client requests that use the final‑element style, which is indicated to the
batchAPIfunction by setting the$batch_api_arg_in_urivariable toon:코드 예제를 로드하는 중…
- 쿼리 문자열 형식을 사용하는 클라이언트 요청을 처리할 location을 정의합니다. 이 형식은
batchAPI함수에$batch_api_arg_in_uri변수를off로 설정하여 지정합니다.코드 예제를 로드하는 중…
- 하위 요청을 처리하는 location을 정의합니다:
코드 예제를 로드하는 중…
- Enable the NGINX Plus API를 활성화하여 키-값 저장소의 데이터를 유지 관리할 수 있도록 합니다:
코드 예제를 로드하는 중…
전체 구성은 다음과 같습니다:
코드 예제를 로드하는 중…
일괄 API 요청 구성
NGINX Plus의 키-값 저장소 기능을 사용하여 수신 클라이언트 요청을 실행할 API 요청 집합에 매핑합니다. 이전 섹션의 구성에서는 두 가지 요청 방식에 대해 별도의 키-값 저장소를 정의합니다:
- 최종 요소 스타일의 키-값 저장소 이름은 batch_api이고, 키는 요청 URI의 마지막
$uri_prefix앞에 있는 요소를 캡처하는 / 변수입니다. - 쿼리 문자열 형식의 키-값 저장소 이름은 batch_api2이고, 키는
$uri변수입니다. 이 변수는 쿼리 문자열을 제외한 전체 요청 URI를 캡처합니다.
두 키-값 저장소 모두에서 각 키와 연결된 값은 런타임에 $batch_api 또는 $batch_api2 변수로 제공되는 URI의 쉼표로 구분된 목록입니다.
최종 요소 스타일 요청의 경우, /batch-api/product에 대한 클라이언트 요청을 다음 세 서비스에 대한 요청으로 매핑하려고 합니다. /myapi/catalog, /myapi/inventory, /myapi/review입니다. 따라서 /batch-api/product/14286에 대한 요청은 다음 요청으로 이어집니다. /myapi/catalog/14286, /myapi/product/14286 및 /myapi/review/14286.
이러한 매핑을 batch_api 키-값 저장소에 추가하려면 로컬 머신에서 실행 중인 NGINX Plus 인스턴스에 다음 요청을 보냅니다:
$ curl -iX POST -d '{"/batch-api/product":"/myapi/catalog,/myapi/inventory,/myapi/review"}' http://localhost/api/3/http/keyvals/batch_api쿼리 문자열 형식의 요청에서는 /batch-api2/product에 대한 클라이언트 요청을 다음 세 서비스에 대한 요청으로 매핑하려고 합니다: /myapi/catalog.php, /myapi/inventory.php, /myapi/review.php. 즉, /batch-api2/product?item=14286에 대한 요청은 다음 요청으로 이어집니다: /myapi/catalog?item=14286, /myapi/product?item=14286 및 /myapi/review?item=14286.
이러한 매핑을 batch_api2 키-값 저장소에 추가하려면 다음 요청을 전송합니다:
$ curl -iX POST -d '{"/batch-api2/product":"/myapi/catalog.php,/myapi/inventory.php,/myapi/review.php"}' http://localhost/api/3/http/keyvals/batch_api2예제 실행하기
동일한 PHP 페이지가 두 요청 스타일로 이루어진 요청을 모두 처리합니다. 설명을 간단히 하기 위해 백엔드 서버가 최종 요소 스타일 URI(/myapi/service/item#)를 쿼리 문자열 스타일 URI(/myapi/service.php?item=item#)로 변환할 수 있다고 가정합니다. 쿼리 문자열 스타일 URI는 PHP 프로그램의 ‘기본’ URI 형식이므로 변환할 필요가 없습니다.
모든 서비스는 서비스 이름과 item 인수를 포함하는 JSON 형식의 응답을 반환합니다. 예를 들어, /myapi/catalog.php?item=14286을 요청하면 catalog.php에서 다음과 같은 응답을 반환합니다:
{"service":"Catalog","item":"14286"}이 예제에서 사용된 PHP 프로그램은 응답에 서비스 이름을 포함하지만, 모든 서비스가 그런 것은 아닐 수 있습니다. 응답을 생성한 서비스와 각 응답을 쉽게 연결할 수 있도록 JavaScript 프로그램은 집계된 응답에 URI를 포함합니다.
예를 들어 /batch-api/product/14286에 대한 요청의 집계된 응답은 다음과 같습니다(단, 세 구성 요소 응답의 순서는 달라질 수 있습니다).
[["/myapi/review/14286",{"service":"Review","item":"14286"}],["/myapi/inventory/14286",{"service":"Inventory","item":"14286"}],["/myapi/catalog/14286",{"service":"Catalog","item":"14286"}]]URI 변환을 위한 NGINX Plus 구성 확장
앞서 언급했듯이, 위에서 설명한 최소 NGINX Plus 구성에서는 API 서버가 다음 형식의 URI를 변환할 수 있다고 가정합니다. /myapi/service/item# 형식을 /myapi/service.php/?item=item# 형식으로 변환합니다. 다음과 같이 변경하여 NGINX Plus 구성에서도 이 변환을 구현할 수 있습니다.
- 하위 요청을 수신할 새 업스트림 그룹을 추가합니다:
코드 예제를 로드하는 중…
- 새 가상 서버를 추가하여 services 업스트림 그룹이 수신한 요청을 수신 대기합니다. 쿼리 문자열 형식의 요청이 수신되면 URI에 이미 api_servers 업스트림 그룹으로 프록시됩니다. 이는 URI에 이미 .php 확장자가 있기 때문입니다. 마지막 요소 형식의 요청이 수신되면 URI의 마지막 요소가 제거되어 쿼리 문자열 인수로 변환되도록 URI를 다시 작성합니다.
코드 예제를 로드하는 중…
- 새 업스트림 그룹으로 프록시하도록 /myapi location을 변경합니다.
코드 예제를 로드하는 중…
전체 구성은 다음과 같습니다:
코드 예제를 로드하는 중…
추가 구성 요소
샘플 JavaScript 프로그램과 NGINX Plus 구성은 다른 형식의 API에도 맞게 조정할 수 있습니다. 하지만 이 블로그 게시물을 작성하는 데 사용된 모든 구성 요소를 활용해 테스트하려면, PHP 페이지 제공을 위한 NGINX Unit 구성을 비롯한 관련 자료를 GitHub의 Gist 저장소에서 확인할 수 있습니다:
batch-api.js
catalog.php
inventory.php
review.php
unit.config
결론
이 예제에서는 API 요청을 일괄 처리하고 집계된 응답을 클라이언트에 제공하는 방법을 보여 줍니다. NGINX Plus 키-값 저장소를 사용하면 NGINX Plus API를 통해 API 요청을 동적으로 구성할 수 있습니다. API 시스템은 구체적인 작동 방식이 매우 다양하므로 특정 API의 요구 사항에 맞게 이 예제를 여러 가지로 개선할 수 있습니다.
You can start testing NGINX JavaScript subrequests with NGINX Open Source를 사용하여 NGINX JavaScript 하위 요청 테스트를 시작할 수 있습니다. API 일괄 처리 예제를 사용해 보거나 키-값 저장소 및 NGINX Plus API와 같은 NGINX Plus 기능을 활용하는 다른 사용 사례를 테스트하려면 30일 무료 평가판을 신청하고 직접 실험해 보세요.
작성자 소개

관련 블로그 게시물
시청하기: 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에게서 알아보세요.