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

[Network] HTTP/2: multiplexing, HPACK, server push의 종말

· 수정 · 📖 약 4분 · 1,320자/단어 #http #network #backend #protocol #multiplexing
HTTP/2, h2, HPACK, stream multiplexing, server push, h2c

정의

HTTP/2 (2015, RFC 9113) 는 HTTP/1.1 의 문법은 유지하되 전송을 바이너리 + 멀티플렉싱 으로 바꾼다. Head-of-Line Blocking (HTTP 레벨) 해결이 핵심.

핵심 변경 3가지:

  1. Binary framing: 텍스트 → 바이너리. 파싱 효율 + 정확성.
  2. Stream multiplexing: 한 TCP 연결에서 여러 stream 병렬.
  3. HPACK 헤더 압축: 반복 헤더의 압축 + 인덱싱.

Binary Framing

HTTP/1.1 의 텍스트 메시지frame 으로 분해:

Frame Type의미
DATA본문
HEADERS헤더
PRIORITY스트림 우선순위
RST_STREAM스트림 취소
SETTINGS연결 설정
PUSH_PROMISEserver push (대부분 비활성)
PINGkeep-alive 측정
GOAWAY연결 종료
WINDOW_UPDATEflow control
CONTINUATION큰 헤더 분할
flowchart LR
    H1["HTTP/1.1 메시지<br/>(텍스트)"] -->|HTTP/2| Frames
    Frames["[HEADERS frame]<br/>[DATA frame]<br/>[DATA frame]"]

Multiplexing

한 TCP 연결에서 여러 stream (요청/응답 쌍)frame 인터리빙 으로 동시 진행:

sequenceDiagram
    autonumber
    participant C as Client
    participant S as Server

    C->>S: HEADERS stream=1 (GET /a)
    C->>S: HEADERS stream=3 (GET /b)
    C->>S: HEADERS stream=5 (GET /c)
    S-->>C: HEADERS stream=3 (작은 응답 먼저)
    S-->>C: DATA stream=3 (완료)
    S-->>C: HEADERS stream=1
    S-->>C: DATA stream=5 (부분)
    S-->>C: DATA stream=1 (부분)
    S-->>C: DATA stream=1 (완료)
    S-->>C: DATA stream=5 (완료)
항목HTTP/1.1HTTP/2
동시 요청N개 TCP 연결1 TCP, N streams
HoL Blocking (HTTP)있음 (pipelining)없음
헤더 압축없음HPACK
Binary텍스트binary

IMPORTANT

Multiplexing 은 HTTP 레벨의 HoL blocking 만 해결. TCP 패킷 손실 이 발생하면 그 아래 모든 stream 이 대기. 이 한계가 HTTP/3 (QUIC) 의 등장 이유.

HPACK 헤더 압축

반복되는 헤더 (User-Agent, Cookie 등) 를 인덱스로 참조. Static Table (61개 미리 정의) + Dynamic Table (연결마다 갱신) + Huffman.

요청 1: :method=GET, :path=/a, user-agent=Mozilla/5.0...
→ 보내고 dynamic table 에 등록 (예: index 62)

요청 2: :method=GET, :path=/b, user-agent=Mozilla/5.0...
→ index 62 만 보냄 (수십 바이트 → 1 바이트)

자세한 건 hpack 참고.

CAUTION

CRIME / BREACH 공격 의 변형 (HPACK 압축 oracle). 일반적으로 안전하지만, 비밀 헤더 + 사용자 입력이 같은 응답 에 들어가면 위험.

Server Push (사실상 폐기)

/index.html 요청에 서버가 미리 /style.css, /app.js 도 push:

sequenceDiagram
    C->>S: GET /index.html
    S-->>C: PUSH_PROMISE /style.css
    S-->>C: PUSH_PROMISE /app.js
    S-->>C: 200 /index.html
    S-->>C: 200 /style.css (요청 없이 미리)
    S-->>C: 200 /app.js (요청 없이 미리)

WARNING

