본문으로 건너뛰기

안동민 개발노트

본문 시작

HTTP/2

HTTP/2의 바이너리 프레이밍·스트림 다중화·HPACK을 익히고 HTTP/1.1 병목과 남은 TCP HOL 문제를 이해합니다.

9장에서 HTTP/1.1의 요청-응답 구조를 살펴보았습니다.

HTTP/1.1은 웹의 폭발적 성장을 이끌었지만, 현대 웹 페이지의 복잡도가 증가하면서 성능 한계가 드러났습니다.

하나의 웹 페이지가 수십 개의 CSS, JavaScript, 이미지 파일을 필요로 하는 상황에서, HTTP/1.1의 구조적 문제가 병목이 되기 시작했습니다.


HTTP/1.1의 한계

HTTP/1.1의 대표적인 성능 한계는 Head-of-Line(HOL) Blocking입니다.

같은 연결에서 앞선 응답이 늦어지면 뒤 요청이 기다리기 쉽고, 브라우저는 이를 완화하려고 여러 TCP 연결을 동시에 열었습니다.

하지만 연결 수가 늘면 TCP/TLS 핸드셰이크, 혼잡 제어, 서버 부하가 함께 증가합니다.

HTTP/1.1 한 연결에서는 앞 응답 지연이 뒤 요청의 대기열이 된다

pipelining이나 keep-alive가 있어도 같은 TCP 연결 안에서는 앞선 응답이 늦으면 뒤 요청이 영향을 받기 쉽다.

  1. 1 req A

    req A 느린 이미지/API 응답 생성 지연

  2. 2 req B

    req B 작은 리소스 A 뒤에서 대기

  3. 3 req C

    req C 캐시 가능한 파일 같은 연결이면 함께 지연

  4. 4 workaround

    workaround 연결 추가 또는 domain sharding 병목을 우회

개발자들은 HTTP/1.1의 연결 단위 병목을 줄이기 위해 다양한 최적화 패턴을 사용했습니다.

최적화 기법방식HTTP/2 이후의 관점
CSS 스프라이트여러 이미지를 하나로 합침요청 수 절감 효과는 줄고 유지보수 비용이 큼
도메인 샤딩리소스를 여러 도메인에 분산HTTP/2 연결 재사용과 충돌하고 DNS/TLS 비용 증가
인라이닝CSS/JS를 HTML에 직접 삽입초기 렌더링에는 도움 될 수 있으나 캐시 효율 저하
파일 합치기JS/CSS 파일 결합작은 리소스를 병렬 전송할 수 있어 필요성이 줄어듦

HTTP/2는 이런 패턴이 의존하던 “요청 수 자체를 줄여야 한다”는 압박을 프로토콜 레벨에서 완화합니다.

다만 번들링, 인라이닝, 프리로드 같은 최적화는 애플리케이션 특성에 따라 여전히 선택적으로 사용됩니다.


바이너리 프레이밍과 멀티플렉싱

HTTP/2의 핵심 변화는 바이너리 프레이밍 계층(Binary Framing Layer)의 도입입니다.

HTTP 메시지를 텍스트 줄 단위로 그대로 흘려보내지 않고, HEADERS와 DATA 같은 프레임으로 나누어 여러 스트림을 하나의 연결 위에서 동시에 진행합니다.

HTTP/2는 TCP 한 줄에 섞인 frame을 stream id로 재조립한다

여러 요청의 HEADERS와 DATA frame이 하나의 TCP 연결에서 섞여 흘러도 stream id가 요청 경계를 복원한다.

  1. HEADERS GET /a stream 1

    시작

  2. HEADERS GET /b stream 3

    시작

  3. DATA A1 stream 1 본문
  4. DATA B1 stream 3 본문
  5. END_STREAM A stream 1 완료

헤더 압축 (HPACK)

HTTP/1.1에서는 매 요청마다 비슷한 헤더가 반복 전송되었습니다.

HTTP/2는 HPACK으로 헤더 필드를 인덱스와 동적 테이블 중심으로 표현해 반복 전송량을 줄입니다.

민감한 값은 동적 테이블에 넣지 않는 표현도 있어, 압축 효율과 보안 고려를 함께 다룹니다.

HPACK은 반복 헤더를 문자열 대신 테이블 인덱스로 보낸다

처음 보낸 헤더 이름과 값은 정적/동적 테이블에 놓고, 이후 반복은 짧은 번호 참조로 줄인다.

  1. 1 literal

    literal 처음 등장한 header 이름과 값을 그대로 보냄

  2. 2 table

    table 정적/동적 테이블 저장 반복 가능한 항목을 index화

  3. 3 indexed

    indexed 번호만 전송 같은 문자열 반복 비용 감소

  4. 4 evict

    evict 테이블 크기 관리 오래된 항목은 제거


