콘텐츠로 이동

네트워크 3편 - HTTP의 진화, 트레이드오프의 역사

작성일: 2026년 4월 25일

과거의 정답이 현재의 오답이 될 때, 우리는 그것을 경로 의존성이라 부른다. 1981년에 설계된 TCP는 현대의 초고속 트래픽을 감당하기에 너무 좁았다. HTTP의 진화는 이 견고한 경로에서 벗어나기 위한 30년간의 탈출기다.

계약 비용을 줄였더니, 이번엔 줄 서기가 발목을 잡았다. Keep-Alive로 연결을 유지하는 데 성공했지만, 데이터는 앞 요청을 기다리느라 멈춰 서 있었다. 엔진을 고쳤는데 도로가 1차선인 상황인 것이다. 이것이 HTTP/1.1이 마주한 두 번째 병목이었다.


Keep-Alive 덕분에 하나의 연결로 여러 요청을 처리할 수 있게 되었다. 연결 수립 비용은 줄었다. 하지만 전달 큐는 여전히 한 줄이었다. 애플리케이션 프로토콜을 개선하자 더 깊은 곳에 있던 전송 계층의 병목이 드러났다. 그 병목은 TCP였다.

HTTP/1.1에는 철저한 규칙이 하나 있었다. 한 연결에서는 한 번에 하나의 요청만 순서대로 처리한다.

Keep-Alive 덕분에 매번 새 계약을 맺을 필요는 없어졌다. 하지만 물건을 보낼 때는 앞선 물건이 도착할 때까지 다음 물건은 출발조차 못 한다. 용량이 큰 이미지 하나가 앞에서 지연되면, 뒤에 있는 가벼운 텍스트 데이터들은 줄줄이 대기해야 했다. 이것이 Head-of-Line Blocking(HOLB)이다.

Reference: TCP Head-of-Line Blocking — http3-explained

브라우저들은 이 줄을 여러 개 만들기 위해 서버당 연결을 6개씩 강제로 열어 대응했다. 하지만 이는 다시 2편에서 말한 포트 고갈과 서버 부하라는 비용을 발생시켰다. 문제가 해결된 것이 아니라, 단지 다른 형태의 비용으로 전가된 것이다.


2015년 등장한 HTTP/2는 이 줄 세우기 문제를 애플리케이션 계층에서 해결하려 했다. 바로 멀티플렉싱(Multiplexing)이다.

하나의 연결 안에서 여러 요청과 응답을 조각(Frame)으로 잘게 나누어 섞어서 보낸다. 다시 말해 큰 데이터 조각 사이사이에 작은 데이터들이 끼어들 수 있게 됐다. 겉으로 보기엔 완벽한 병렬 처리처럼 보였다.

그런데 하부 도로인 TCP가 여전히 1차선이다.

TCP는 패킷 순서를 엄격하게 지킨다. 중간에 패킷 하나가 유실되면, TCP는 그 패킷을 다시 받을 때까지 뒤에 도착한 다른 조각들을 모두 멈춰 세운다. 애플리케이션 계층에서는 길을 넓혔지만, 하위 계층의 낡은 규칙이 전체 속도를 제한하는 상황이 반복됐다.

경로 의존성이 작동하는 방식이 바로 이것이다. TCP라는 초기 선택이 이후의 모든 개선에 한계를 부여했다. HTTP/2는 존속적 혁신이었다. 기존 경로 위에서 최선을 다했지만, 경로 자체를 바꾸지는 못했다.

Reference: web.dev: HTTP/2


결국 구글은 TCP를 버리는 결단을 내렸다.

그런데 여기서 오해가 생기기 쉽다. TCP를 버렸다고 해서 신뢰성까지 포기한 게 아니다. TCP가 하던 일을 더 잘하는 방식으로 대체한 것이다.

새로운 토대는 UDP다. UDP는 TCP와 달리 패킷 순서도 보장하지 않고, 유실돼도 재전송하지 않는다. 그냥 빠르게 던지는 것만 한다. 구글은 이 단순한 토대 위에 QUIC이라는 새로운 전송 계층을 직접 쌓았다. TCP가 하던 재전송, 암호화, 연결 관리를 QUIC이 떠안되, 스트림별로 독립적으로 처리하는 방식으로 HOL Blocking을 근본적으로 없앴다.

HTTP/2 (TCP) HTTP/3 (QUIC)
┌────────────────────┐ ┌────────────────────┐
│ Stream A │ │ Stream A │
│ Stream B │ │ Stream B │
│ Stream C │ │ Stream C │
└─────────┬──────────┘ └──┬──────┬──────┬───┘
│ │ │ │
▼ ▼ ▼ ▼
┌─────────┐ 독립적인 스트림 처리
│ TCP │ (QUIC 내부)
└────┬────┘ │
▼ ▼
IP UDP
TCP : 하나의 패킷 손실 → 전체 스트림 대기 (HOL Blocking)
QUIC : 손실된 스트림만 대기 → 다른 스트림은 계속 처리

HTTP/3가 “UDP 기반”이라고 불리는 이유가 여기 있다. UDP 위에 QUIC을 얹고, 그 위에 HTTP/3가 동작한다. TCP를 버린 게 아니라, TCP가 하던 역할을 QUIC으로 대체한 것이다.

왜 유튜브와 줌은 이미 UDP를 쓰고 있었는가

섹션 제목: “왜 유튜브와 줌은 이미 UDP를 쓰고 있었는가”

