블로그 목록

HTTP/1.1 vs 2 vs 3 — 프론트 성능과 사라진 최적화들

2026-06-268 min read
HTTP성능네트워크QUIC프론트엔드

"2는 멀티플렉싱, 3은 QUIC"까지는 외우기 쉽다. 한 걸음 더 들어가 HOL 블로킹이 어느 계층에서 일어나는가를 축으로 잡으면, 세 버전이 깔끔하게 정리되고 왜 옛날 최적화가 이제 안티패턴인지까지 자연스럽게 풀린다.

1. 큰 그림 — HOL 블로킹은 두 계층에 있다

Head-of-Line(HOL) 블로킹 = 앞의 것이 막히면 뒤가 다 기다리는 현상. 이게 두 군데서 일어난다.

버전이 올라갈수록 HOL 블로킹을 한 계층씩 제거해 왔다HTTP/1.1TCP · 연결당 순차HTTP/2TCP · 멀티플렉싱HTTP/3QUIC (UDP)HTTP 계층 HOL❌ 있음✅ 없음✅ 없음TCP 계층 HOL❌ 있음❌ 있음✅ 없음프론트 핵심요청 수 줄이기샤딩 · 스프라이트샤딩 폐기캐시 단위 분할모바일 · 재방문지연 개선2는 멀티플렉싱으로 HTTP HOL을, 3은 QUIC으로 TCP 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.1TCP, 연결당 순차—요청 수 줄이기(샤딩·concat)
HTTP/2TCP, 멀티플렉싱HTTP HOL샤딩·스프라이트 폐기, 캐시 단위 분할
HTTP/3QUIC(UDP)HTTP + TCP HOL모바일·재방문 지연 개선

한 줄 정리 — HTTP/2는 멀티플렉싱으로 HTTP 계층 HOL을, HTTP/3은 QUIC으로 TCP 계층 HOL까지 없앴다. 그 결과 "요청 수를 줄이려던" 1.1식 최적화(샤딩·스프라이트·과한 번들)는 안티패턴이 되고, 프론트는 캐시 효율 중심의 분할 + 연결/우선순위 힌트로 무게중심이 옮겨갔다.