HTTP(HyperText Transfer Protocol)는 웹 브라우저와 웹 서버 간의 통신 규칙을 정의한 프로토콜입니다. HTTP는 시대의 요구에 따라 기술적인 한계를 극복하며 발전해왔습니다.
본 문서는 HTTP/1.0부터 HTTP/3에 이르기까지 각 버전의 주요 특징과 등장 배경, 그리고 기술적인 발전 과정을 중심으로 설명합니다.
HTTP/1.0: 요청 단위의 TCP 연결
HTTP/1.0은 1996년에 등장하여 초기 웹 생태계의 성장을 이끌었습니다. 이 버전의 가장 큰 특징은 요청마다 새로운 TCP 연결을 생성한다는 점입니다. 클라이언트가 특정 리소스를 요청하면, 서버와 TCP 연결을 수립하고 응답을 받은 직후 연결을 해제했습니다. 이로 인해 한 페이지에 포함된 여러 리소스(HTML, CSS, 이미지 등)를 다운로드하려면 각각의 리소스마다 연결과 해제 과정을 반복해야 했습니다.
한계점
이 방식은 TCP 연결 과정(3-way handshake)에서 발생하는 오버헤드 때문에 비효율적이었습니다. 페이지 하나를 로드하기 위해 수십 번의 연결과 해제가 반복되면서 네트워크 지연과 서버 부하를 유발하여 성능 저하의 주요 원인이 되었습니다.
HTTP/1.1: 연결 재사용과 파이프라이닝
1997년에 발표된 HTTP/1.1은 HTTP/1.0의 비효율 문제를 해결하기 위해 등장했으며, 오랫동안 웹 통신의 표준으로 자리 잡았습니다.
주요 개선 사항
- 지속적 연결(Persistent Connection): HTTP/1.0의 가장 큰 문제였던 ‘요청마다 연결 맺기’를 개선했습니다.
Keep-Alive기능을 통해 한 번 맺은 TCP 연결을 재사용하여 여러 요청을 처리할 수 있게 되면서, 네트워크 부하와 지연 시간을 크게 줄였습니다. - 파이프라이닝(Pipelining): 하나의 연결에서 응답을 기다리지 않고 여러 요청을 순차적으로 전송할 수 있는 기능입니다. 이를 통해 통신 지연을 일부 개선할 수 있었습니다.
한계점
하지만 HTTP/1.1은 다음과 같은 구조적 한계를 가지고 있었습니다.
- HOL(Head-of-Line) Blocking: 파이프라이닝을 사용하더라도, 응답은 반드시 요청 순서에 맞춰 수신되어야 합니다. 만약 첫 번째 요청에 대한 응답이 지연되면 후속 요청들의 처리도 함께 지연되는 ‘병목 현상’이 발생했습니다.
- 비대한 헤더(Header): 다수의 요청에서 거의 동일한 내용의 헤더 정보가 중복으로 전송되어 불필요한 데이터 낭비를 초래했습니다.
- 파이프라이닝의 현실적 문제: 이론적으로는 성능 향상이 가능했지만, 많은 프록시 서버와 중개 노드가 파이프라이닝을 제대로 지원하지 않거나 오류를 발생시키는 경우가 많아 실제 환경에서는 거의 활성화되지 못했습니다.
HTTP/2: 스트림을 통한 다중화
HTTP/2는 HTTP/1.1의 성능 한계를 극복하기 위해 2015년에 등장했습니다. HTTP/2는 이전 버전을 대체하는 것이 아니라, 성능을 개선하는 확장(extension)으로 설계되었습니다.
주요 개선 사항
- 멀티플렉싱(Multiplexing): HTTP/1.1의 고질적인 문제였던 HOL Blocking을 해결하기 위한 핵심 기능입니다. 하나의 TCP 연결 위에서 여러 개의 요청과 응답을 동시에, 순서에 상관없이 주고받을 수 있습니다. 각 요청과 응답은 고유한 스트림(Stream) ID를 가지므로, 먼저 준비되는 응답부터 클라이언트에 전달될 수 있습니다.
- 바이너리 프레이밍(Binary Framing): HTTP/1.1이 줄바꿈으로 구분되는 일반 텍스트(Plain Text)를 사용한 반면, HTTP/2는 모든 메시지를 프레임(Frame)이라는 작은 단위로 분할하고 바이너리 형식으로 인코딩하여 전송합니다. 요청/응답 메시지는
HEADERS프레임(헤더 정보)과DATA프레임(본문) 등으로 구성됩니다. 이 구조 덕분에 멀티플렉싱이 가능해졌으며, 텍스트 파싱(parsing) 과정이 필요 없어 더 빠르고 효율적인 처리가 가능합니다. - 헤더 압축(Header Compression): HPACK이라는 헤더 압축 방식을 사용하여 중복된 헤더 필드를 제거하고, 전송 데이터의 크기를 획기적으로 줄였습니다.
- 서버 푸시(Server Push): 클라이언트가 요청하지 않은 리소스를 서버가 능동적으로 전송하는 기능입니다. 예를 들어, 클라이언트가
index.html을 요청했을 때, 해당 페이지가 필요로 하는style.css와script.js파일을 서버가 미리 함께 전송하여 추가적인 요청 없이도 클라이언트가 리소스를 바로 사용할 수 있게 합니다. - 스트림 우선순위(Stream Prioritization): 여러 요청이 동시에 처리될 때, 브라우저가 리소스의 중요도(예: 렌더링을 막는 CSS 파일을 이미지보다 우선)에 따라 우선순위를 설정할 수 있습니다. 서버는 이 우선순위를 바탕으로 중요한 리소스를 먼저 전송하여 렌더링 성능을 최적화합니다.
한계점: TCP 계층의 HOL Blocking
HTTP/2는 애플리케이션 계층에서 스트림을 통해 HOL Blocking을 해결했지만, 전송 계층인 TCP가 가진 HOL Blocking 문제는 해결하지 못했습니다. TCP는 패킷의 순서를 보장해야 하므로, 하나의 패킷이 유실되면 해당 패킷이 재전송될 때까지 그 뒤의 모든 패킷(다른 스트림의 데이터 포함)이 대기해야 하는 문제가 여전히 존재했습니다.
HTTP/3: QUIC 기반의 새로운 전송 프로토콜
HTTP/3는 HTTP/2가 남긴 TCP의 한계를 극복하기 위해 등장한 최신 버전입니다. 가장 큰 변화는 전송 프로토콜을 TCP에서 UDP 기반의 QUIC(Quick UDP Internet Connections)으로 전환한 것입니다.
주요 개선 사항
- QUIC를 통한 HOL Blocking 해결: QUIC는 TCP와 달리 스트림 간 순서 보장을 요구하지 않습니다. 각 스트림이 독립적인 전송 단위로 취급되므로, 한 스트림에서 패킷 손실이 발생하더라도 다른 스트림은 영향을 받지 않고 데이터를 계속 전송할 수 있습니다. 이를 통해 전송 계층의 HOL Blocking을 해결했습니다.
- 0-RTT 연결 수립 (0-RTT Connection Establishment): 이전에 연결한 적이 있는 클라이언트가 서버에 다시 연결할 때, 핸드셰이크 과정을 생략하고 첫 패킷부터 바로 데이터를 전송할 수 있는 기능입니다. 이를 통해 연결 지연을 최소화합니다.
- 연결 마이그레이션(Connection Migration): 클라이언트의 네트워크 환경이 변경(예: Wi-Fi에서 LTE로 전환)되어 IP 주소가 바뀌더라도, QUIC의 고유한
Connection ID를 사용하여 연결을 식별합니다. 덕분에 연결이 끊기지 않고 연속적인 통신이 가능합니다.
버전별 특징 요약 및 결론
HTTP의 발전 과정은 각 버전이 이전 버전의 한계를 어떻게 해결했는지 중심으로 요약할 수 있습니다.
| 버전 | 주요 특징 | 해결한 문제점 (이전 버전 대비) | 남은 한계점/문제점 |
|---|---|---|---|
| HTTP/1.0 | 요청/응답 당 하나의 TCP 연결 | - | 매 요청마다 새로운 연결 생성 (높은 오버헤드) |
| HTTP/1.1 | 지속적 연결, 파이프라이닝 | 연결 재사용으로 오버헤드 감소 | 애플리케이션 계층의 HOL Blocking, 비대한 헤더, 파이프라이닝의 현실적 문제 |
| HTTP/2 | 멀티플렉싱, 바이너리 프레이밍, 헤더 압축(HPACK), 서버 푸시, 스트림 우선순위 | Application-Layer의 HOL Blocking 해결, 헤더 중복 제거, RTT 감소 | Transport-Layer(TCP)의 HOL Blocking 잔존 |
| HTTP/3 | QUIC(UDP 기반), 0-RTT 연결, 연결 마이그레이션 | Transport-Layer의 HOL Blocking 해결, 연결 설정 시간 단축 | 현재진행형으로 프로토콜 확산 중 |
이처럼 HTTP는 더 빠르고 효율적인 통신을 위해 지속적으로 발전해왔습니다. 현재는 HTTP/1.1과 HTTP/2가 안정적으로 사용되며 공존하고 있으며, HTTP/3는 차세대 프로토콜로서 점차 적용 범위를 넓혀가고 있습니다.