NGINX의 HTTP/2 모듈

NGINX | 2016년 1월 19일

이 블로그 게시물은 9월 샌프란시스코에서 열린 nginx.conf 2015에서 Valentin V. Bartenev가 진행한 발표를 바탕으로 작성되었습니다.

목차

며칠 전, NGINX의 HTTP/2 모듈을 출시했습니다. 이번 발표에서는 새 모듈을 간략히 소개하겠습니다.

0:20 프로토콜 개요

HTTP/2는 HTTP/1.x를 대체하거나 모든 문제를 해결해 주는 만능 해결책이 아닙니다. 장단점이 있는 HTTP/1의 또 다른 전송 계층이며, 기본적으로 SPDY와 동일합니다.

우선, 새로운 프로토콜을 둘러싼 몇 가지 오해부터 바로잡고자 합니다.

많은 사람이 HTTP/2를 HTTP/1의 새롭고 뛰어난 후속 프로토콜로 생각합니다. 하지만 저는 그렇게 생각하지 않습니다. 그 이유는 다음과 같습니다. HTTP/2는 사실 HTTP/1을 위한 또 하나의 전송 계층일 뿐입니다. 그렇다고 나쁜 것은 아닙니다. 덕분에 애플리케이션을 변경하지 않고도 HTTP/2를 사용할 수 있으며, 동일한 헤더도 그대로 사용할 수 있기 때문입니다. NGINX에서 HTTP/2를 활성화하기만 하면 NGINX가 모든 프로토콜 관련 작업을 알아서 원활하게 처리해 줍니다.

하지만 HTTP/2가 만능은 아닙니다. 장점과 단점이 분명히 있으며, 효과적으로 작동하는 사용 사례가 있는 반면 제대로 작동하지 않는 상황도 있습니다.

1:40 HTTP/2의 주요 기능

HTTP/2의 주요 특징은 바이너리 형식, 멀티플렉싱, HPACK 헤더 압축, 복잡한 우선순위 지정입니다.

HTTP/2는 SPDY를 기반으로 하며 매우 유사한 프로토콜이므로, SPDY의 새로운 버전이라고 생각할 수 있습니다. SPDY는 웹 콘텐츠 전송 속도를 높이기 위해 Google이 몇 년 전에 개발한 프로토콜입니다.

NGINX는 이미 2년 전부터 SPDY를 지원해 왔으므로, SPDY 모듈을 사용해 HTTP/2의 장점을 확인할 수 있습니다. 어떤 사람들은 HTTP/2가 단지 SPDY 3.1을 다듬은 버전일 뿐이라고 말하기도 합니다.

SPDY에 익숙하지 않은 분들을 위해 몇 가지 핵심 사항을 살펴보겠습니다. 이러한 핵심 사항은 HTTP/2에도 그대로 적용됩니다. 세부적인 차이는 있지만 기본적으로 동일한 프로토콜이기 때문입니다.

첫 번째 핵심은 프로토콜 자체가 바이너리 형식이라는 점입니다. 저는 바이너리 프로토콜을 좋아합니다. 코딩하기가 더 쉽고, 잘 설계된 바이너리 프로토콜은 성능 면에서도 몇 가지 이점이 있기 때문입니다. 하지만 이러한 접근 방식의 단점도 이해하고 있습니다.

3:08 HTTP/2 내부 – 바이너리

HTTP/2 요청의 페이로드는 바이너리 형식인 반면, HTTP/1.1 요청은 사람이 읽을 수 있는 텍스트 형식임을 보여 주는 슬라이드

여기 HTTP/2 요청이 있습니다. 꽤 멋져 보이고, 보시다시피 디버깅하기도 아주 쉽습니다. 아니요, 농담입니다. 디버깅하기 어렵습니다. 이것이 바이너리 프로토콜의 단점 중 하나입니다.

요청을 디코딩하려면 도구를 사용해야 할 수도 있습니다. 아니면… 때로는 도구가 제대로 작동하지 않거나 비트에 숨겨진 모든 세부 정보를 보여 주지 않을 수 있기 때문에 바이너리를 직접 디버깅해야 할 수도 있습니다.

다행히도 대부분의 경우 NGINX에 HTTP/2를 적용하기만 하면 되므로, 그 바이너리 특성을 직접 다룰 필요가 없습니다. 또한 다행히도 대부분의 요청은 기계가 처리합니다. 기계는 사람보다 바이너리 프로토콜을 훨씬 더 잘 읽습니다.

4:26 HTTP/2 내부 – 멀티플렉싱

