편집자 - "NGINX JavaScript 모듈 소개"라는 제목의 블로그 게시물이 여기로 리디렉션됩니다. 이 게시물은 2021년 4월부터 지원되는 NGINX JavaScript 모듈 지침과 기능으로 업데이트되었습니다.
NGINX JavaScript 모듈(njs)은 NGINX Open Source 1.11.10 및 NGINX Plus R12 에서 안정적인 모듈로 일반적으로 사용 가능해졌습니다. [이 모듈은 원래 nginScript라고 불렸으며, 이 이름은 일부 이전 게시물에 나타납니다.] 우리는 2015년 9월 출시 이후 NGINX JavaScript에서 꾸준히 작업해 왔으며, 안정적인 모듈에 포함된 기능과 언어 지원을 추가했습니다.
NGINX JavaScript는 NGINX 및 NGINX Plus를 위한 고유한 JavaScript 구현으로, 서버 측 사용 사례와 요청별 처리를 위해 특별히 설계되었습니다. 정교한 구성 솔루션을 구현하기 위해 JavaScript 코드로 NGINX 구성 구문을 확장합니다.
특히 NGINX JavaScript 모듈은 HTTP와 TCP/UDP 프로토콜 모두에서 사용할 수 있으므로 사용 사례가 광범위합니다. NGINX JavaScript의 샘플 사용 사례는 다음과 같습니다.
NGINX JavaScript에 대해 더 자세히 논의하기 전에 먼저 두 가지 일반적인 오해에 대해 알아보겠습니다.
NGINX 커뮤니티는 수년에 걸쳐 여러 가지 프로그래밍 확장 기능을 만들어 왔습니다. 이 글을 쓸 당시에는 Lua가 가장 인기 있었습니다. NGINX에서는 모듈 로 사용할 수 있고, NGINX Plus에서는 지원되는 미리 빌드된 타사 동적 모듈로 사용할 수 있습니다. Lua 모듈과 추가 라이브러리는 NGINX 코어와의 긴밀한 통합과 Redis 드라이버를 포함한 풍부한 기능 세트를 제공합니다.
Lua는 강력한 스크립팅 언어입니다. 그러나 채택 측면에서는 여전히 상당히 틈새 시장에 머물러 있으며 일반적으로 프런트엔드 개발자나 DevOps 엔지니어의 "기술 도구 상자"에서 찾을 수 없습니다.
NGINX JavaScript는 Lua를 대체할 계획이 없으며 NGINX JavaScript가 동등한 수준의 기능을 갖추기까지는 시간이 걸릴 것입니다. NGINX JavaScript의 목표는 인기 있는 프로그래밍 언어를 사용하여 가능한 한 광범위한 커뮤니티에 프로그래밍 방식의 구성 솔루션을 제공하는 것입니다.
NGINX JavaScript는 NGINX 또는 NGINX Plus를 애플리케이션 서버로 바꾸는 것을 목표로 하지 않습니다. 간단히 말해서, NGINX JavaScript의 사용 사례는 미들웨어와 유사합니다. JavaScript 코드 실행은 클라이언트와 콘텐츠 사이에서 발생하기 때문입니다. 기술적으로 말하자면, Node.js는 NGINX JavaScript와 NGINX 또는 NGINX Plus의 조합과 이벤트 기반 아키텍처 와 JavaScript 프로그래밍 언어라는 두 가지를 공유하지만 유사점은 거기서 끝입니다.
Node.js는 Google V8 JavaScript 엔진을 사용하는 반면, NGINX JavaScript는 NGINX 및 NGINX Plus용으로 특별히 설계된 ECMAScript 표준의 맞춤 구현입니다. Node.js는 메모리에 영구적인 JavaScript 가상 머신(VM)을 갖고 메모리 관리를 위해 정기적인 가비지 수집을 수행하는 반면, NGINX JavaScript는 새로운 JavaScript VM과 각 요청에 필요한 메모리를 초기화하고 요청이 완료되면 메모리를 해제합니다.
위에서 언급했듯이 NGINX JavaScript는 JavaScript 언어의 맞춤형 구현입니다. 기존의 다른 모든 JavaScript 런타임 엔진은 웹 브라우저 내에서 실행되도록 설계되었습니다. 클라이언트 측 코드 실행의 특성은 시스템 리소스의 가용성부터 동시 실행 가능한 런타임 수까지 여러 면에서 서버 측 코드 실행과 다릅니다.
우리는 서버 측 코드 실행 요구 사항을 충족하고 NGINX의 요청 처리 아키텍처와 우아하게 맞물리기 위해 자체 JavaScript 런타임을 구현하기로 결정했습니다. NGINX JavaScript에 대한 당사의 디자인 원칙은 다음과 같습니다.
런타임 환경은 요청에 따라 작동하고 종료됩니다.
NGINX JavaScript 모듈은 빠른 초기화 및 폐기를 위해 설계된 단일 스레드 바이트코드 실행을 사용합니다. 런타임 환경은 요청마다 초기화됩니다. 복잡한 상태나 초기화해야 할 도우미가 없으므로 시작이 매우 빠릅니다. 메모리는 실행 중에 풀에 축적되고 완료되면 풀을 해제하여 해제됩니다. 이 메모리 관리 방식을 사용하면 개별 객체를 추적하고 해제하거나 가비지 수집기를 사용할 필요가 없습니다.
비차단 코드 실행
NGINX 및 NGINX Plus의 이벤트 기반 모델은 개별 NGINX JavaScript 런타임 환경의 실행을 예약합니다. NGINX JavaScript 규칙이 차단 작업(예: 네트워크 데이터 읽기 또는 외부 하위 요청 발행)을 수행하는 경우 NGINX 및 NGINX Plus는 연관된 NGINX JavaScript VM의 실행을 투명하게 일시 중단하고 이벤트가 완료되면 다시 예약합니다. 즉, 간단하고 선형적인 방식으로 규칙을 작성하면 NGINX 및 NGINX Plus에서 내부 차단 없이 이를 예약할 수 있습니다.
우리에게 필요한 언어 지원만 구현하세요
JavaScript의 사양은 ECMAScript 표준에 의해 정의됩니다. NGINX JavaScript는 수학 함수를 위한 일부 ECMAScript 6을 포함하여 ECMAScript 5.1을 따릅니다. 우리만의 JavaScript 런타임을 구현하면 서버 측 사용 사례에 대한 언어 지원을 우선시하고 필요 없는 것은 무시할 수 있는 자유를 얻습니다. 현재 지원되는 언어 요소 목록을 유지 관리합니다.
요청 처리 단계와의 긴밀한 통합
NGINX와 NGINX Plus는 서로 다른 단계로 요청을 처리합니다. 구성 지침은 일반적으로 특정 단계에서 작동하며 네이티브 NGINX 모듈은 종종 특정 단계에서 요청을 검사하거나 수정하는 기능을 활용합니다. NGINX JavaScript는 JavaScript 코드가 실행되는 시기를 제어할 수 있도록 구성 지침을 통해 일부 처리 단계를 노출합니다. 구성 구문과의 통합은 JavaScript 코드의 단순성과 함께 기본 NGINX 모듈의 강력함과 유연성을 제공합니다.
아래 표는 이 글을 쓸 당시 NGINX JavaScript를 통해 접근할 수 있는 처리 단계와 이를 제공하는 구성 지침을 나타냅니다.
처리 단계 | HTTP 모듈 | 스트림 모듈 |
---|---|---|
액세스 - 인증 및 액세스 제어 |
auth_request 및 js_content |
js_접근 |
사전 읽기 – 읽기/쓰기 페이로드 |
없음 | js_사전읽기 |
필터 - 프록시 중 읽기/쓰기 응답 |
js_바디_필터 js_헤더_필터 |
js_필터 |
내용 – 클라이언트에게 응답 보내기 |
js_컨텐츠 |
없음 |
로그/변수 - 요구에 따라 평가됨 |
js_세트 |
js_세트 |
NGINX JavaScript는 NGINX 오픈 소스 바이너리로 컴파일하거나 NGINX 또는 NGINX Plus에 동적으로 로드할 수 있는 모듈로 구현됩니다. NGINX JavaScript 활성화를 위한 지침 NGINX 및 NGINX Plus에 대한 내용은 이 문서의 마지막에 나와 있습니다.
이 예에서는 NGINX 또는 NGINX Plus를 간단한 역방향 프록시로 사용하고 NGINX JavaScript를 사용하여 다음과 같은 특수 형식으로 액세스 로그 항목을 구성합니다.
이 예제의 NGINX 구성은 매우 간단합니다.
보시다시피 NGINX JavaScript 코드는 구성 구문에 맞지 않습니다. 대신 js_import
지시어를 사용하여 모든 JavaScript 코드가 포함된 파일을 지정합니다. js_set
지시문은 새로운 NGINX 변수 $access_log_headers
와 이를 채우는 JavaScript 함수를 정의합니다. log_format
지시어는 $access_log_headers
값으로 각 로그 줄을 작성하는 kvpairs 라는 새로운 형식을 정의합니다.
서버
블록은 모든 요청을 https://www.example.com 으로 전달하는 간단한 HTTP 역방향 프록시를 정의합니다. access_log
지시어는 모든 요청이 kvpairs 형식으로 기록됨을 지정합니다.
이제 로그 항목을 준비하는 JavaScript 코드를 살펴보겠습니다.
kvAccess
함수의 반환 값(로그 항목)은 rawheader_logging.conf 의 js_set
구성 지시문에 전달됩니다. NGINX 변수는 요구에 따라 평가되며, 이는 js_set
으로 정의된 JavaScript 함수가 변수 값이 필요할 때 실행된다는 것을 의미합니다. 이 예에서 $access_log_headers는
log_format
지시문에서 사용되므로 kvAccess()는
로그 시간에 실행됩니다. 맵
이나 재작성
지시문(이 예에서는 표시되지 않음)의 일부로 사용되는 변수는 이전 처리 단계에서 해당 JavaScript 실행을 트리거합니다.
NGINX JavaScript로 강화된 로깅 솔루션이 어떻게 동작하는지 확인하려면 역방향 프록시를 통해 요청을 전달하고 요청 헤더에 in.
접두사가 붙은 것과 응답 헤더에 out.
접두사가 붙은 것을 포함하는 결과 로그 파일 항목을 살펴보세요.
$ curl http://127.0.0.1/ $ tail --lines=1 /var/log/nginx/access_headers.log 2021-04-23T10:08:15+00:00 클라이언트=172.17.0.1 메서드=GET uri=/index.html 상태=200 in.호스트=localhost:55081 in.사용자 에이전트=curl/7.64.1 in.수락=*/* out.콘텐츠 유형=text/html out.콘텐츠 길이=612 out.ETag=\x22606339ef-264\x22 out.수락 범위=바이트
NGINX JavaScript의 유용성은 대부분 NGINX 내부에 접근할 수 있기 때문에 가능합니다. 이 예제에서는 요청( r
) 객체의 여러 속성을 활용합니다. Stream NGINX JavaScript 모듈(TCP 및 UDP 애플리케이션용)은 자체 속성 집합을 갖는 세션 객체
를 활용합니다. HTTP와 TCP/UDP에 대한 NGINX JavaScript 솔루션의 다른 예를 보려면 NGINX JavaScript 모듈의 사용 사례를 참조하세요.
여러분이 NGINX JavaScript에 대해 생각해 낸 사용 사례에 대해 들어보고 싶습니다. 아래 댓글 섹션을 통해 알려주세요.
NGINX JavaScript 모듈에 대한 다른 HTTP 및 TCP/UDP 사용 사례를 알아보려면 다음 블로그 게시물을 확인하세요.
auth_request
확장
[ngx_snippet 이름='njs-enable-instructions']
"이 블로그 게시물에는 더 이상 사용할 수 없거나 더 이상 지원되지 않는 제품이 참조될 수 있습니다. 사용 가능한 F5 NGINX 제품과 솔루션에 대한 최신 정보를 보려면 NGINX 제품군을 살펴보세요. NGINX는 이제 F5의 일부가 되었습니다. 이전의 모든 NGINX.com 링크는 F5.com의 유사한 NGINX 콘텐츠로 리디렉션됩니다."