njs 0.7.7 로 NGINX 구성을 모듈화하고 재사용 가능하게 만드세요

2015년 NGINX JavaScript 모듈(njs)(원래 이름 nginScript)을 도입하고 2017년에 일반 공급한 이후, 우리는 꾸준히 새로운 기능을 추가하고 수십 개의 버전 업데이트를 통해 구현을 개선해 왔습니다. 일반적으로 새로운 NGINX JavaScript 버전의 기능에 대해 논의하기 위해 NGINX Plus 릴리스를 기다리지만, 이번에는 njs 0.7.7 버전에 대해 너무 흥분해서 기다릴 수 없습니다!

njs 0.7.7의 중요한 개선 사항은 NGINX 구성을 더욱 모듈화하고 재사용할 수 있도록 지원합니다.

  • 이제 전역이 아니라 적용되는 context에서 njs 코드를 선언할 수 있으므로 사용자 지정 코드가 사용 지점에 더 가까워집니다.
  • njs 코드 자체의 Hook를 사용하면 실행 context에 따라 동작을 수정할 수 있습니다.
  • 새로운 fs.FileHandle 체를 사용하면 파일 작업의 효율성을 높일 수 있습니다.

njs에 대해 자세히 알아보고 샘플 코드를 제공하는 사용 사례 목록을 검토하려면 포스트에서 NGINX JavaScript 모듈을 사용하여 각 요청에 대한 JavaScript의 성능과 편의성 활용을 참조하십시오.

njs 0.7.7의 모든 새로운 기능 및 버그 수정의 전체 목록은 변경 문서를 참조하세요.

목차

1. Local Context에 JavaScript 코드 및 변수 선언
2. Execution Context 따라 동작 수정
2-1. HTTP r.internal 속성

2-2. 향상된 s.send() Stream 메서드
3. 새로운 fs.FileHandle() 객체를 통한 보다 효율적인 파일 작업

1. Local Context에 JavaScript 코드 및 변수 선언

이전 njs 버전에서는 최상위 http 또는 stream context에서 JavaScript 코드를 가져와야 하고 js_import, js_path, js_set 및 js_var 지시문을 사용하여 관련 변수를 선언해야 했습니다. 그러나 실제로 JavaScript 함수와 변수를 호출하는 지시문은 하위 context에서 나타납니다. 예를 들어 HTTP location {} 블록의 js_content 지시문과 Stream server{} 블록의 js_access 지시문이 있습니다. 이로 인해 다음 두 가지 문제가 발생합니다.

  1. 구성을 읽는 사람에게 http 및 stream context의 선언은 본질적으로 노이즈입니다. 관련 코드와 변수가 실제로 사용되는 위치에 대한 표시가 없기 때문입니다.
  2. 코드와 변수를 가져오고 선언한 하위 context에서는 명확하지 않습니다. 기본 구성 파일(nginx.conf)에 만 http{} 및 stream{} 블록을 포함하고 include 지시문를 사용하여 /etc/nginx/conf.d 및 /etc/nginx/stream.d 디렉토리에서 더 작은 기능 별 구성 파일을 읽는 것이 권장되지만 NGINX 구성은 유연합니다. 여러 파일에 http{} 및 stream{} 블록을 포함할 수 있습니다. 이 문제는 여러 사람이 NGINX 구성을 작업하는 환경에서 특히 문제가 될 수 있으며 항상 기존 규칙을 따르지 않을 수 있습니다.

njs 0.7.7 이상에서는 코드를 가져오고 사용되는 context에서 변수를 선언할 수 있습니다.

HTTP 

  • 다음 지시문은 서버 및 위치 context와 http context에 나타날 수 있습니다.
    • js_import
    • js_path
    • js_set
    • js_var
  • 다음 지시문은 if context와 location 및 limit_except context에 나타날 수 있습니다.
    • js_body_filter
    • js_content
    • js_header_filter

Stream – 다음 지시문은 서버 context와 stream context에 나타날 수 있습니다.

  • js_import
  • js_path
  • js_set
  • js_var

또한 특정 사용 사례에 대한 모든 njs 구성을 단일 파일에 포함하면 코드가 더 모듈화되고 이식성이 높아집니다.

예를 들어 이전 njs 버전에서는 새 스크립트를 추가할 때 nginx.conf(js_import 및 js_path, js_set 및 js_var 추가)와 JavaScript 함수가 호출되는 파일( jscode_local.conf)을 모두 변경해야 했습니다.

nginx.conf


