LabHub

블로그

HTTP/3 & QUIC 심화 완전 가이드 2025: 0-RTT, Connection Migration, 멀티플렉싱

TL;DR


1. HTTP의 진화

1.1 HTTP/1.0 (1996)

GET /index.html HTTP/1.0

HTTP/1.0 200 OK
Content-Type: text/html
Content-Length: 1234

<html>...</html>

특성:

문제: 연결 비용 폭증.

1.2 HTTP/1.1 (1997)

개선:

여전한 문제:

1.3 HTTP/2 (2015)

대혁신:

개선 효과:

여전한 문제:

1.4 HTTP/3 (2022)

전송 계층 교체:

이건 단순 업데이트가 아니라 근본적 재설계입니다.


2. TCP의 문제들

2.1 핸드셰이크 비용

[Client]                          [Server]
   │                                 │
   ├──── TCP SYN ──────────────────→│  ← 1 RTT
   │←─── SYN+ACK ───────────────────┤
   ├──── ACK ──────────────────────→│
   │                                 │
   ├──── TLS ClientHello ──────────→│  ← 1 RTT
   │←─── ServerHello, Certificate ──┤
   ├──── Finished ─────────────────→│  ← 1 RTT
   │←─── Finished ──────────────────┤
   │                                 │
   ├──── HTTP Request ─────────────→│  ← 1 RTT
   │←─── HTTP Response ─────────────┤

총 4 RTT. 100ms 핑이면 400ms 첫 응답.

2.2 Head-of-Line Blocking

TCP 연결 (HTTP/2):
  Stream 1: ●●●●●● (이미지)
  Stream 2: ●●●●●● (CSS)
  Stream 3: ●●●●●● (JS)

패킷 손실 발생:
  ●●●❌●●  ← 손실
  TCP가 재전송 + 재정렬 대기
  Stream 1, 2, 3 모두 멈춤! ← 한 stream의 손실이 전체 차단

근본 원인: TCP는 byte stream만 알고, HTTP/2 stream은 모름.

2.3 Connection Migration 불가능

TCP 연결 = (src_ip, src_port, dst_ip, dst_port) 4-tuple.

모바일 시나리오:

  1. 카페 WiFi에서 Netflix 시청
  2. 카페 나옴 → 4G로 전환
  3. IP 변경 → 연결 끊김
  4. 새 연결 + 인증 + 비디오 buffering

사용자 경험: 끊김.

2.4 TCP의 근본적 한계

이 문제들은 TCP를 패치할 수 없습니다:


3. QUIC의 등장

3.1 Google의 시도

2012: Google이 내부에서 QUIC 시작. 2013: Chrome에 실험적 배포. 2018: IETF 표준화 시작. 2021: RFC 9000 (QUIC 표준). 2022: RFC 9114 (HTTP/3 표준).

3.2 왜 UDP?

UDP는 단순함:

QUIC가 사용자 공간에서 모든 것을 구현.

3.3 QUIC의 핵심 아이디어

┌─────────────────────┐
HTTP/3├─────────────────────┤
QUIC         │  ← 사용자 공간
  (Streams, TLS,Reliability,Flow Control)├─────────────────────┤
UDP          │  ← 커널
├─────────────────────┤
IP└─────────────────────┘

효과:


4. QUIC의 혁신

4.1 0-RTT 핸드셰이크

처음 연결 (1-RTT):

[Client]                          [Server]
   │                                 │
   ├──── Initial (TLS ClientHello) →│  ← 1 RTT
   │←─── Initial (ServerHello,     ─┤
Certificate, Finished)   ├──── HTTP Request ─────────────→│

TCP+TLS의 4 RTT → 1 RTT.

재방문 (0-RTT):

[Client]                          [Server]
   │                                 │
   ├──── Initial + HTTP Request ───→│  ← 0 RTT!
   │←─── Response ──────────────────┤

이전 세션의 키를 캐시 → 첫 패킷에 데이터 포함.

4.2 0-RTT의 보안

Replay attack 위험:

해결:

4.3 Stream 멀티플렉싱

QUIC 연결:
  Stream 1: ●●●●●●
  Stream 2: ●●●●●●
  Stream 3: ●●●●●●
  
