HTTP3와 QUIC — UDP 기반 전송의 등장 배경
HTTP/3는 TCP를 버리고 UDP 위에 QUIC을 올렸습니다. 왜 수십 년간 쓰던 TCP를 대체하는 흐름이 생겼는지, QUIC이 해결하는 문제가 무엇인지 정리합니다.
TCP의 한계
HTTP/2는 TCP 위에서 멀티플렉싱을 지원하지만, TCP 레벨에서는 여전히 하나의 바이트 스트림 입니다.
Head-of-Line Blocking (HOL Blocking)
HTTP/2 + TCP:
스트림 1: [패킷A] [패킷B]
스트림 2: [패킷C] [패킷D]
TCP가 보는 것: [A][C][B][D] ← 하나의 스트림
패킷 C가 손실되면:
→ TCP는 C의 재전송을 기다림
→ 그 동안 D도 블록됨 (스트림 2만의 문제인데 전체 블록)
TCP 연결 수립 지연
TCP + TLS 1.2:
클라이언트 → SYN → 1 RTT (TCP)
← SYN-ACK ←
→ ACK →
→ ClientHello → 2 RTT (TLS)
← ServerHello, Cert ←
→ Finished →
← Finished ←
→ HTTP 요청 → 총 3 RTT
QUIC:
→ Initial (Crypto) → 0~1 RTT
← Handshake ←
→ HTTP 요청 → 재연결 시 0-RTT!
QUIC이란
QUIC(Quick UDP Internet Connections) 은 Google이 개발한 UDP 기반 전송 프로토콜 입니다. TCP + TLS + HTTP/2의 장점을 하나로 합쳤습니다.
기존 스택: QUIC 스택:
┌──────────┐ ┌──────────┐
│ HTTP/2 │ │ HTTP/3 │
├──────────┤ ├──────────┤
│ TLS │ │ QUIC │ ← TCP + TLS + 멀티플렉싱 통합
├──────────┤ ├──────────┤
│ TCP │ │ UDP │
├──────────┤ ├──────────┤
│ IP │ │ IP │
└──────────┘ └──────────┘
QUIC의 핵심 특징
1. 독립적 스트림 멀티플렉싱
QUIC:
스트림 1: [패킷A] [패킷B] ← 독립
스트림 2: [패킷C] [패킷D] ← 독립
패킷 C가 손실되어도:
→ 스트림 1의 B는 정상 처리 (HOL Blocking 해결!)
→ 스트림 2만 C 재전송 대기
2. 빠른 연결 수립
- 첫 연결: 1-RTT (TCP의 3-RTT 대비)
- 재연결: 0-RTT (이전 세션 정보 캐싱)
3. 연결 마이그레이션
TCP는 (출발IP, 출발포트, 목적IP, 목적포트) 4-tuple로 연결을 식별합니다. Wi-Fi ↔ LTE 전환 시 IP가 바뀌면 연결이 끊깁니다.
QUIC은 Connection ID 로 연결을 식별하므로, IP가 바뀌어도 연결이 유지됩니다.
4. 내장 암호화
QUIC은 TLS 1.3을 내장합니다. 평문 전송이 불가능하므로 보안이 기본입니다.
HTTP/3
QUIC 위에서 동작하는 HTTP 버전입니다.
| 항목 | HTTP/1.1 | HTTP/2 | HTTP/3 |
|---|---|---|---|
| 전송 계층 | TCP | TCP | QUIC (UDP) |
| 멀티플렉싱 | 없음 | 있음 (HOL 문제) | 있음 (HOL 해결) |
| 헤더 압축 | 없음 | HPACK | QPACK |
| 연결 수립 | 1+2 RTT | 1+2 RTT | 1 RTT (0-RTT 가능) |
| 암호화 | 선택 | 사실상 필수 | 필수 |
핵심 포인트
- 왜 TCP가 아닌 UDP인가: TCP는 커널에 구현되어 수정이 어려움 → UDP 위에 사용자 공간에서 QUIC 구현
- 0-RTT의 보안 문제: 재생 공격(Replay Attack) 가능 → 멱등한 요청에만 사용
- QUIC이 UDP를 쓰면 신뢰성은?: QUIC이 자체적으로 재전송, 혼잡 제어, 흐름 제어를 구현
정리
QUIC/HTTP3는 TCP의 근본적 한계(HOL Blocking, 느린 핸드셰이크, 연결 마이그레이션 불가)를 해결합니다. 이미 Google, Cloudflare, Facebook 등이 대규모로 적용하고 있으며, 모바일 환경에서 특히 큰 성능 개선을 보여줍니다.