실시간 스트리밍 서비스는 오래전부터 TCP 대신 UDP를 선택해왔다. 영상 통화 중 패킷 하나가 유실됐을 때, TCP처럼 전체를 멈추고 기다리면 화면이 굳어버린다. 차라리 그 순간을 건너뛰고 다음 프레임을 받는 게 낫다. 신뢰성보다 연속성이 더 중요한 상황에서는 TCP의 신뢰성이 오히려 적이 된다.

QUIC은 이 발상을 가져와 일반 웹 트래픽에 적용했다. 패킷 유실이 발생해도 해당 스트림만 멈추고, 나머지는 계속 진행된다.

0-RTT — 보안 핸드셰이크 비용 절감

섹션 제목: “0-RTT — 보안 핸드셰이크 비용 절감”

2편에서 다룬 1.5 RTT의 비용을 기억하는가. TCP 위에 HTTPS를 쓰면 TLS 보안 핸드셰이크 비용까지 추가로 발생한다. 연결 하나를 맺는 데만 최대 3 RTT가 소모되는 구조다.

QUIC은 TLS 1.3을 내장해 연결과 보안 협상을 동시에 처리한다. 이전에 접속한 적 있는 서버라면 핸드셰이크 없이 바로 데이터를 보낼 수 있다. 2편에서 말한 1.5 RTT가 0으로 수렴하는 것이다.

┌─────────────────────┬────────────────────┐
│ TCP + TLS │ QUIC │
├─────────────────────┼────────────────────┤
│ TCP 1.5 RTT │ 최초 1 RTT │
│ TLS 1.5 RTT │ 재접속 0 RTT │
│ ─────────────── │ │
│ 합계 3 RTT │ │
└─────────────────────┴────────────────────┘

이런 방식엔 거대한 트레이드오프가 존재한다. TCP가 담당하던 신뢰성, 보안, 연결 관리를 QUIC이 애플리케이션 레벨에서 직접 떠안는다. 속도를 얻기 위해 복잡함을 감수한 것이다.

Reference: Chromium: QUIC
Reference: RFC 9000: QUIC


[ HTTP/1.1 — 요청은 반드시 순서대로 ]
시간 → t1 t2 t3 t4 t5
R1 [====] [====]
R2 [====] [====]
R3 [====]
R1이 끝나야 R2 시작, R2가 끝나야 R3 시작
---
[ HTTP/2 — 패킷 유실 시 전체 동결 ]
시간 → t1 t2 t3 t4 t5
R1 [====] [====] [====]
R2 [====] ✕ ← 유실
R3 [====] ← 대기 중... ← 대기 중...
✕ 발생 시, R1·R2·R3 전부 멈춤
---
[ HTTP/3 — 패킷 유실 시 해당 스트림만 정지 ]
시간 → t1 t2 t3 t4 t5
R1 [====] [====] [====] [====]
R2 [====] ✕ ← 유실 [재전송]
R3 [====] [====] [====] [====] ← 계속 진행
✕ 발생해도 R1·R3는 멈추지 않음

버전이 바뀔 때마다 선택도 바뀌었다. 비용을 없앤 게 아니라, 감당하는 위치를 옮긴 것이다.


이 진화 과정 전체에 걸쳐, 두 가지 보이지 않는 패턴이 발전 속도를 좌우했다.

하나는 수십 년 전의 결정이 그 위에 쌓이는 모든 새로운 계층의 처리 속도를 정체시켰고, 다른 하나는 점진적 개선이 한계에 도달하여 시스템 자체를 완전히 교체해야 했다.

경영학에서는 이를 다음과 같이 정의한다.

전 세계의 라우터와 방화벽이 TCP에 최적화되어 있었기에, 더 효율적인 대안이 있어도 TCP를 쉽게 떠날 수 없었다. 이것이 전형적인 경로 의존성이다. 1980년대의 선택이 2020년대의 기술적 선택지의 발목을 잡아 온 셈이다.

혁신의 딜레마(Innovator’s Dilemma)

섹션 제목: “혁신의 딜레마(Innovator’s Dilemma)”

HTTP/1.1에서 HTTP/2로의 이동은 존속적 혁신이었다. 기존 체제를 유지하며 성능을 개선하려 했다. 안전했지만 구조적 한계를 깰 수 없었다.

반면 HTTP/3는 파괴적 혁신(disruptive innovation)이다. 기존 표준을 버리고 완전히 새로운 기반을 선택했다. 위험했지만 병목을 근본적으로 해결했다. 경로 의존성이라는 제한을 끊어내는 데 30년이 걸렸다.

이 두 개념의 교차점에 현재 웹 기술이 있다. 경로 의존성은 웹의 진화가 왜 40년이나 걸렸는지 보여준다. 혁신의 딜레마는 왜 이토록 급진적인 전환이 불가피했는지 설명한다.

Reference: Clayton Christensen: The Innovator’s Dilemma


HTTP/1.1은 계약 비용을 줄였고, HTTP/2는 거래의 밀도를 높였으며, HTTP/3는 과거의 레거시를 거부하며 속도를 얻었다. 프로토콜의 진화는 기술적 정답을 찾는 과정이 아니다. 시대에 맞는 최선의 트레이드오프를 선택해 온 역사다.

경로를 따라 개선할 것인가, 경로 자체를 바꿀 것인가. 이 질문은 프로토콜에만 적용되는 게 아니다.

다음 편에서는 수만 대의 요청이 동시에 몰려올 때 그것을 적절한 서버로 안내하는 관제탑, 로드 밸런서를 들여다본다. L4와 L7에서 각각 어떻게 트래픽을 처리하는지, 그리고 그 선택이 어떤 트레이드오프를 만드는지를 살펴본다.