HTTP/2는 단일 연결을 통해 요청과 응답을 다중화합니다

HTTP/2의 다음 핵심은 멀티플렉싱입니다. 여러 연결을 통해 응답과 요청을 각각 별도의 데이터 스트림으로 주고받는 대신, HTTP/2는 이를 하나의 바이트 스트림, 즉 하나의 데이터 스트림으로 다중화합니다. 서로 다른 요청과 응답의 데이터를 조각으로 나누며, 각 조각에는 고유 식별자와 크기 필드가 있어 엔드포인트가 어떤 데이터가 어떤 요청에 속하는지 판단할 수 있습니다.

여기서 단점은 각 데이터 조각에 고유한 식별자와 필드가 있기 때문에 실제 데이터 외에도 일부 메타데이터가 함께 전송된다는 점입니다. 따라서 어느 정도의 오버헤드가 발생합니다. 그 결과, 예를 들어 영화를 시청하는 경우처럼 데이터 스트림이 하나뿐이라면 HTTP/2는 적합한 프로토콜이 아닙니다. 추가적인 오버헤드만 발생하기 때문입니다.

멀티플렉싱의 장점은 무엇일까요? 멀티플렉싱의 가장 큰 장점은 단일 연결만 사용하므로 새 요청을 생성할 때 HTTP/1.x에서 핸드셰이크에 소요되는 시간을 모두 절약할 수 있다는 것입니다.

이러한 지연은 TLS를 사용할 때 특히 큰 문제가 됩니다. 그래서 현재 대부분의 클라이언트는 TLS를 통한 HTTP/2만 지원합니다. 제가 알기로는 일반 TCP를 통한 HTTP/2는 이점이 크지 않아 이를 지원할 계획이 없습니다. TCP 핸드셰이크는 TLS 핸드셰이크만큼 비용이 많이 들지 않으므로 여러 연결을 피하더라도 여기서 절약할 수 있는 부분이 많지 않기 때문입니다.

7:09 HTTP/2의 주요 기능 – 헤더 압축

HTTP/2는 헤더 압축을 위해 특별히 설계된 HPACK 알고리즘을 사용합니다

HTTP/2의 다음 핵심 사항은 헤더 압축입니다. 쿠키가 매우 크다면 요청이나 응답마다 수백 바이트를 절약할 수 있지만, 일반적으로는 헤더 압축의 이점을 크게 누리지 못하는 경우가 대부분입니다. 개별 요청을 따로 생각하더라도 결국 네트워크의 패킷 계층을 거치게 되므로, 100바이트를 보내든 150바이트를 보내든 어차피 하나의 패킷으로 전송된다는 점에서는 큰 차이가 없기 때문입니다.

HTTP/2 헤더 압축의 단점은 상태를 유지한다는 점입니다[편집자 – 압축/압축 해제 정보를 저장하는 데 사용되는 테이블을 의미합니다]. 따라서 서버와 클라이언트는 각 연결에 대해 일정한 상태 정보를 유지해야 하며, 이는 HTTP/1 연결의 상태를 유지하는 것보다 훨씬 많은 메모리를 소모합니다. 결과적으로 각 HTTP/2 연결은 훨씬 더 많은 메모리를 사용하게 됩니다.

8:40 HTTP/2의 주요 기능 – 우선순위 지정

HTTP/2의 우선순위 지정 메커니즘은 채널이 하나뿐일 때 가장 중요한 데이터를 먼저 전송해야 하는 문제를 해결합니다.

HTTP/2의 마지막 핵심은 우선순위 지정 메커니즘입니다. 이는 멀티플렉싱으로 인해 발생한 문제를 해결합니다. 연결이 하나뿐이면 데이터 전송 경로도 하나뿐이므로, 다음에 어떤 응답을 이 경로로 보낼지 신중하게 결정해야 합니다.

HTTP/2에서 우선순위 지정은 선택 사항이지만, 이를 사용하지 않으면 성능상 큰 이점을 얻을 수 없습니다. NGINX의 HTTP/2 모듈은 우선순위 지정을 완벽하게 지원하며, 가중치 기반 우선순위와 종속성 기반 우선순위를 모두 지원합니다. 지금까지 확인한 바로는 현재 가장 빠른 HTTP/2 구현체를 제공하고 있습니다. 이상이 HTTP/2의 핵심 사항입니다.

10:06 HTTP/2의 역사

NGINX 릴리스의 SPDY 및 HTTP/2 지원 역사를 요약한 슬라이드