패킷 손실:
  Stream 2: ●●●❌●●  ← Stream 2만 영향
  Stream 1: ●●●●●●  ← 영향 없음 ✅
  Stream 3: ●●●●●●  ← 영향 없음 ✅

핵심: 각 stream이 독립적인 순서 보장. HTTP/2의 HOL blocking 해결.

4.4 Connection Migration

QUIC 연결 = Connection ID (4-tuple X).

모바일 시나리오:

  1. WiFi에서 영상 시청 (Connection ID: ABC123)
  2. 4G로 전환 (IP 변경)
  3. 같은 Connection ID로 계속
  4. 서버가 인식 → 끊김 없이 계속

NAT rebinding에도 강함:

4.5 Forward Error Correction (선택)

일부 QUIC 구현은 FEC 지원:


5. QUIC vs TCP 상세 비교

5.1 핸드셰이크

TCP+TLS 1.3QUIC
첫 연결2-3 RTT1 RTT
재연결1-2 RTT0 RTT

5.2 HOL Blocking

TCPQUIC
패킷 손실 시모든 stream 차단해당 stream만

5.3 Connection Migration

TCPQUIC
IP 변경연결 끊김유지
NAT rebinding끊김유지

5.4 암호화

TCP+TLSQUIC
암호화TLS over TCP통합 (의무)
메타데이터일부 노출거의 모두 암호화

5.5 진화 속도

TCPQUIC
위치커널사용자 공간
업데이트OS 업데이트 필요앱 업데이트만

6. HTTP/3의 변화

6.1 메시지 형식

HTTP/2 (이진):

프레임 헤더 + 페이로드

HTTP/3 (QUIC 위):

6.2 헤더 압축

HTTP/2: HPACK HTTP/3: QPACK

QPACK이 HPACK과 다른 이유:

6.3 Server Push

HTTP/2 Server Push: 사실상 deprecated (Chrome 106+ 비활성). HTTP/3: Server Push 옵션, 거의 사용 안 함.

대안: 103 Early Hints.

6.4 새로운 응답 코드

103 Early Hints:

HTTP/2 103 Early Hints
Link: </styles.css>; rel=preload; as=style
Link: </script.js>; rel=preload; as=script

HTTP/2 200 OK
Content-Type: text/html
...

서버가 본 응답 전에 "이런 자원을 미리 받으세요"라고 힌트. Server Push의 더 좋은 대안.


7. 성능 벤치마크

7.1 페이지 로딩 시간

Cloudflare 데이터 (HTTP/2 → HTTP/3):

Google 데이터 (YouTube):

Facebook 데이터:

7.2 패킷 손실 환경

1% 패킷 손실 (좋은 모바일 환경):

5% 패킷 손실 (나쁜 환경):

QUIC가 진가를 발휘하는 환경: 모바일, 멀리 떨어진 사용자.

7.3 CPU 사용량

문제: QUIC는 사용자 공간에서 작동 → CPU 부담.

HTTP/2 (TCP): 커널이 모든 것 처리
HTTP/3 (QUIC): 사용자 공간에서 처리

서버:

해결책:


8. 배포

8.1 어떻게 시작?

Alt-Svc 헤더:

HTTP/2 200 OK
Alt-Svc: h3=":443"; ma=86400

브라우저가 다음 요청부터 HTTP/3로 시도. 실패 시 HTTP/2로 fallback.

효과: 점진적 마이그레이션, 위험 없음.

8.2 서버 옵션

Nginx:

server {
    listen 443 quic reuseport;
    listen 443 ssl;
    
    http2 on;
    http3 on;
    
    add_header Alt-Svc 'h3=":443"; ma=86400';
}

Caddy: 자동 (HTTPS 자동 + HTTP/3 자동).

example.com {
    root * /var/www
    file_server
}

이게 전부. HTTP/3 자동 활성화.

8.3 CDN

HTTP/3 지원:

→ CDN 사용 시 이미 HTTP/3 사용 중일 가능성 높음.

8.4 클라이언트 지원

브라우저 (2024년 말):

라이브러리:

8.5 방화벽 문제

기업 방화벽이 UDP를 차단하는 경우:

문제: Latency 증가 (실패 → fallback).


9. 디버깅과 모니터링

9.1 Wireshark

QUIC 디코딩 지원 (Wireshark 3.4+):

9.2 qlog

QUIC 표준 로깅 형식:

도구:

9.3 Chrome DevTools

