본문으로 건너뛰기
김신건의 로그

[Network] HTTP/3: QUIC 위의 HTTP, 0-RTT, connection migration

· 수정 · 📖 약 3분 · 1,278자/단어 #http #network #backend #protocol #quic #udp
HTTP/3, h3, HTTP over QUIC, 0-RTT, connection migration, QPACK

정의

HTTP/3 (2022, RFC 9114)는 HTTP의 전송 레이어를 TCP 에서 QUIC 으로 교체한 버전이다. UDP 위에 QUIC, QUIC 위에 HTTP 구조다.

핵심 동기:

  • TCP HoL Blocking 해결: 스트림 단위 패킷 손실 격리
  • 0-RTT 핸드셰이크: 재방문 시 연결 지연 제로
  • Connection Migration: IP 변경 시 연결 유지
flowchart TB
    HTTP["HTTP/3 semantics\n(RFC 9114)"]
    QUIC["QUIC\n멀티스트림 + 암호화 + 혼잡제어\n(RFC 9000)"]
    UDP["UDP"]
    IP["IP"]

    HTTP --> QUIC --> UDP --> IP

HTTP 버전 비교

항목HTTP/1.1HTTP/2HTTP/3
전송 계층TCPTCPQUIC (UDP)
멀티플렉싱없음 (keep-alive)TCP 스트림 내QUIC 독립 스트림
HoL BlockingTCP + 앱 레벨TCP 레벨없음
핸드셰이크1 RTT + TLS1 RTT + TLS1 RTT (TLS 통합)
재접속1 RTT1 RTT0 RTT
헤더 압축없음[[hpackHPACK]]
서버 Push없음있음 (사실상 폐기)없음
Connection Migration불가불가가능
암호화선택선택필수 (TLS 1.3 통합)

Handshake: 0-RTT의 마법

sequenceDiagram
    autonumber
    participant C as Client
    participant S as Server

    rect rgb(220,240,220)
    Note over C,S: 첫 방문 (1-RTT)
    C->>S: Initial (TLS ClientHello + crypto frames)
    S-->>C: Initial + Handshake (server params + cert)
    C->>S: Handshake (finish) + HTTP/3 request
    S-->>C: HTTP/3 response + session ticket
    end

    rect rgb(255,235,220)
    Note over C,S: 재방문 (0-RTT)
    C->>S: 0-RTT data (HTTP/3 request + cached session params)
    S-->>C: HTTP/3 response (즉시)
    end

QUIC은 TLS 1.3 핸드셰이크를 전송 계층 협상과 통합한다. 첫 방문은 1 RTT, 이전 연결의 세션 티켓을 캐시해두면 재접속 시 0 RTT로 데이터를 즉시 전송할 수 있다.

CAUTION

0-RTT는 replay 공격에 취약하다. 비멱등 요청(POST, DELETE, 결제)을 0-RTT로 보내면 중간자가 같은 요청을 반복 재생할 수 있다. GET/HEAD 같은 안전한 메서드만 0-RTT를 허용하고, 나머지는 반드시 1-RTT 이후 처리해야 한다.

TCP HoL Blocking vs QUIC Stream 독립

flowchart TB
    subgraph T["HTTP/2 over TCP"]
        TS["stream 1, 3, 5가\n같은 TCP 시퀀스 안"]
        TPacket1["패킷 1: stream 1 데이터"]
        TPacket2["패킷 2: stream 3 데이터 (손실!)"]
        TPacket3["패킷 3: stream 5 데이터"]
        TBlock["stream 1, 5 모두 대기"]
        TS --> TPacket1 & TPacket2 & TPacket3
        TPacket2 -.->|"TCP는 순서 보장 필요"| TBlock
    end
    subgraph Q["HTTP/3 over QUIC"]
        QS["stream 1, 3, 5가\n각자 독립 시퀀스"]
        QPacket1["패킷 1: stream 1 (도착)"]
        QPacket2["패킷 2: stream 3 (손실)"]
        QPacket3["패킷 3: stream 5 (도착)"]
        QOK["stream 1, 5 즉시 처리"]
        QWait["stream 3만 대기"]
        QS --> QPacket1 & QPacket2 & QPacket3
        QPacket1 --> QOK
        QPacket3 --> QOK
        QPacket2 --> QWait
    end

HTTP/2는 TCP 레이어에서 스트림 1, 3, 5를 하나의 바이트 스트림으로 전송한다. 패킷 2가 손실되면 TCP가 재전송을 완료할 때까지 패킷 3도 애플리케이션에 전달되지 않는다. 이것이 TCP 레벨 HoL Blocking이다.