HTTP/2의 역사를 간략히 살펴보는 슬라이드입니다. 비교적 이해하기 쉽습니다. 이제 HTTP/2가 실제로 어떻게 작동하는지 알아보겠습니다.

10:16 테스트 페이지

NGINX HTTP/2 모듈의 성능을 테스트하는 데 사용되는 일반적인 리소스 유형이 혼합된 웹 페이지

다양한 네트워크 환경에서 HTTP/2가 어떻게 작동하는지 알아보기 위해 일반적인 웹페이지를 대상으로 몇 가지 벤치마크 테스트를 진행했습니다. 이 페이지는 Github에서 찾은 HTTP/2 페이지입니다. 포함된 리소스의 수와 각 리소스의 크기를 확인할 수 있습니다. 일반적인 사이트의 특성을 상당히 잘 보여주는 페이지라고 생각합니다.

10:52 테스트 환경

NGINX HTTP/2 모듈 테스트에 사용된 하드웨어, 소프트웨어 및 NGINX 구성을 설명하는 슬라이드

테스트를 재현하고 싶은 분들을 위해 제가 사용한 테스트 환경을 소개합니다.

11:02 DOM 로드

지연 시간이 서로 다른 네트워크에서 HTTP/1, HTTP/2 및 HTTPS의 다운로드 시간을 비교한 막대그래프

그리고 이것이 제가 얻은 결과입니다. X축에는 서로 다른 네트워크 지연 시간을 밀리초 단위의 왕복 시간(RTT)으로 시뮬레이션했고, Y축에는 역시 밀리초 단위로 다운로드 시간을 측정한 것을 볼 수 있습니다. 이 테스트에서는 페이지의 모든 리소스가 완전히 로드될 때까지 걸리는 시간을 페이지 로딩 시간으로 측정합니다.

그래프를 보면 지연 시간이 짧을 때는 HTTP, HTTPS, HTTP/2 간에 큰 차이가 없다는 뚜렷한 경향을 확인할 수 있습니다. 지연 시간이 길어지면 일반 HTTP/1.x가 가장 빠르고, HTTP/2가 그다음이며, HTTPS가 가장 느립니다.

11:48 최초 페인팅

지연 시간이 서로 다른 네트워크에서 HTTP/1, HTTP/2 및 HTTPS를 사용할 때 웹 페이지의 첫 번째 요소가 표시되기까지 걸리는 시간을 비교한 막대그래프

‘최초 페인트’ 시간은 어떨까요? 사용자가 실제로 화면에서 무언가를 보게 되는 시점이므로, 많은 경우 사용자 관점에서 가장 중요한 지표입니다. 페이지가 완전히 로드되는 데 걸리는 시간보다 사용자가 무언가를 보기까지 걸리는 시간이 훨씬 더 중요한 경우가 많습니다.

여기서도 동일한 추세를 확인할 수 있지만, 이번 테스트에서 흥미로운 점은 30ms에서 250ms 사이의 중간 범위 지연 시간에서는 그 차이가 매우 작기는 해도 HTTP/2가 일반 HTTP보다 약간 더 빠르다는 것입니다.

12:45 구성

HTTP/2 모듈이 포함된 NGINX 바이너리를 빌드하기 위한 요구 사항과 명령줄 인수, 그리고 구성에서 HTTP/2를 활성화하는 지시어를 설명하는 슬라이드

지금까지 벤치마크 결과를 살펴보았으니, 이제 HTTP/2와 NGINX를 구성하는 방법에 대해 알아보겠습니다.

사실 매우 간단합니다. http2 매개변수를 listen 지시어에 추가하기만 하면 됩니다. 여기서 가장 복잡한 단계는 아마 최신 버전의 OpenSSL을 구하는 것일 텐데, HTTP/2에는 ALPN[애플리케이션 계층 프로토콜 협상] 확장이 필요하고 이 확장은 OpenSSL 1.0.2에서만 지원되기 때문입니다.

또한 HTTP/2를 위해 NPN[차기 프로토콜 협상]도 구현했습니다. 현재는 대부분의 클라이언트에서 작동하지만, 2016년 초에 SPDY가 폐기됨에 따라 NPN 지원도 제거될 예정입니다. 따라서 현재 여러 Linux 배포판에 포함된 OpenSSL 버전으로도 HTTP/2를 사용할 수 있지만, 가까운 시일 내에 작동하지 않게 된다는 점을 유의해야 합니다.

이상으로 HTTP/2를 위한 NGINX 구성에 대한 설명과 제 발표를 마치겠습니다. 감사합니다.

[다음에 대한 참조 문서: HTTP/2 모듈]

질문과 답변

