nginx http2 설정 (feat. http/1.x 부터 http/3)

TIL/ETC|2025. 8. 5. 21:12

 

최근 프록시 서버로써 nginx에서 http2를 설정하면서 알아본 내용을 간략하게 정리해 본다.

더보기
server {
    listen 443 ssl; # 예전에는 이 뒤에 http2를 붙였지만
    http2 on; # 이제 이렇게 합니다

    ssl_certificate ssl/certificate.pem;
    ssl_certificate_key ssl/key.pem;

    location = / {
    	...
    }
}

 

HTTP가 뭔데?

널리 알려져있다시피, HTTP는 HyperText Transfer Protocol 의 줄임말이다.

HyperText를 전송하는 프로토콜이라고 직역할 수 있다.

html 페이지에서 <a> 태그로 생성한 요소를 클릭하면 다른 페이지로 이동하게 되는데,

이렇게 링크를 통해 다른 페이지로 연결이 될 수 있도록 하는 개념을 하이퍼텍스트라고 한다.

즉, 일반 텍스트와 달리, 링크를 통해 다른 문서나 정보로 즉시 이동할 수 있도록 연결된 텍스트를 의미한다.

파일을 주고받는 FTP와 마찬가지로, HyperText를 주고 받기 위한 통신규약이 HTTP라고 할 수 있다.

 

이렇게 데이터를 주고 받기 위해서는 요청을 보낸 사람의 IP 주소나 데이터의 종류, 필요한 정보들이 있을 것이고, 

요청과 응답을 보낼 때는 이러이러한 양식을 지켜 보내 주십시오~ 하는 것이 프로토콜인 것이다.

 

 

태초에 HTTP/0.9가 있었다. - https://httpwg.org/specs/

지금으로부터 약 34년 전.. HTTP/0.9가 있었다.

웹의 시작으로, 텍스트 기반에 GET만 지원됐으며, HTTP 헤더 없이 HTML만 전송하는 단순한 구조였다.

 

여기서 요청/응답 구조를 도입하고 헤더를 사용하며 요청마다 새로운 TCP 연결을 사용하는 HTTP/1.0이 발표됐다.

매번 새로운 TCP 연결을 사용하는 것은 성능적으로 매우 비효율적이었기 때문에...

 

그 이후, HTTP/1.1에서 지속 연결(Keep-Alive) 속성으로 기존 연결을 재사용할 수 있게 되었고,

캐싱, 압축과 같은 성능 개선 기능이 추가되었다. 

또한 Host 헤더가 추가되면서 가상 호스팅이 가능해졌고, 하나의 IP에 여러 도메인을 운영할 수 있게 되었다.

Head-Of-Line Blocking이 발생한다는 문제점이 있었지만, 여전히 많은 서버에서 기본값으로 사용하고 있다.

 

 

HTTP/2 -  https://httpwg.org/specs/rfc9113.html

HTTP 메서드, 상태 코드, 의미 체계는 동일하게 가져가면서 성능과 지연 시간, 네트워크/서버 자원 사용량을 개선한 버전이다.

저지연성을 위해 설계된 프로토콜인 SPDY(SPeeDY)를 기반으로 설계되었으나, 여러 가지 개선사항이 포함됐다.

주요 목표는 브라우저에서 웹사이트로 진정한 의미의 단일 연결을 사용할 수 있도록 하는 것이다. 

 

텍스트 대신 바이너리를 전송하는 Binary Framing 의 추가로 전송 성능이 좋아졌고,

또한 멀티플렉싱(Multiplexing, 요청 다중화)을 이용해 하나의 연결에서 여러 데이터 스트림을 동시에 보내고 받을 수 있게 되었다!

즉, 하나의 TCP 연결로 HTTP/1.1보다 안정적으로 여러 요청과 응답을 처리할 수 있게 되었다.

하지만 TCP 위에서 동작하기 때문에 HOL Blocking 문제는 여전히 존재한다.

 

 

그런 당신을 위한 HTTP/3 - https://httpwg.org/specs/rfc9114.html

TCP 기반의 HTTP/2에서 HTTP/3로 넘어오면서,

UDP 기반의 QUIC(Quick UDP Internet Connections) 프로토콜을 도입했다.

이로써 TCP의 한계를 근본적으로 제거할 수 있었고, HOL Blocking 이슈도 완전히 해결되었다.

 

이게 무슨 소리냐 하면...

TCP와 UDP는 둘 다 IP 위에서 작동하는 전송 계층 프로토콜이다.

https://blog.smartbuildingsacademy.com/what-is-the-osi-model

 

그 말은, 데이터를 어떤 방식으로 나눠서 보내고 도착하게 할 지 정하는 프로토콜이라는 것이다.

 

 

TCP

TCP는 데이터를 순서대로 처리하며, 데이터 신뢰성을 보장하기 때문에...

반드시 데이터(패킷)를 순차적으로 전송하며, 중간에 하나라도 손실되는 경우에는