HTTP/3 QUIC은 스트림을 독립 단위로 격리한다. stream 3 패킷이 손실되어도 stream 1과 5는 즉시 애플리케이션에 전달된다.

Connection Migration

WiFi에서 4G로 전환, NAT 재할당 등 IP가 바뀌어도 연결이 유지된다.

sequenceDiagram
    participant C as Client
    participant S as Server

    C->>S: WiFi IP 192.168.1.10:54321 (conn_id=XYZ)
    S-->>C: 응답 (conn_id=XYZ)
    Note over C: 지하철 진입, 4G 전환
    Note over C: IP 변경: 10.0.0.5:65432
    C->>S: 4G IP 10.0.0.5:65432 (conn_id=XYZ)
    Note over S: Connection ID XYZ로 식별 (IP 무관)
    S-->>C: 응답 (conn_id=XYZ, 연결 유지)
    Note over C,S: TLS 세션 유지, 처음부터 다시 안 함

TCP는 (src IP, src port, dst IP, dst port) 4-tuple로 연결을 식별하므로 IP가 바뀌면 연결이 끊긴다. QUIC은 Connection ID로 연결을 식별하여 IP/포트 변경을 투명하게 처리한다.

QPACK 헤더 압축

HPACK의 순서 의존성 문제를 해결한 변형이다.

flowchart LR
    E["QPACK Encoder\n(클라이언트)"]
    D["QPACK Decoder\n(서버)"]

    E -->|"인코더 스트림\n동적 테이블 업데이트"| D
    D -->|"디코더 스트림\n테이블 업데이트 ACK"| E
    E -->|"요청 스트림\n헤더 블록 (인덱스 참조)"| D
항목HPACK (HTTP/2)QPACK (HTTP/3)
동적 테이블단일 스트림에서 인라인 업데이트별도 인코더/디코더 스트림
순서 의존성있음 (TCP가 보장)없음 (QUIC 스트림 독립)
HOL 블로킹TCP 레벨QPACK 레벨 동기화로 제거

Alt-Svc: HTTP/3 협상 방법

브라우저는 HTTP/3를 처음부터 알 수 없다. 서버가 Alt-Svc 헤더로 HTTP/3 지원을 알린다.

HTTP/1.1 200 OK
Alt-Svc: h3=":443"; ma=86400, h3-29=":443"; ma=86400

이후 브라우저는 UDP 443 포트로 QUIC 연결을 시도하고, 성공하면 HTTP/3를 사용한다. 실패하면 HTTP/2나 HTTP/1.1로 fallback한다.

실전: 서버 설정

nginx (1.25+)

server {
    listen 443 quic reuseport;   # HTTP/3 UDP
    listen 443 ssl;              # HTTP/2 TCP fallback

    ssl_certificate     /path/to/cert.pem;
    ssl_certificate_key /path/to/key.pem;
    ssl_protocols       TLSv1.3;  # QUIC은 TLS 1.3 필수

    # 브라우저에 HTTP/3 지원 알림
    add_header Alt-Svc 'h3=":443"; ma=86400';

    # QUIC 버퍼 최적화
    quic_retry on;  # QUIC Retry 패킷으로 DoS 방어
}

Cloudflare Workers (HTTP/3 자동)

// Cloudflare Workers는 HTTP/3를 자동 협상
// 별도 설정 없이 h3 지원
export default {
  async fetch(request, env) {
    // request.cf.httpProtocol 로 클라이언트 프로토콜 확인
    const proto = request.cf?.httpProtocol;  // "HTTP/3" | "HTTP/2" | "HTTP/1.1"
    return new Response(`Protocol: ${proto}`);
  },
};

HTTP/3 연결 테스트

# curl로 HTTP/3 요청 (curl 7.88+, QUIC 빌드 필요)
curl --http3 https://cloudflare.com -I

# HTTP/3 협상 확인
curl -v --http3 https://example.com 2>&1 | grep -E "ALPN|http"
# * ALPN: h3

# 연결 없이 HTTP/3 즉시 시도
curl --http3-prior-knowledge https://example.com

# Python httpx로 HTTP/3
# pip install httpx[http3]
import httpx
with httpx.Client(http2=True) as client:
    response = client.get("https://example.com")
    print(response.http_version)  # HTTP/3 또는 HTTP/2

도입 현황 (2026)

