NGINX JavaScript 모듈(njs)을 2015년에 처음 선보이고(당시 명칭은 nginScript), 2017<.htmla>년에 정식 출시한 이후, 수십 차례의 버전 업데이트를 거치며 새로운 기능을 꾸준히 추가하고 구현을 개선해 왔습니다. 일반적으로 새로운 NGINX JavaScript 버전의 기능은 NGINX Plus 릴리스에 맞춰 소개하지만, 이번에는 버전 0.7.7이 너무 기대되어 도저히 기다릴 수가 없습니다!
njs 0.7.7의 주요 개선 사항을 통해 NGINX 구성을 더욱 모듈화하고 체계적으로 정리하여 재사용할 수 있습니다:
- 이제 njs 코드를 전역으로 선언하는 대신 적용되는 컨텍스트에서 선언하여 사용자 지정 코드를 실제 사용 지점에 더 가깝게 배치할 수 있습니다.
- njs 코드 자체의 훅을 사용하면 실행 컨텍스트에 따라 동작을 수정할 수 있습니다.
- 새로운
fs.FileHandle객체를 사용하면 파일 작업을 더 효율적으로 수행할 수 있습니다.
njs에 대해 자세히 알아보고 샘플 코드를 제공하는 사용 사례 목록을 확인하려면 블로그에서 NGINX JavaScript 모듈로 각 요청에 JavaScript의 강력함과 편리함 활용하기를 읽어보세요.
njs 0.7.7의 모든 새로운 기능과 버그 수정 사항에 대한 전체 목록은 변경 사항 문서를 참조하세요.
로컬 컨텍스트에서 JavaScript 코드 및 변수 선언
이전 버전의 njs에서는 최상위 js_import, js_path, js_set, js_var 지시어를 사용하여 JavaScript 코드를 가져오고 관련 변수를 http 또는 stream 컨텍스트에서 선언해야 합니다. 이는 기본 파일의 맨 위에서 전역 변수를 선언하는 것과 같습니다. 하지만 JavaScript 함수와 변수를 실제로 호출하는 지시어는 하위 컨텍스트에 있습니다. 예를 들어 HTTP location{} 블록의 js_content 지시어와 Stream server{} 블록의 js_access 지시어가 이에 해당합니다. 이로 인해 다음 두 가지 문제가 발생합니다.
- 구성 파일을 살펴보는 사람에게는
http및stream컨텍스트의 선언이 관련 코드와 변수가 실제로 어디에서 사용되는지 알려 주지 않으므로 사실상 불필요한 정보에 불과합니다. - 하위 컨텍스트에서는 코드와 변수가 어디에서 가져와지고 선언되었는지 명확하지 않습니다.
http{}및stream{}블록은 기본 구성 파일(nginx.conf)에만 포함하고,include지시어를 사용하여 /etc/nginx/conf.d 및 /etc/nginx/stream.d 디렉터리에서 기능별로 나뉜 더 작은 구성 파일을 읽어 들이는 방식을 권장하지만, NGINX 구성은 유연하므로 여러 파일에http{}및stream{}블록을 포함할 수 있습니다. 여러 사람이 NGINX 구성을 함께 작업하면서 정해진 규칙을 항상 따르지는 않을 수 있는 환경에서는 이로 인해 특히 문제가 발생할 수 있습니다.
njs 0.7.7 이상에서는 코드가 사용되는 컨텍스트에서 코드를 가져오고 변수를 선언할 수 있습니다.
- HTTP –
- 스트림 – 이러한 지시문은
server컨텍스트뿐만 아니라stream컨텍스트에도 사용할 수 있습니다:
특정 사용 사례에 필요한 모든 njs 구성을 하나의 파일에 모아 두면 코드의 모듈성과 이식성도 향상됩니다.
예를 들어, 이전 버전의 njs에서는 새 스크립트를 추가할 때 nginx.conf 파일(js_import 및 필요한 경우 js_path, js_set, js_var 추가)과 JavaScript 함수가 호출되는 파일(여기서는 jscode_local.conf)을 모두 변경해야 했습니다.
코드 예제를 로드하는 중…
코드 예제를 로드하는 중…
njs 0.7.7 이상에서는 util 함수와 관련된 모든 구성이 하나의 파일인 jscode_integrated.conf에 있습니다:
코드 예제를 로드하는 중…
실행 컨텍스트에 따라 동작 변경하기
njs 0.7.7에 추가된 여러 새로운 기능을 사용하면 JavaScript 코드가 실행되는 컨텍스트(처리 단계)에 따라 코드의 동작을 변경할 수 있습니다.
HTTP r.internal 속성
HTTP r.internal 속성은 내부 요청에 대해 “true”로 설정되는 부울 플래그입니다. 내부 요청은 location{} 블록 중 internal 지시어가 포함된 블록에서 처리됩니다. 스크립트가 내부 및 비내부 컨텍스트 모두에서 호출될 수 있는 범용 이벤트 핸들러를 사용할 때 r.internal 플래그를 사용하여 로직을 분기할 수 있습니다.
다음은 내부 요청으로 분류됩니다:
- 다음 지시어에 의해 리디렉션된 요청:
error_page,index,random_index,try_filesdirectives - 업스트림 서버의
X-Accel-Redirect응답 헤더에 의해 리디렉션된 요청 - 다음에 의해 호출되는 하위 요청:
auth_request및mirror지시어, ngx_http_addition_module 모듈의 지시어 또는 SSI(Server Side Include)의includevirtual명령(ngx_http_ssi_module 모듈에서 지원) - Requests changed by the
rewrite지시어에 의해 변경된 요청
개선된 s.send() 스트림 메서드
이전 njs 버전에서는 Stream의 s.send() 메서드가 컨텍스트에 따라 동작했습니다. 데이터 전송 방향이 이 메서드를 호출하는 콜백의 위치(업스트림 또는 다운스트림)에 의해 결정되었기 때문입니다. 이는 s.send()가 원래 대상으로 설계된 동기 콜백에서는 제대로 작동하지만, ngx.fetch()와 같은 비동기 함수에서는 작동하지 않습니다.
njs 0.7.7 이상에서는 방향이 별도의 내부 플래그에 저장되며, 이후 s.send()에서 이 플래그를 사용할 수 있습니다.
새로운 fs.FileHandle() 객체를 활용한 더욱 효율적인 파일 작업
파일 시스템 모듈(fs)은 파일에 대한 작업을 구현합니다. 새로운 FileHandle 객체는 fs 모듈에서 숫자형 파일 디스크립터를 감싸는 객체입니다. FileHandle 객체의 인스턴스는 fs.promises.open() 메서드로 생성됩니다.
Use the FileHandle 객체를 사용하여 다음 작업에 활용할 수 있는 파일 디스크립터를 가져옵니다:
- 파일에
read()및write()같은 함수를 수행합니다 - 파일 전체를 읽지 않고도 파일을 열어 지정된 위치에서 읽기 및 쓰기 작업 수행
다음 FileHandle 속성이 구현되었습니다(각 속성의 필수 및 선택적 인수에 대한 자세한 내용은 문서 참조):
filehandle.fdfilehandle.read()filehandle.stat()filehandle.write()filehandle.write()filehandle.close()
다음 메서드는 FileHandle을 지원하도록 업데이트되었습니다(각 메서드의 인수에 관한 자세한 내용은 링크된 문서를 참조하세요):
njs를 사용하여 구성 개선하기
njs 0.7.7에서는 팀이 njs 코드를 더 쉽게 개발하고 공유할 수 있도록 개선했습니다. njs 지시문의 컨텍스트가 확장되어 사용자 지정 JavaScript 코드로 NGINX 구성을 한층 더 간편하게 강화할 수 있습니다. 단순한 미들웨어나 엣지 구성 요소를 넘어서는 API 게이트웨이, 리버스 프록시 또는 웹 서버를 구축하는 첫걸음을 내디딜 수 있습니다. JavaScript, TypeScript 또는 타사 node 모듈을 통해 이를 애플리케이션의 일부로 통합할 수 있으며, 스택에 별도의 구성 요소를 추가할 필요도 없습니다. NGINX만 있으면 됩니다!
궁금한 점이 있으신가요? NGINX 커뮤니티 Slack에 참여하고 #njs-code-review 채널에서 자세한 내용을 알아보고, 질문하고, 작성한 njs 코드에 대한 피드백을 받아보세요.
관련 블로그 게시물
시청하기: 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에게서 알아보세요.