서버 푸시

HTTP/2의 서버 푸시(Server Push)는 서버가 클라이언트의 후속 요청을 예측하여 PUSH_PROMISE로 미리 자원을 예약하고 보내는 기능입니다.

프로토콜에는 정의되어 있지만, 실제 웹에서는 캐시 중복, 예측 실패, 우선순위 제어 문제 때문에 활용이 제한적이었고 현대 브라우저 환경에서는 대부분 비활성화되거나 제거된 방향으로 흘렀습니다.

서버 푸시는 예측과 캐시가 맞을 때만 이득이다

PUSH_PROMISE는 후속 리소스를 미리 보낼 수 있지만, 이미 캐시에 있거나 우선순위가 틀리면 대역폭 낭비가 된다.

  1. 1 request

    request HTML 요청 필요 리소스를 서버가 예측

  2. 2 promise

    promise PUSH_PROMISE 브라우저가 받을 stream 예약

  3. 3 cache check

    cache check 이미 있으면 취소가 유리 중복 전송 방지

  4. 4 deliver

    deliver 정말 필요한 critical 리소스 초기 렌더링 단축 가능


HTTP/2의 남은 문제

HTTP/2는 HTTP 메시지 단위의 HOL Blocking을 크게 줄였지만, TCP 계층의 HOL Blocking은 여전히 남습니다.

하나의 TCP 연결 위에 여러 HTTP/2 스트림이 올라가기 때문에, 패킷 손실이 발생하면 TCP가 순서를 복구할 때까지 뒤쪽 바이트 전달이 함께 지연될 수 있습니다.

HTTP/2는 메시지 대기는 줄여도 TCP 바이트 손실 대기는 피하지 못한다

여러 stream이 하나의 TCP byte stream을 공유하기 때문에 한 패킷 손실이 뒤 바이트 전달을 막을 수 있다.

  1. 1

    HTTP/2 streams frame 단위로 요청을 섞어 메시지 HOL 완화

  2. 2

    TLS record 섞인 byte stream을 암호화해 보호

  3. 3

    TCP byte stream 빠진 바이트가 채워질 때까지 뒤 바이트 전달 대기

  4. 4

    IP packets 손실과 재전송이 실제로 발생하는 계층

항목HTTP/1.1HTTP/2HTTP/3
프로토콜 표현텍스트 기반 메시지바이너리 프레임바이너리 프레임
전송 계층TCPTCPQUIC over UDP
멀티플렉싱제한적, 보통 여러 연결 사용한 TCP 연결 안에서 여러 스트림QUIC 스트림 기반
HOL BlockingHTTP 계층 + TCP 계층HTTP 계층은 완화, TCP 계층은 남음TCP HOL은 제거, 스트림 단위로 완화
헤더 압축없음HPACKQPACK
서버 푸시없음프로토콜 기능은 있으나 사용 축소프로토콜에 정의, 사용은 제한적
연결 수립TCP + TLS 여부에 따라 다름TCP + TLS/ALPN 영향QUIC/TLS 1.3, 재개 시 0-RTT 가능
암호화선택표준상 h2/h2c 가능, 브라우저는 사실상 TLSQUIC에 TLS 1.3 통합

마지막으로 HTTP/2를 운영할 때 확인해야 할 프로토콜 상태, 실패 응답, 관측 도구, 복구 기준을 정리합니다.

HTTP/2는 한 TCP 연결 안에 여러 스트림을 프레임으로 섞는다

HTTP/2의 성능 개선은 요청을 하나로 합치는 것이 아니라, HEADERS와 DATA 프레임을 stream ID로 구분해 한 연결에서 섞어 보내는 데 있습니다. 단, TCP 손실은 여전히 연결 전체에 영향을 줍니다.

  1. HTTP/2에서는 여러 연결이 항상 이득이 아니다

    도메인 샤딩 HTTP/2에서는 여러 연결이 항상 이득이 아니다 연결 재사용과 압축 효율을 오히려 떨어뜨릴 수 있습니다.

  2. HTTP 계층 HOL은 줄었지만 전송 계층 HOL은 남는다

    TCP HOL HTTP 계층 HOL은 줄었지만 전송 계층 HOL은 남는다 손실 네트워크에서는 HTTP/3 검토 이유가 됩니다.

  3. 프로토콜 기능과 실무 채택은 다르다

    server push 프로토콜 기능과 실무 채택은 다르다 캐시 중복과 예측 실패 때문에 현대 브라우저에서는 제한적입니다.

이 문제를 줄이기 위해 QUIC 기반의 HTTP/3가 등장했습니다.

다음 절에서 QUIC이 연결 수립, 손실 복구, 스트림 처리 방식을 어떻게 바꾸는지 자세히 다루겠습니다.