웹 서버·WAS 용어 사전
프로토콜h2 · 다중화 · HPACK · HoL 블로킹

HTTP/2

하나의 연결에 스트림을 다중화한다. HTTP 레벨 HoL은 없앴지만 TCP 레벨은 남았다.

하나의 연결에 스트림을 다중화하는 프로토콜.

  • HTTP/1.1 — 연결 하나에 요청을 한 줄로 보낸다

    • 앞 응답이 느리면 뒤가 막힌다 (HTTP 레벨 HoL)
    • 브라우저가 연결을 6개씩 여는 것으로 우회했다
  • HTTP/2 — 하나의 연결에 스트림을 다중화한다

    • 요청·응답이 섞여 오갈 수 있다
    • 헤더를 HPACK 으로 압축한다
    • 연결 하나로 충분해진다

HPACK 이 생각보다 크게 기여한다

요청마다 쿠키 · User-Agent · Accept 가 반복된다 큰 쿠키를 쓰는 서비스는 헤더만 수 KB 가 된다

  • HPACK 은 이전에 보낸 헤더를 테이블로 기억하고 인덱스만 보낸다
  • 반복 요청의 헤더가 수십 바이트로 준다

API 호출이 잦은 서비스에서 체감이 크다

남는 문제 — TCP 레벨 HoL

HTTP/2 는 TCP 위에서 돈다 패킷 하나가 유실되면 TCP 가 재전송을 기다린다

  • 그 동안 '그 연결의 모든 스트림' 이 멈춘다

  • HTTP 레벨 HoL 은 없앴지만 TCP 레벨 HoL 이 남았다

  • 손실률이 높은 모바일 환경에서는 이득이 줄어든다

  • 이것을 풀려고 HTTP/3 가 TCP 를 버렸다

설정

listen 443 ssl;
http2 on;              # nginx 1.25.1+ 의 형태
# listen 443 ssl http2;   # 그 이전 형태 — 이 표기의 문서가 아직 많다
  • HTTP/2 는 사실상 TLS 위에서만 쓴다 (브라우저가 평문 h2 를 지원하지 않는다)
  • nginx → 업스트림 구간은 별개다. 기본이 HTTP/1.1 이다
    • (nginx 1.31 부터 proxy 모듈이 HTTP/2 백엔드를 지원한다)

HTTP/1.1 시대의 최적화를 되돌려야 한다

  • 도메인 샤딩 — 정적 자원을 여러 도메인으로 쪼개 연결 수를 늘리던 기법

    • HTTP/2 에서는 연결이 늘어 다중화 이점이 사라진다 → 되돌린다
  • 스프라이트·인라이닝 — 작은 파일을 합치던 기법

    • 요청 비용이 싸졌으므로 이득이 줄었다
    • 다만 압축 효율 때문에 여전히 유효한 경우가 있다
  • "HTTP/1.1 최적화를 그대로 두고 HTTP/2 를 켜면" 기대만큼 안 빨라진다

서버 푸시는 사실상 사라졌다

HTTP/2 서버 푸시는 브라우저에서 제거되는 방향으로 정리됐다

  • 캐시에 이미 있는 것을 다시 밀어 낭비가 잦았다
  • 복잡도 대비 이득이 작았다

대체 — 103 Early Hints · <link rel=preload>

스트림 수와 흐름 제어

http2_max_concurrent_streams 128;   # 연결당 동시 스트림 상한

클라이언트가 한 연결에 스트림을 무한히 열 수 있으면 자원 고갈이 된다 과거 이 지점을 노린 공격이 여러 차례 있었다

  • (Rapid Reset — 스트림을 열자마자 취소하는 것을 반복)

  • 상한과 함께 요청률 제한을 둔다

  • nginx 버전을 최신으로 유지하는 것이 가장 확실한 대응이다

뒤쪽 구간은 별개다

  • 클라이언트 ↔ nginx — HTTP/2
  • nginx ↔ 업스트림 — 기본 HTTP/1.1

프론트만 h2 를 켜고 "전 구간이 빨라졌다" 고 생각하기 쉽다 뒤 구간의 이득을 원하면 upstream keepalive 부터 챙기는 편이 효과가 크다 (연결 재사용이 다중화보다 먼저다)

면접 함정

  • "HTTP/2면 HoL 블로킹이 없다" → TCP 레벨에는 남아 있다.
  • "켜기만 하면 빨라진다" → 도메인 샤딩 같은 1.1 시대 최적화를 되돌려야 한다.

함께 보면 좋은 용어

노트에서 맥락과 함께 보기 — TLS 종단과 HTTP/2·3