영역비중
Cloudflare / Fastly / Akamai (CDN)기본 활성
Google 서비스전면 HTTP/3
모바일 앱 (iOS, Android)빠르게 증가
일반 웹 사이트 (브라우저 트래픽)약 35%+
기업 내부망 (방화벽 UDP 차단)더딤

브라우저 지원 현황: Chrome, Firefox, Safari, Edge 모두 HTTP/3를 지원한다 (2022년 이후 기본 활성).

NOTE

방화벽이 UDP 443 포트를 차단하면 HTTP/3 fallback이 발생해 HTTP/2 (TCP)로 내려간다. 사내망 환경에서 HTTP/3가 동작하지 않는 가장 흔한 원인이다.

흔한 함정

WARNING

  1. 방화벽 UDP 차단: 기업망, 일부 ISP에서 UDP 443을 차단한다. Alt-Svc로 광고하더라도 실제 사용률을 모니터링해야 한다.
  2. 0-RTT replay 공격: POST, DELETE, 결제 등 비멱등 요청을 0-RTT로 허용하면 재생 공격 가능. GET/HEAD만 0-RTT 허용.
  3. Connection ID 추적: Connection ID가 식별자처럼 쓰일 수 있어 프라이버시 우려. RFC 9000은 주기적 Connection ID 변경을 권장.
  4. 로드 밸런서 UDP 해싱 문제: 전통적 LB는 5-tuple(IP+포트) 해싱. IP 변경 시 다른 백엔드로 라우팅될 수 있다. Connection ID 기반 라우팅 지원 LB 필요.
  5. 세션 티켓 공유: 다중 서버 환경에서 0-RTT를 위해 세션 티켓을 서버 간 공유해야 한다. 미공유 시 0-RTT 실패.
  6. CPU 비용: QUIC의 사용자 공간 구현은 커널 바이패스 없이 암호화 비용이 TCP+TLS보다 높을 수 있다.

관련 위키

  • QUIC - HTTP/3의 전송 계층
  • HTTP/2 - HPACK, 멀티플렉싱 도입 (전 단계)
  • HPACK - HTTP/2 헤더 압축 (HTTP/3는 QPACK)
  • UDP - QUIC 기반 프로토콜
  • TLS - QUIC에 통합된 암호화
  • Head-of-Line Blocking - HTTP/3가 해결하는 핵심 문제
  • Load Balancer - QUIC/HTTP3 LB 고려사항
이 글의 용어 (8개)
[Network] HTTP/2: multiplexing, HPACK, server push의 종말network
정의 HTTP/2 (2015, RFC 9113) 는 HTTP/1.1 의 문법은 유지하되 전송을 바이너리 + 멀티플렉싱 으로 바꾼다. Head-of-Line Blocking (HT…
[Network] Load Balancer: L4 vs L7, 알고리즘, sticky sessionnetwork
정의 Load Balancer 는 트래픽을 여러 백엔드로 분산 하는 인프라. 수평 확장 + 가용성 + 무중단 배포 의 토대. L4 vs L7 | 구분 | L4 (Transport…
Head-of-Line Blockingnetwork
정의 Head-of-Line Blocking (HOLB) 은 처리 순서가 정해진 큐에서 맨 앞 항목의 지연이 그 뒤 항목 전체의 지연으로 전파되는 현상이다. 네트워크 프로토콜에서…
HPACKnetwork
정의 HPACK (RFC 7541)은 HTTP/2에서 요청/응답 헤더를 압축하는 방식이다. HTTP/1.1에서 헤더는 매 요청마다 평문 텍스트로 반복 전송되었다. 한 페이지 로드…
QUICnetwork
정의 QUIC (Quick UDP Internet Connections)은 Google이 2012년 처음 제안하고 2021년 RFC 9000으로 표준화된 UDP 기반 전송 프로토…
TCPnetwork
정의 TCP (Transmission Control Protocol) 는 신뢰성 있는 연결 지향 전송 계층 프로토콜이다. RFC 9293 으로 정의되어 있다. HTTP/1.1·2…
TLS / SSLnetwork
정의 TLS (Transport Layer Security) 는 (또는 위 ) 위에서 동작하는 암호화·인증 프로토콜이다. SSL 은 TLS 의 전신 (Netscape 1995, …
UDPnetwork
정의 UDP (User Datagram Protocol)는 비연결·비신뢰 전송 계층 프로토콜이다. RFC 768 (1980) 로 정의되었다. TCP 와 대비된다. "보내고 잊는다…

💬 댓글

사이트 검색 / 명령어

검색

스크롤 = 확대/축소 · 드래그 = 이동 · 0 = 원래 크기 · ESC = 닫기