chrome://net-export/  → 네트워크 로그
chrome://flags/#enable-quic

9.4 OpenSSL은 안 됨

OpenSSL은 QUIC 지원이 늦음 (2024년 OpenSSL 3.2+ 부분 지원).

대안:


10. 미래

10.1 HTTP/3의 채택

2024년 말:

10.2 MASQUE

QUIC 위의 프록시 프로토콜:

Apple Private Relay: MASQUE 사용.

10.3 WebTransport

WebSocket의 후속작:

const transport = new WebTransport('https://example.com:4433/api')
await transport.ready

// 신뢰성 stream
const stream = await transport.createBidirectionalStream()
const writer = stream.writable.getWriter()
writer.write(new TextEncoder().encode("Hello"))

10.4 QUIC for Everything

QUIC은 HTTP에만 국한되지 않습니다:

UDP 위의 신뢰성 있는 새 프로토콜의 표준이 되어가는 중.

10.5 HTTP/4?

이미 논의 중:


퀴즈

1. HTTP/3가 HTTP/2보다 빠른 핵심 이유는?

: (1) 0-RTT 핸드셰이크 — 재방문 시 첫 패킷에 데이터 포함, latency 0, (2) HOL Blocking 해결 — TCP는 한 stream의 패킷 손실이 모든 stream 차단, QUIC는 stream별 독립적 순서 보장, (3) Connection Migration — IP 변경에도 연결 유지 (모바일에 핵심), (4) TLS 1.3 통합 — 핸드셰이크 RTT 절약. 모바일과 패킷 손실 환경에서 효과 극대화. 데스크톱 좋은 네트워크에서는 5-10%, 모바일에서는 25%+ 개선.

2. 왜 QUIC는 UDP 위에 만들어졌나요?

: TCP를 변경할 수 없기 때문입니다. TCP는 모든 OS, 라우터, 미들박스에 구현되어 있어 변경하면 인터넷 전체 변경이 필요. UDP는 단순한 패킷 송수신만 제공 → QUIC가 사용자 공간에서 모든 것 (신뢰성, 흐름 제어, 암호화)을 구현. 장점: (1) 커널 업데이트 불필요, (2) 빠른 진화 (앱 업데이트만), (3) 미들박스 간섭 회피. 단점: CPU 사용량 증가 (커널 → 사용자 공간).

3. Connection Migration이 왜 모바일에 중요한가요?

: TCP 연결은 (src_ip, src_port, dst_ip, dst_port) 4-tuple로 식별됩니다. IP 하나만 바뀌어도 연결 끊김. 모바일 시나리오: 카페 WiFi → 4G 전환 시 IP 변경 → 연결 끊김 → 새 연결 + 인증 + buffering = 사용자 경험 망가짐. QUIC은 Connection ID로 식별 → IP 바뀌어도 같은 연결 유지. NAT rebinding에도 강함. YouTube, Netflix 같은 비디오 스트리밍에 큰 효과.

4. 0-RTT의 보안 위험은?

: Replay attack — 공격자가 캡처한 0-RTT 패킷을 재생할 수 있습니다. 일반 핸드셰이크는 nonce로 방지하지만, 0-RTT는 이전 세션의 키를 사용하므로 unique하지 않음. 해결: (1) Idempotent 요청만 0-RTT — GET은 OK, POST는 위험, (2) 서버가 0-RTT 거부 가능, (3) anti-replay 메커니즘 — 시간 윈도우 검증, nonce 기반. 대부분의 라이브러리는 자동 처리하지만, 애플리케이션 레벨에서 의식 필요.

5. HTTP/3 배포가 위험 없는 이유는?

: Alt-Svc 헤더 덕분입니다. 서버가 Alt-Svc: h3=":443"; ma=86400을 보내면 브라우저는 다음 요청부터 HTTP/3 시도. 실패 시 자동 fallback to HTTP/2. 결과: 점진적 마이그레이션, 단일 사용자도 영향 없음. 또한 Cloudflare, Fastly, CloudFront 등 CDN이 자동으로 HTTP/3 활성화. 기업 방화벽이 UDP 차단해도 HTTP/2로 fallback. 새 기술이지만 채택 위험이 거의 0.


참고 자료

댓글

아직 댓글이 없습니다.

로그인하면 댓글을 쓸 수 있습니다