2022 Chrome 이 server push 를 제거. push 캐시 적중률이 낮고 bandwidth 낭비 + priority 충돌. 2026 시점 server push 는 사실상 죽은 기능. 대신 103 Early Hints + <link rel=preload> 패턴.

h2 vs h2c

프로토콜의미
h2TLS 위 HTTP/2 (대부분)
h2ccleartext (내부 네트워크, gRPC mesh)

브라우저는 h2 만. 서버끼리는 h2c 도 흔함 (TLS 종료를 가까운 sidecar/proxy 에서).

Flow Control

스트림 / 연결마다 window size. WINDOW_UPDATEbackpressure. TCP 의 sliding window 와 별개 application 레벨 제어.

flowchart LR
    Server -->|WINDOW_UPDATE +65535| Client
    Client -->|"DATA (window 안에서만)"| Server

흔한 함정

WARNING

  1. 다수 TCP 연결의 습관 = HTTP/2 환경에서 6 connections per origin 같이 옛 패턴을 유지하면 멀티플렉싱 효과 0.
  2. Connection, Upgrade, Proxy-Connection 헤더 = HTTP/2 에서 금지된 헤더. 보내면 연결 RST.
  3. Priority 잘못 설정 = 일부 클라이언트가 priority frame 무시. RFC 9218 의 priority hints 가 더 신뢰.
  4. PUSH 의존 코드 = 위 server push 폐기 때문에 fallback 필수.

Connection Preface

HTTP/2 연결의 첫 24 바이트 = magic octets:

PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n

이후 클라이언트 SETTINGS frame 전송. h2c (cleartext) 직접 연결 식별에 사용. h2 (TLS+ALPN) 에서는 ALPN 협상 후 magic 전송.

ALPN 협상

HTTP/2 를 사용하려면 TLS 핸드셰이크 중 ALPN (Application-Layer Protocol Negotiation) 으로 버전 협상.

sequenceDiagram
    participant C as Client
    participant S as Server
    C->>S: TLS ClientHello + ALPN: h2, http/1.1
    S-->>C: TLS ServerHello + ALPN: h2
    Note over C,S: 이후 HTTP/2 바이너리 프레임 교환
식별자의미
h2TLS 위 HTTP/2 (브라우저 표준)
h2cCleartext HTTP/2 (내부망, gRPC mesh)
http/1.1ALPN fallback (h2 미지원 시)

서버 설정 예:

  • Nginx: listen 443 ssl; http2 on; (nginx 1.26+ 권장)
  • Caddy: 자동 ALPN 협상 (별도 설정 불필요)
  • Go net/http: h2.ConfigureServer 또는 기본 TLS 서버
  • Java Netty: ApplicationProtocolNegotiationHandler

Stream 상태 머신

각 HTTP/2 stream 은 상태 머신. RST_STREAM 으로 언제든지 즉시 취소.

stateDiagram-v2
    [*] --> idle
    idle --> open : HEADERS 전송 또는 수신
    open --> half_closed_local : END_STREAM 전송
    open --> half_closed_remote : END_STREAM 수신
    half_closed_local --> closed : RST_STREAM 또는 END_STREAM 수신
    half_closed_remote --> closed : RST_STREAM 또는 END_STREAM 전송
    open --> closed : RST_STREAM
    closed --> [*]
상태의미
idle미사용. 클라이언트 = 홀수 ID, 서버 push = 짝수 ID
open양방향 송수신 가능
half_closed_local로컬 전송 완료, 수신만
half_closed_remote원격 전송 완료, 송신만
closed완전 종료. ID 재사용 불가

NOTE

스트림 ID 는 단조 증가. 연결 수명 동안 최대 2^31 개. 한도 도달 시 GOAWAY 로 연결 재시작.

gRPC 와 HTTP/2

gRPC 는 HTTP/2 를 전송 계층으로 사용. Protobuf 를 DATA frame 에 실어 보낸다.

flowchart LR
    Caller["gRPC Caller<br/>Protobuf 직렬화"]
    Caller --> H2["HTTP/2 DATA frames"]
    H2 --> Mux["Stream Multiplexing<br/>단일 TCP 연결"]
    Mux --> Svr["gRPC Server<br/>Protobuf 역직렬화"]
