"2는 멀티플렉싱, 3은 QUIC"까지는 외우기 쉽다. 한 걸음 더 들어가 HOL 블로킹이 어느 계층에서 일어나는가를 축으로 잡으면, 세 버전이 깔끔하게 정리되고 왜 옛날 최적화가 이제 안티패턴인지까지 자연스럽게 풀린다.
1. 큰 그림 — HOL 블로킹은 두 계층에 있다
Head-of-Line(HOL) 블로킹 = 앞의 것이 막히면 뒤가 다 기다리는 현상. 이게 두 군데서 일어난다.
각 버전은 이 두 블로킹을 하나씩 제거해 온 역사다.
2. HTTP/1.1 — 연결당 한 번에 하나
한 TCP 연결에서 요청을 보내면 응답이 올 때까지 다음 요청을 못 보낸다(순차 처리). 이게 HTTP 계층 HOL 블로킹이다.
파이프라이닝(요청을 연달아 보내기)이 스펙엔 있었지만, 응답은 보낸 순서대로 와야 해서 느린 응답 하나가 뒤를 다 막았다. 사실상 폐기됐다.
브라우저의 우회책은 오리진당 연결을 6개쯤 동시에 여는 것. 하지만 6개도 금방 부족하다. 그래서 당시의 "최적화"가 등장했다.
- 도메인 샤딩 —
img1.site.com,img2.site.com으로 도메인을 쪼개 연결 한도(6개)를 늘림 - 번들 concat · CSS 스프라이트 · 이미지 인라인(base64) — 요청 개수 자체를 줄임
이 기법들은 전부 "요청 수가 비싸다"는 1.1의 제약에서 나왔다. 이게 핵심이다 — HTTP/2부터 전제가 바뀐다.
3. HTTP/2 — 멀티플렉싱으로 HTTP HOL 제거
한 TCP 연결 위에서 여러 스트림을 병렬로 주고받는다. 응답 순서도 상관없다.
- 바이너리 프레이밍 — 메시지를 프레임으로 쪼개 스트림 ID를 붙임 → 한 연결에 여러 요청이 뒤섞여 흘러도 재조립 가능
- 멀티플렉싱 — 연결 1개로 수십 개 리소스를 동시에 → 연결 6개 우회가 불필요
- HPACK 헤더 압축 — 반복되는 헤더(쿠키 등)를 압축
- 스트림 우선순위 — 중요한 리소스(CSS) 먼저
그래서 옛날 기법이 안티패턴이 된다
- 도메인 샤딩 ❌ — 이제 연결 1개면 충분. 샤딩하면 연결마다 TCP 핸드셰이크·혼잡제어가 따로 돌아 오히려 느려진다.
- 과도한 번들 concat ❌ — 하나로 합치면 작은 변경에도 전체 캐시가 무효화된다. 잘게 쪼개도 멀티플렉싱으로 병렬 전송되니, 캐시 효율을 위해 적당히 나누는 게 유리.
- CSS 스프라이트 · base64 인라인 ❌ — 요청 수가 더는 비싸지 않으니 이득이 사라지고 캐시·관리만 나빠진다.
하지만 남은 한계 — TCP HOL
HTTP/2는 결국 TCP 연결 하나에 모든 스트림을 싣는다. TCP는 패킷을 순서대로 보장하므로, 패킷 하나만 유실돼도 재전송을 기다리는 동안 그 연결의 모든 스트림이 멈춘다.
아이러니하게도 1.1은 연결이 6개라 하나가 막혀도 나머지가 살아있었는데, 2는 연결을 1개로 합친 탓에 패킷 손실에 더 취약할 수 있다. 손실률 높은 모바일·불안정 네트워크에서 이게 드러난다.
4. HTTP/3 — QUIC으로 TCP HOL까지 제거
TCP를 버리고 UDP 기반 QUIC 위에서 동작한다. UDP는 순서 보장이 없는 대신, QUIC이 스트림을 독립적으로 관리한다.
- 스트림별 독립 전송 — 한 스트림의 패킷이 유실돼도 다른 스트림은 영향 없음 → TCP HOL 제거
- 빠른 연결 수립 — 전송 + 암호화(TLS 1.3)를 하나로 묶어 핸드셰이크가 짧다. 재방문 시 0-RTT로 사실상 즉시 시작
- 연결 마이그레이션 — Wi-Fi ↔ LTE로 네트워크가 바뀌어도 Connection ID로 연결 유지 → 모바일 재연결 끊김 없음
프론트 체감: 불안정한 네트워크·모바일에서 특히 강하고, 연결 설정 지연(첫 연결·재방문)이 줄어 TTFB·LCP에 유리하다.
5. 프론트엔드 관점 — 무엇을 바꿔야 하나
| 옛날(1.1) 기법 | 2/3 시대 | 이유 |
|---|---|---|
| 도메인 샤딩 | 버림 | 연결 1개로 충분, 샤딩은 오히려 오버헤드 |
| 무조건 번들 합치기 | 적당히 분할 | 멀티플렉싱 + 캐시 효율 |
| CSS 스프라이트 | 버림 | 요청 수가 더는 비싸지 않음 |
| base64 인라인 | 신중히 | 캐시 불가 + 33% 용량 증가 |
여전히 유효한 것 (프로토콜과 무관):
- 압축(gzip/brotli), 캐시 헤더, CDN, 이미지 포맷 최적화, 라우트 단위 코드 스플리팅, 중요 리소스
preload preconnect/preload같은 연결·우선순위 힌트는 오히려 더 중요해졌다.
즉 HTTP/2·3로 바뀌면서 "요청 수를 줄여라"는 규칙이 "캐시 단위로 잘 쪼개라"로 역전됐다.
6. 정리
| 버전 | 전송 | 없앤 블로킹 | 프론트 핵심 |
|---|---|---|---|
| HTTP/1.1 | TCP, 연결당 순차 | — | 요청 수 줄이기(샤딩·concat) |
| HTTP/2 | TCP, 멀티플렉싱 | HTTP HOL | 샤딩·스프라이트 폐기, 캐시 단위 분할 |
| HTTP/3 | QUIC(UDP) | HTTP + TCP HOL | 모바일·재방문 지연 개선 |
한 줄 정리 — HTTP/2는 멀티플렉싱으로 HTTP 계층 HOL을, HTTP/3은 QUIC으로 TCP 계층 HOL까지 없앴다. 그 결과 "요청 수를 줄이려던" 1.1식 최적화(샤딩·스프라이트·과한 번들)는 안티패턴이 되고, 프론트는 캐시 효율 중심의 분할 + 연결/우선순위 힌트로 무게중심이 옮겨갔다.