HTTP/1.1, HTTP/2, HTTP/3는 status code와 method 같은 HTTP 의미를 새로 바꾼 버전이 아니다. 같은 HTTP semantics를 전달하는 message framing과 transport 방식이 달라졌다.
핵심 차이는 세 문장으로 줄일 수 있다.
- HTTP/1.1은 한 연결에서 응답 순서에 제약이 있고, 병렬 처리를 위해 여러 TCP 연결을 쓰는 경우가 많다.
- HTTP/2는 한 TCP 연결에서 여러 stream을 multiplexing하고 header를 HPACK으로 압축한다.
- HTTP/3는 HTTP semantics를 QUIC 위에 매핑해 stream 간 전송 의존을 줄이고 연결 수립과 이동성 측면을 개선한다.
먼저 HTTP semantics와 전송을 나눈다
GET, POST, 200 OK, cache와 content negotiation 같은 의미는 RFC 9110에 정의된다. HTTP/1.1·2·3은 이 의미를 wire에서 어떻게 표현하고 전달하는지가 다르다.
| 항목 | HTTP/1.1 | HTTP/2 | HTTP/3 |
|---|---|---|---|
| 주된 transport | TCP | TCP | QUIC(UDP 기반) |
| framing | text 형식의 message | binary frame | QUIC stream 위 binary frame |
| 한 연결의 병렬 request | protocol multiplexing 없음 | 여러 stream multiplexing | 여러 QUIC stream multiplexing |
| header compression | 기본 제공 없음 | HPACK | QPACK |
| transport security | HTTP 자체와 별도, HTTPS에서 TLS | 실제 browser 사용은 주로 TLS | QUIC이 TLS 1.3 handshake를 통합 |
서버와 client가 같은 HTTP version을 지원해야 하므로 실제 서비스에서는 negotiation과 fallback도 중요하다. URL만 보고 version이 고정되는 것은 아니다.
HTTP/1.1: 지속 연결은 있지만 multiplexing은 없다
HTTP/1.1은 기본적으로 persistent connection을 사용할 수 있어 매 요청마다 TCP connection을 새로 만들 필요는 없다. 이 점은 HTTP/1.0 초기 사용 방식과 큰 차이다.
하지만 한 TCP connection에 여러 request를 동시에 독립 stream으로 싣는 protocol layer가 없다. pipelining이 정의돼 있어도 response는 request 순서대로 대응해야 하고, 중간 응답이 늦으면 뒤 응답도 전달 순서의 영향을 받는다. 그래서 browser는 한 origin에 여러 TCP connection을 열어 병렬성을 확보해 왔다.
HTTP Keep-Alive의 동작과 한계를 보면 지속 연결과 동시 처리 능력이 같은 개념이 아닌 이유를 확인할 수 있다.
HTTP/2: 한 TCP 연결 위의 여러 stream
HTTP/2는 message를 frame으로 나누고 각 frame에 stream을 구분하는 정보를 둔다. 한 TCP connection 안에서 여러 request와 response의 frame을 교차 전송할 수 있으므로 application layer의 순차 대기를 크게 줄인다.
주요 변화는 다음과 같다.
- binary framing
- stream multiplexing
- HPACK header compression
- stream별 flow control과 priority 관련 기능
- protocol 차원의 server push
여기서 “HTTP/2는 head-of-line blocking을 완전히 없앴다”라고 하면 절반만 맞다. HTTP/1.1 message 순서 문제는 줄였지만 모든 stream이 하나의 TCP byte stream을 공유한다. packet 하나가 손실되면 TCP가 순서를 복구할 때까지 그 connection의 뒤 byte 전달이 지연될 수 있다.
Server Push도 HTTP/2의 필수 장점으로만 계산하면 안 된다. protocol에 기능은 있지만 client 지원과 cache 상호작용, 잘못 예측한 resource 전송 비용 때문에 운영 효과는 환경에 따라 달라진다.
HTTP/3: QUIC stream으로 전송 의존을 줄인다
HTTP/3는 HTTP semantics를 QUIC transport 위에 올린다. QUIC은 UDP datagram을 이용하지만, application에 단순한 비신뢰성 전송을 그대로 노출하지 않는다. QUIC 자체가 encryption, congestion control, reliable per-stream delivery와 stream multiplexing을 제공한다.
중요한 차이는 stream별 순서 복구다. 한 stream에서 packet loss가 발생해도 손실된 data가 필요 없는 다른 stream은 계속 진행할 수 있다. HTTP/2가 TCP connection 전체의 byte 순서에 묶이는 것과 다르다.
그렇다고 packet loss 영향이 사라지는 것은 아니다. loss recovery와 congestion control은 여전히 작동하고 connection 전체의 전송률이 낮아질 수 있다. 정확한 표현은 손실로 인한 application stream 간 head-of-line blocking을 줄인다는 것이다.
QUIC은 TLS 1.3 handshake를 transport handshake와 결합하고 connection ID를 사용한다. network가 Wi-Fi에서 mobile network로 바뀌어 IP가 달라지는 상황에서도 조건이 맞으면 connection을 이어 갈 수 있다. 다만 이것도 server, client와 network 환경의 지원이 필요하다.
어떤 버전을 선택해야 하나
application code에서 하나만 강제로 고르는 문제라기보다 server, CDN, load balancer와 client가 함께 지원하는 version을 안전하게 협상하는 문제다.
- 오래된 client와 중간 장비 호환성이 중요하면 HTTP/1.1 fallback을 유지한다.
- 대부분의 HTTPS service는 HTTP/2를 켜서 한 connection의 동시 request 효율을 얻을 수 있다.
- mobile network, packet loss와 connection setup 비용이 중요한 service라면 HTTP/3를 측정해 본다.
- version 이름만 보고 성능을 단정하지 말고 TTFB, LCP, connection reuse, loss, CPU와 CDN log를 함께 본다.
TCP loss와 congestion window가 실제 지연에 미치는 영향은 TCP 혼잡 제어에서 더 자세히 볼 수 있다.
확인 방법
curl이 HTTP/2·3 지원으로 build돼 있다면 negotiated version을 확인할 수 있다.
curl --http1.1 -sS -o /dev/null -w '%{http_version}\n' https://example.com
curl --http2 -sS -o /dev/null -w '%{http_version}\n' https://example.com
curl --http3 -sS -o /dev/null -w '%{http_version}\n' https://example.com
설치된 curl이 해당 protocol을 지원하지 않거나 server가 제공하지 않으면 command가 실패할 수 있다. browser 개발자 도구의 Network panel에서도 protocol column을 표시해 실제 request가 h2, h3 중 무엇으로 처리됐는지 확인할 수 있다.
자주 묻는 질문
HTTP/3는 UDP라서 data를 잃어도 그냥 넘어가나?
아니다. QUIC은 UDP 위에서 동작하지만 HTTP/3에 필요한 reliable delivery, loss recovery와 congestion control을 제공한다. UDP를 사용한다는 사실과 application data가 비신뢰적으로 전달된다는 결론은 같지 않다.
HTTP/2를 쓰면 TCP connection은 하나뿐인가?
한 origin의 여러 request를 한 connection에 multiplexing할 수 있다는 뜻이다. 인증서, origin coalescing 조건, connection 장애, browser 정책 등에 따라 실제 connection 수는 달라질 수 있다.
HTTP/3가 항상 가장 빠른가?
아니다. network 품질, RTT, packet loss, server와 CDN 구현, CPU 비용, resource 구성에 따라 결과가 달라진다. protocol enablement 뒤 실제 사용자 지표로 확인해야 한다.
참고 자료
'배움과 성장 > 네트워크·보안' 카테고리의 다른 글
| SSH와 Telnet 차이: 원격 접속에서 Telnet을 운영에 쓰면 안 되는 이유 (0) | 2024.08.15 |
|---|---|
| 웹 1.0·2.0·3.0 차이: 버전이 아니라 참여 방식의 변화 (0) | 2024.08.13 |
| REST·GraphQL·gRPC·WebSocket 차이: API 통신 방식 고르는 기준 (0) | 2024.08.13 |
| 세션 ID·쿠키·OAuth 토큰·JWT 차이: 식별자와 자격 증명 구분하기 (0) | 2024.08.13 |
| NAT와 NAPT 차이: IP 변환·포트 변환·포트 포워딩 구분 (0) | 2024.08.12 |
댓글