먼저 말씀드리자면, NGINX Unit 팀의 소식을 전한 지도 꽤 오랜 시간이 흘렀습니다. 이 격동의 시기는 모두에게 영향을 미쳤으며, 저희도 예외는 아닙니다. 올해 3월, Unit 팀의 창립 멤버인 Valentin Bartenev와 Maxim Romanov는 수년간의 노력과 무한한 창의성을 NGINX Unit에 쏟은 뒤 새로운 기회를 찾아 떠나기로 했습니다. 공로를 인정받아 마땅한 이들에게 찬사를 보냅니다. 두 사람이 없었다면 NGINX Unit은 지금의 위치에 오르지 못했을 것입니다. 두 분께 박수를 보냅니다.
그럼에도 우리의 의지는 여전히 굳건하며, NGINX 공동 창립자 이고르 시소예프가 NGINX Unit에 품었던 원대한 비전을 실현하겠다는 약속도 변함없습니다. 새로 합류한 두 팀원 알레한드로 콜로마르와 앤드루 클레이턴 덕분에 개발에 더욱 박차를 가할 수 있었고, 이제 NGINX Unit 버전 1.25부터 1.28까지의 주목할 만한 여러 소식을 여러분께 전해 드리고자 합니다.
이제 관측 가능성을 지원합니다
Unit이 항상 핵심 목표 중 하나로 삼아 온 것은 관측 가능성이며, 버전 1.28.0에는 가장 많은 기대를 받아 온 기능 중 하나인 통계 엔진의 첫 번째 구현이 포함되었습니다. 통계 엔진의 출력은 새로운 /status API 엔드포인트를 통해 제공됩니다:
$ curl --unix-socket /var/run/control.unit.sock http://localhost/status
{
"connections": {
"accepted": 1067,
"active": 13,
"idle": 4,
"closed": 1050
},
"requests": {
"total": 1307
},
"applications": {
"wp": {
"processes": {
"running": 14,
"starting": 0,
"idle": 4
},
"requests": {
"active": 10
}
}
}
}여기에 있는 대부분의 필드는 그 의미가 명확합니다. connections(2행)와 requests(9행)는 인스턴스 전체의 데이터를 제공하는 반면, applications 객체(13행)는 /config/applications의 구조를 반영하며 해당 애플리케이션과 직접 관련된 프로세스와 요청을 다룹니다.
3~6행에는 NGINX Unit이 추적하는 네 가지 연결 범주가 나와 있습니다. 즉, accepted, active, idle, closed입니다. 프로세스 범주는 running, starting, idle입니다(16~18행). 이러한 범주는 연결과 프로세스의 내부 표현을 반영하므로, 이제 여러분도 서버만큼이나 이에 대해 잘 알게 되었습니다.
너무 간단해 보이나요? 지금으로서는 알아야 할 내용이 거의 전부입니다. 물론 더 유용한 메트릭을 제공하기 위해 노력하고 있지만, 이미 명령줄에서 이 API를 쿼리하여 서버에서 무슨 일이 일어나고 있는지 확인할 수 있으며, 출력을 대시보드나 원하는 좀 더 세련된 도구에 연동할 수도 있습니다. 대시보드가 없으신가요? 기본 제공 대시보드를 지원하는 것도 저희 계획 중 하나이니, 앞으로 어떻게 진행되는지 지켜봐 주세요.
자세한 내용은 NGINX Unit 설명서의 사용 통계를 참조하세요.
더 많은 변수, 더 다양한 활용처
버전 1.24부터 도입된 변수는 매우 다양하며, 여기에는 $body_bytes_sent, $header_referer, $header_user_agent, $remote_addr, $request_line, $request_uri, $status, 그리고 $time_local이 포함됩니다.
대부분은 비교적 이해하기 쉽지만, 그중 특히 주목할 만한 몇 가지는 다음과 같습니다:
$request_uri에는 브라우저 인코딩이 유지된 요청 URI의 경로와 쿼리가 포함됩니다- 이름이 비슷한
$request_line에는GET/docs/help.htmlHTTP/1.1과 같은 전체 요청이 저장되며, 로깅 용도로 사용됩니다… - HTTP 응답 상태 코드를 포함하는
$status도 마찬가지입니다
눈치채셨나요? 응답에 대해 언급했습니다. 맞습니다. 이제 응답 영역도 다루기 시작합니다. 이전 Unit 버전의 변수는 수신 요청에 초점을 맞췄지만, 이제는 $status 및 $body_bytes_sent와 같이 응답 속성을 담는 변수도 제공됩니다.
변수를 사용할 수 있는 새로운 위치와 관련해 가장 먼저 언급할 것은 새롭게 사용자 지정할 수 있는 액세스 로그 형식입니다. NGINX Unit의 로그 항목에 JSON을 사용하고 싶으신가요? 단순한 경로 문자열을 지정하는 것 외에도 access_log 옵션을 로그 항목의 형식까지 설정하는 객체로 지정할 수 있습니다:
{
"access_log": {
"path": "/var/log/unit/access.log",
"format": "{ \"remote_addr\":\"$remote_addr\", "time\":\"$time_local\", \"request\":\"$request_line\", \"response\":\"$status\", \"header_referer\":\"$header_referer\", \"header_user_agent\":\"$header_user_agent\" }"
}
}따라서 원하는 방식으로 일반적인 로그 형식의 한계를 넘어설 수 있습니다.
변수의 두 번째 주목할 만한 사용 사례는 라우트 location의 action 값입니다:
{
"action": {
"return": 301,
"location": "https://$host$request_uri"
}
}여기서는 $request_uri를 사용하여 쿼리 부분을 포함한 요청을 HTTPS를 통해 동일한 웹사이트로 전달합니다.
이제 chroot 옵션도 share 옵션과 마찬가지로 변수를 지원합니다. 이는 당연한 일입니다:
{
"action": {
"share": "/www$uri",
"chroot": "/www/data/$host/"
}
} 이제 NGINX Unit은 동적 변수도 지원합니다. 요청 인수, 쿠키 및 헤더는 변수로 제공됩니다. 예를 들어 쿼리 문자열 Type=car&Color=red는 두 개의 인수 변수인 $arg_Type과 $arg_Color를 생성합니다. 런타임에 이러한 변수는 동적 값으로 확장되며, 존재하지 않는 변수를 참조하면 빈 값으로 간주됩니다.
자세한 내용은 NGINX Unit 설명서의 변수 항목을 참조하세요.
Extensive Support for the X-Forwarded-* 헤더에 대한 폭넓은 지원
여러분의 요청에 부응했습니다. 버전 1.25.0부터 NGINX Unit은 일정 수준의 X-Forwarded-* 인식 기능을 비롯해 리스너를 위한 몇 가지 TLS 구성 기능을 제공해 왔습니다. 이제 리스너 구성에서 클라이언트 IP 주소와 프로토콜 대체를 설정할 수 있습니다:
{
"listeners": {
"*:80": {
"pass": "routes/my-app",
"forwarded": {
"client_ip": "X-Forwarded-For",
"protocol": "X-Forwarded-Proto",
"recursive": false,
"source": [
"198.51.100.1-198.51.100.254",
"!198.51.100.128/26",
"203.0.113.195"
]
}
}
},
...
}참고: 이 새 구문은 이전 client_ip 구문을 더 이상 사용하지 않으며, 해당 구문은 향후 릴리스에서 제거될 예정입니다.
자세한 내용은 NGINX Unit 설명서의 IP, 프로토콜 포워딩을 참조하세요.
새롭게 개편된 share 옵션
NGINX Unit 버전 1.11.0에서는 정적 콘텐츠를 제공하기 위한 share 라우팅 옵션이 도입되었습니다. 이는 NGINX의 root 지시어와 유사합니다:
{
"share": "/path/to/dir/"
}처음에는 share 옵션이 이른바 문서 루트 디렉터리를 지정했습니다. Unit은 제공할 파일을 결정하기 위해 요청의 URI를 이 share 경로에 단순히 덧붙였습니다. 예를 들어 GET 방식으로 /some/file.html을 요청하면 Unit은 /path/to/dir/some/file.html을 제공했습니다. 하지만 파일 경로를 더 세밀하게 제어해야 하는 경계 사례가 계속 발생하여 이 방식을 개선하기로 했습니다. 버전 1.26.0부터 share 옵션은 문서 루트만이 아니라 공유 파일의 전체 경로를 지정합니다.
특정 파일을 제공하고 싶으신가요? 좋습니다:
{
"share": "/path/to/a/file.html"
}경로 내에서 변수를 사용하고 싶으신가요? 물론 문제없습니다:
{
"share": "/www/data/$host/app.html"
}그렇다면 NGINX와 이전 버전의 Unit에서 이미 익숙해진 동작을 어떻게 구현할 수 있을까요? 몇 단락 앞에서 더 이상 필요 없다고 했던 문서 루트 말입니다. 해결 방법이 있습니다.
이제 다음과 같이 구성을 다시 작성할 수 있습니다:
{
"share": "/www/data/"
}다음과 같이 요청된 URI를 경로에 명시적으로 추가합니다!
{
"share": "/www/data/$uri"
}마지막으로, share 지시문은 이제 경로 배열을 받아 파일을 찾을 때까지 각 경로를 하나씩 시도할 수 있습니다:
{
"share": [
"/www/$host$uri",
"/www/static$uri",
"/www/app.html"
]
}파일을 찾을 수 없으면 라우팅은 fallback 액션으로 넘어갑니다. fallback이 없으면 404 (Not Found) 상태 코드가 반환됩니다.
자세한 내용은 NGINX Unit 설명서의 정적 파일을 참조하세요.
계획: njs, URI 재작성, 작업 연결, OpenAPI
이 글을 읽고 계신 지금도 저희는 이미 다음 릴리스를 준비하고 있습니다. 앞으로 선보일 내용을 살짝 소개해 드리겠습니다.
먼저 NGINX Unit을 NGINX에서 활발히 개발 중인 또 하나의 핵심 프로젝트인 NGINX JavaScript 모듈(njs)과 통합하고 있습니다. 간단히 말해, NGINX Unit에서 JavaScript 모듈 호출을 지원하게 된다는 뜻입니다. 다음 예를 살펴보세요:
var hellonjs = {}
hellonjs.hello = function(vars) {
if ('unitvar' in vars) {
return vars.unitvar;
} else {
return 'default';
}
}
export default hellonjsNGINX Unit에서 모듈을 가져오면 구성을 활용해 몇 가지 유용한 작업을 수행할 수 있습니다:
{
"match": {
"uri": "~(?.*)" }, "action": { "share": "`/www/html${hellonjs.hello(vars)}`" } }또한, 널리 사용되는 NGINX의 rewrite 지시어와 유사한 기능도 도입할 계획입니다:
{
"match": {
"uri": "/app/old_path"
},
"action": {
"rewrite": "/app/new_path",
"pass": "routes"
}
}하지만 저희의 계획은 여기서 끝나지 않습니다. NGINX Unit의 라우팅을 앱 자체의 출력과 연결하는 것은 어떨까요(일명 action 체이닝)?
{
"action": [
{
"pass": "applications/auth_check"
},
{
"pass": "applications/my_app"
}
]
}여기서 핵심은 auth_check 앱이 들어오는 요청을 인증하고 그 결과를 나타내는 상태 코드를 반환한다는 것입니다. 인증에 성공하면 200 OK가 반환되고 요청은 my_app으로 전달됩니다.
한편, 저희는 NGINX Unit의 API와 정확한 기능을 명확히 정의하기 위한 OpenAPI 명세도 작업하고 있습니다. 엄청난 규모의 작업인 만큼 많은 응원 부탁드립니다.
그래도 궁금증이 해소되지 않는다면, 저희의 로드맵에서 향후 계획을 세부적으로 살펴보세요. 대화형으로 제공되므로 독자 여러분의 의견은 언제든 환영합니다.
관련 블로그 게시물
시청하기: 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에게서 알아보세요.