Q: 업스트림 측에서도 HTTP/2를 지원할 예정인가요, 아니면 클라이언트 측에서만 HTTP/2를 지원할 예정인가요?

A: 현재는 클라이언트 측에서만 HTTP/2를 지원합니다. proxy_pass로는 HTTP/2를 구성할 수 없습니다. [편집자 주 – 이 게시물의 원본 버전에서는 이 문장이 “HTTP/2를 구성할 수 있습니다. 사용 명령은 proxy_pass입니다.”라고 잘못 옮겨졌습니다. 이로 인해 혼란을 드렸다면 사과드립니다.]

하지만 백엔드 측에서 HTTP/2를 사용하는 것이 무슨 의미가 있을까요? 벤치마크에서 볼 수 있듯이 업스트림 연결과 같은 저지연 네트워크에서는 HTTP/2를 사용해도 큰 이점이 없기 때문입니다.

또한 NGINX에는 keepalive 모듈이 있으며, keepalive 캐시를 구성할 수 있습니다. HTTP/2의 주된 성능상 이점은 추가 핸드셰이크를 없애는 것이지만, keepalive 캐시를 통해 이미 그렇게 하고 있다면 업스트림 측에는 HTTP/2가 필요하지 않습니다.

HTTP/2 관련 추가 자료

현재 환경에서 NGINX Plus로 HTTP/2를 사용해 볼 준비가 되셨나요? 지금 30일 무료 체험을 시작하거나 사용 사례에 대해 논의하려면 문의해 주세요.


공유
태그: F5 NGINX, 2016, Tech

관련 블로그 게시물

시청하기: KubeCon North America 2023에서의 NGINX Gateway Fabric
NGINX | 2023. 11. 30.

시청하기: KubeCon North America 2023에서의 NGINX Gateway Fabric

이 영상에서는 KubeCon의 NGINX 부스를 찾아가, 저희가 공개한 Kubernetes Gateway API 구현을 살펴봅니다.

F5 NGINX로 대규모 WAF 플릿을 확인하고 관리하는 2가지 방법
NGINX | 2023. 03. 23.

F5 NGINX로 대규모 WAF 플릿을 확인하고 관리하는 2가지 방법

앱 보안을 강화하는 두 가지 방법을 소개합니다. NGINX Management Suite를 통해 WAF 운영에 대한 가시성을 높이고, NGINX App Protect WAF를 활용해 코드형 보안을 구현하는 것입니다.

Ingress 컨트롤러 선택 가이드, 4부: NGINX Ingress Controller 옵션
NGINX | 2021. 09. 27.

Ingress 컨트롤러 선택 가이드, 4부: NGINX Ingress Controller 옵션

개발 주체, 개발 철학, 프로덕션 환경 준비도, 보안 및 지원을 기준으로 어떤 NGINX Ingress 컨트롤러가 가장 적합한지 알아보세요.

진화하는 공격 환경에 NGINX App Protect Denial of Service가 적응하는 방법
NGINX | 2021. 07. 06.

진화하는 공격 환경에 NGINX App Protect Denial of Service가 적응하는 방법

NGINX App Protect Denial of Service(DoS)가 계층 7 DoS 공격을 방어하기 위해 완화 방법을 실시간으로 조정하는 방식을 설명합니다. 정상적인 사용자 행동과 서버 상태에 대한 모델을 생성하여 공격을 나타내는 이상 징후를 감지하고 맞춤형 완화 시그니처를 적용할 수 있습니다.

NGINX Instance Manager를 활용한 대규모 구성 업데이트 및 인증서 관리
NGINX | 2021. 06. 30.

NGINX Instance Manager를 활용한 대규모 구성 업데이트 및 인증서 관리

NGINX Instance Manager 버전 1.0에는 두 가지 새로운 기능이 도입되었습니다. NGINX 인스턴스에 태그와 사용자 역할을 지정하면 전체 그룹에 구성을 한 번에 적용할 수 있습니다. 인증서 검사는 만료 예정인 인증서를 감지하여 서비스 중단을 방지할 수 있도록 인증서를 교체할 수 있게 해줍니다.

Netflix가 자사 CDN의 핵심으로 NGINX를 선택한 이유
NGINX | 2015. 03. 25.

Netflix가 자사 CDN의 핵심으로 NGINX를 선택한 이유

Netflix가 글로벌 콘텐츠 전송 네트워크인 Open Connect의 스트리밍 미디어 기술로 NGINX를 선택한 이유를 NGINX 개발자 Gleb Smirnoff에게서 알아보세요.