HTTP/2 개념gRPC 매핑
stream 1개RPC 호출 1개
HEADERS framegRPC metadata, trailer
DATA frameProtobuf payload
RST_STREAM오류 취소
SETTINGS: MAX_CONCURRENT_STREAMS최대 동시 RPC 수 제한

gRPC 4가지 통신 모드:

모드방향적합 예
Unary1:1단순 API 호출
Server streaming1:N실시간 피드, 로그 스트림
Client streamingN:1파일 업로드, 배치 수집
Bidirectional streamingN:N채팅, 협업, 게임

WARNING

L4 LB 앞 gRPC: 1 TCP 연결 = 1 백엔드 고착 → 편향 분산. L7 gRPC-aware LB (Envoy, Istio, k8s Ingress) 로 stream 레벨 분산 필요. 자세히는 grpc.

HTTP/2 vs HTTP/3 빠른 비교

항목HTTP/2HTTP/3
전송 계층TCPQUIC (UDP 기반)
HoL BlockingTCP 패킷 손실 시 전 스트림 대기스트림별 독립 (없음)
헤더 압축HPACK (dynamic table)QPACK
0-RTT 재개없음있음 (session ticket)
배포 성숙도광범위CDN, 모던 브라우저 지원 확대 중

자세히는 http-3 참고.

실전 체크리스트

항목확인 방법
h2 협상 여부curl -I --http2 https://example.com
ALPN 선택값openssl s_client -alpn h2 -connect example.com:443
Chrome h2 세션chrome://net-internals/#http2
금지 헤더 제거Connection, Upgrade, Keep-Alive 없애기
Server push 제거http2_push 지시자 제거, 103 Early Hints 로 대체
gRPC LBEnvoy 또는 client-side LB 적용
우선순위 힌트RFC 9218 Extensible Priorities (Urgency, Incremental 헤더)

관련 위키

이 글의 용어 (7개)
[Network] gRPC: HTTP/2 + Protobuf, 4가지 streaming 패턴network
정의 gRPC 는 HTTP/2 위에서 Protobuf 직렬화 로 동작하는 고성능 RPC 프레임워크. Google 내부 Stubby 의 오픈소스 후계. 핵심 4가지: 1. Prot…
[Network] HTTP/1.1: keep-alive, pipelining, chunked transfernetwork
정의 HTTP/1.1 (1997, RFC 9112 으로 재정리) 는 텍스트 기반 stateless request/response 프로토콜. 2026 시점에도 대부분의 트래픽이 H…
[Network] HTTP/3: QUIC 위의 HTTP, 0-RTT, connection migrationnetwork
정의 HTTP/3 (2022, RFC 9114)는 HTTP의 전송 레이어를 TCP 에서 QUIC 으로 교체한 버전이다. UDP 위에 QUIC, QUIC 위에 HTTP 구조다. 핵…
Head-of-Line Blockingnetwork
정의 Head-of-Line Blocking (HOLB) 은 처리 순서가 정해진 큐에서 맨 앞 항목의 지연이 그 뒤 항목 전체의 지연으로 전파되는 현상이다. 네트워크 프로토콜에서…
HPACKnetwork
정의 HPACK (RFC 7541)은 HTTP/2에서 요청/응답 헤더를 압축하는 방식이다. HTTP/1.1에서 헤더는 매 요청마다 평문 텍스트로 반복 전송되었다. 한 페이지 로드…
TCPnetwork
정의 TCP (Transmission Control Protocol) 는 신뢰성 있는 연결 지향 전송 계층 프로토콜이다. RFC 9293 으로 정의되어 있다. HTTP/1.1·2…
TLS / SSLnetwork
정의 TLS (Transport Layer Security) 는 (또는 위 ) 위에서 동작하는 암호화·인증 프로토콜이다. SSL 은 TLS 의 전신 (Netscape 1995, …

💬 댓글

사이트 검색 / 명령어

검색

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