이후 도착한 데이터도 처리되지 않고 손실된 패킷이 다시 전송되어 도착할 때까지 대기하게 된다.

 

그리고 연결 지향의 프로토콜이기 때문에 연결을 만들기 위해 SYN → SYN-ACK → ACK 의 3단계 handshake가 필요하다.

TLS 보안 연결을 위해 요구되는 추가 handshake 까지 포함하면 초기 연결 지연이 커진다.

또한 연결 상태를 서버가 메모리에 보관해야 하기 때문에 동시 접속 수가 많을 수록 자원에 부담을 주게 된다.

이 때문에 UDP에 비해 상대적으로 전송 속도가 느리지만 정확하게 전달하는 게 목적이라고 볼 수 있다.

이런 식으로 연결을 만들고 유지하기 위해 필요한 자원을 Overhead 라고 한다.

 

UDP

하지만 UDP는 비연결 지향(Connectionless)으로, handshake가 필요 없다.

데이터 손실, 순서, 중복에 대한 신뢰성을 보장하지 않고, 전송 속도가 빠르며 handshake가 없어 오버헤드도 작다.

이러한 특성 때문에 영상 스트리밍이나 게임, 음성통화 등 실시간성이 중요한 서비스에서 많이 사용된다.

 

QUIC

QUIC는 구글이 개발한 전송 계층 프로토콜로, 기존의 TCP+TLS 를 완전히 대체할 수 있도록 설계됐다.

우선 UDP 기반이기 때문에 순서 처리를 보장하지 않아 검사가 필요 없고, 

HTTP/2와 마찬가지로 하나의 연결 안에서 독립된 스트림을 병렬 처리하는 Multiplexing이 지원된다.

그리고 0-RTT(Zero-Round Trip Time)로 한 번 연결했던 서버에는 즉시 데이터를 전송할 수 있고,

물론 이에 따른 보안 이슈도 존재한다. https://en.wikipedia.org/wiki/Replay_attack

TLS 1.3이 QUIC에 내장되어 있어 TCP 기반의 HTTP/2에 비해 별도 설정할 필요가 없다.

 

점차 확산되고 있는 추세이며, 구글이나 유튜브 등 대형 서비스에서 적극적으로 사용하고 있다.

구글 검색 페이지에서 개발자 도구를 보면 h3이라고 나와 있다.

 

그럼에도 불구하고! 데이터 신뢰성을 따져봤을 때는 꼭 HTTP/3이 HTTP/2가 우월하다고 볼 수는 없다.

 

 

HTTP 버전별 비교

버전 발표 연도 특징
HTTP/0.9 1991  - 최초의 HTTP
 - GET 요청만 지원
 - 헤더 없음, HTML만 전송
HTTP/1.0 1996  - 요청/응답 구조 정립
 - 헤더 추가
 - 요청마다 새로운 TCP 연결 생성
HTTP/1.1 1997  - 지속 연결(Keep-Alive) 지원
 - 파이프라이닝(Pipelining) 도입
 - 호스트 가상화(Host header) 지원
 - 현재까지도 많이 사용됨
HTTP/2 2015  - 바이너리 프레이밍(Binary Framing)
 - 멀티플렉싱(Multiplexing): 하나의 연결로 여러 요청/응답 처리 가능
 - 헤더 압축 (HPACK)
 - 성능 개선
HTTP/3 2022  - TCP 대신 QUIC(UDP 기반) 사용
 - 연결 속도 향상 (0-RTT 지원)
 - 헤드 오브 라인 블로킹 문제 제거
 - 최신 브라우저에서 점차 도입 중

 

 

nginx에서 설정 방법

https://nginx.org/en/docs/http/ngx_http_v2_module.html

server {
    listen 443 ssl http2; # 그냥 뒤에 http2만 추가하면 끝

    ssl_certificate ssl/certificate.pem;
    ssl_certificate_key ssl/key.pem;

    location = / {
    	...
    }
}

과거에는 이렇게 했으나, 현재 이 옵션은 deprecated 되었다.

이렇게 하면 nginx를 재시작할 때 경고 메시지가 뜰 것이다...

 

위처럼 해도 작동은 하지만, deprecated되었으므로 아래처럼 진행하자.

server {
    listen 443 ssl;
    http2 on; # 이제 이렇게 합니다

    ssl_certificate ssl/certificate.pem;
    ssl_certificate_key ssl/key.pem;

    location = / {
    	...
    }
}

 

nginx에서 http3도 지원하긴 하지만 아직 실험적이다. 

nginx 1.25.0 버전부터 공식 지원하고 있다.

https://nginx.org/en/docs/http/ngx_http_v3_module.html?ref=log.somni.one

 

적용됐는지 확인은 어떻게?

개발자 도구에서 필터 추가해서 h2가 뜨면 적용완료.

적용 전
적용 후

 

https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/Evolution_of_HTTP