http {
    # util.mjs is not actually invoked in this file
    js_import util from util.mjs;

    # This reads in jscode_local.conf, where 'util' is actually invoked
    include /etc/nginx/conf.d/*.conf;
}

jscode_local.conf

server {
    listen 4001;
    
    location /foo {
        # Where is 'util' defined? It's not obvious in this context
        js_content util.handler;
    }
}

njs 0.7.7 이상에서는 util 함수와 관련된 모든 구성이 하나의 파일에 있습니다.

jscode_integrated.conf

server {
    listen 4001;
    
    js_import util from util.mjs;

    location /foo {
        js_content util.handler;
    }
}

2. Execution Context 따라 동작 수정

njs 0.7.7의 몇 가지 새로운 기능을 통해 실행 중인 context(처리 단계)에 따라 JavaScript 코드의 동작을 수정할 수 있습니다.

2-1. HTTP r.internal 속성

HTTP r.internal 속성은 내부 요청에 대해 “true”로 설정된 Boolean 플래그입니다(내부 지시문이 포함된 {}개 블록에서 처리됨). 스크립트가 내부 context와 외부 context에서 모두 호출할 수 있는 일반 이벤트 핸들러를 사용하는 경우 r.internal 플래그를 사용하여 로직(Logic)을 분기할 수 있습니다.

다음은 내부 요청으로 분류됩니다.

  • error_page, index, random_index 및 try_files 지시문에 의해 리디렉션된 요청
  • upstream 서버에서 X-Accel-Redirect 응답 헤더를 통 리디렉션된 요청
  • auth_request 및 mirror 지시문, ngx_http_addition_module 모듈의 지시문 또는 SSI(서버 측 포함)에 의해 호출된 하위 요청에는 가상 명령이 포함됩니다(ngx_http_ssi_module 모듈에서 지원).
  • rewrite 지시문에 의해 변경된 요청

2-2. 향상된 s.send() Stream 메서드

이전 njs 버전에서 Stream s.send() 메서드는 context 종속적입니다. 데이터를 보내는 방향은 메서드가 호출되는 callback의 위치(upstream 또는 downstream)에 의해 결정되기 때문입니다. 이것은 s.send()가 원래 설계된 동기식 callback에서는 잘 작동하지만 ngx.fetch()와 같은 비동기식 함수에서는 실패합니다.

njs 0.7.7 이상에서 방향은 s.send()가 사용할 수 있는 별도의 내부 플래그에 저장됩니다.

3. 새로운 fs.FileHandle() 객체를 통한 보다 효율적인 파일 작업

파일 시스템 모듈(fs)은 파일에 대한 작업을 구현합니다. fs 모듈의 새로운 FileHandle 객체는 숫자 File Descriptor를 위한 객체 래퍼(Wrapper)입니다. FileHandle 객체의 인스턴스는 fs.promises.open() 메서드에 의해 생성됩니다.

FileHandle 개체를 사용하여 File Descriptor를 가져올 수 있습니다. 이 Descriptor는 다음에 사용할 수 있습니다.

  • 파일에서 read() 및 write()와 같은 기능 수행
  • 파일을 열고 전체 파일을 읽지 않고 지정된 위치에서 읽기 및 쓰기 수행

FileHandle은 다음 속성이 구현되어있습니다.

  • filehandle.fd
  • filehandle.read()
  • filehandle.stat()
  • filehandle.write()
  • filehandle.write()
  • filehandle.close()

다음 메서드는 FileHandle을 지원하도록 업데이트되었습니다.

  • fs.openSync()
  • fs.promises.open()
  • fs.fstatSync()
  • fs.writeSync() (buffer)
  • fs.writeSync() (string)

4. njs를 사용하여 구성 향상

njs 0.7.7을 사용하면 팀이 njs 코드를 더 쉽게 작업하고 공유할 수 있습니다. njs 지시문에 대한 확장된 context는 사용자 지정 자바스크립트 코드로 NGINX 구성을 향상 시키는 것을 훨씬 더 간단하게 만듭니다. API gateway, Reverse proxy 또는 웹 서버로 먼저 이동할 수 있습니다. 스택에 다른 구성 요소를 추가하지 않고도 JavaScript, TypeScript 또는 타사 노드 모듈을 통해 이 구성 요소를 애플리케이션의 일부로 만들 수 있습니다. NGINX만 있으면 됩니다.

NGINX Plus를 사용해 보고 싶으시면 지금 30일 무료 평가판을 신청하거나 사용 사례에 대해 최신 소식을 빠르게 전달받고 싶으시면 아래 뉴스레터를 구독하세요.