Today Key : HTTP/1.1, Request, Response, Header, Keep-Alive, Persistent Connection, Pipelining
HTTP는 웹에서 리소스를 가져오기 위한 프로토콜이고, 브라우저 같은 클라이언트가 요청을 보내면 서버가 응답을 돌려주는 구조로 동작합니다. RFC 9110은 HTTP를 상태를 저장하지 않는 stateless한 애플리케이션 계층 프로토콜로 설명하고, RFC 9112는 그중에서도 HTTP/1.1이 메시지 문법, 파싱, 연결 관리 방식을 어떻게 표현하는지를 정의합니다.
이번 포스팅에서는 HTTP/1.1의 구조와 흐름을 먼저 잡아두고, 이후 HTTP/2와의 차이를 볼 준비를 해봅니다.
HTTP/1.1의 기본 구조, 메시지
HTTP/1.1의 가장 기본 단위는 메시지입니다.
클라이언트가 보내는 것은 요청 메시지이고, 서버가 돌려주는 것은 응답 메시지입니다.
메시지 안에는 무엇을 요청하는지, 어디를 요청하는지, 어떤 형식의 데이터를 원하는지 같은 정보가 헤더와 본문 형태로 담깁니다.
예를 들어 브라우저는 아래처럼 요청을 보낼 수 있습니다.
GET /index.html HTTP/1.1
Host: example.com
Accept: text/html
User-Agent: Mozilla/5.0
Connection: keep-alive
서버는 그에 대해 아래처럼 응답합니다.
HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 1256
<html>...</html>
요청 첫 줄에는 메서드, 대상, 버전이 들어가고, 응답 첫 줄에는 버전과 상태 코드, 상태 문구가 들어갑니다.
그 뒤에는 헤더가 따라오고, 필요하면 마지막에 본문이 붙습니다.
HTTP/1.1이 사람이 읽을 수 있는 텍스트 기반 프로토콜이라는 점 덕분에, 로그나 개발자도구, 패킷 덤프를 볼 때 흐름을 따라가기가 비교적 직관적입니다.
연결 관리, Persistent Connection
HTTP/1.1을 볼 때 반드시 함께 봐야 하는 개념이 연결 관리입니다.
HTTP/1.0 시절에는 요청 하나마다 TCP 연결을 새로 맺고 끊는 방식이 기본이었습니다.
HTTP/1.1에서는 같은 연결을 여러 요청과 응답에 재사용하는 persistent connection 모델이 핵심이 됩니다.
MDN도 HTTP/1.1에서 persistent connection과 pipelining이라는 두 가지 새로운 연결 모델이 등장했다고 설명합니다.
TCP 연결을 새로 맺는 과정 자체가 비용이 들고, TCP는 연결이 어느 정도 유지될 때 더 효율적으로 동작합니다.
연결을 유지한 채 여러 요청과 응답을 주고받는 방식이 성능상 더 유리한 이유입니다.
흔히 Connection: keep-alive라는 표현으로 접하게 되는 부분이 바로 이 연결 재사용 개념과 맞닿아 있습니다.
구조적 한계, Head-of-Line Blocking
persistent connection으로 연결 재사용이 가능해졌지만, 한 연결 안에서 리소스를 처리하는 방식에는 제약이 남아 있습니다.
MDN은 HTTP/1.1에서 클라이언트가 각 리소스의 다운로드가 끝나기를 기다려야 했고, 그 결과 head-of-line blocking 문제가 발생했다고 설명합니다.
앞 요청의 응답이 지연되면 뒤 요청도 그만큼 밀리는 구조입니다.
이 문제를 완화하기 위해 브라우저들은 한 사이트에 대해 여러 개의 TCP 연결을 병렬로 여는 방식을 사용해 왔습니다.
MDN은 대부분의 브라우저가 웹사이트당 최대 6개의 TCP 연결을 허용해 여러 리소스를 동시에 가져오도록 한다고 설명합니다.
단일 연결 재사용이라는 개선은 있었지만, 리소스가 많아질수록 여러 연결을 추가로 열어 병렬성을 확보하는 방향으로 진화한 셈입니다.
Pipelining, 개념과 현실의 간극
HTTP/1.1에서 자주 함께 언급되는 기능이 pipelining입니다.
응답을 기다리지 않고 여러 요청을 연속으로 보내는 방식으로, 개념만 보면 성능 개선에 도움이 될 것처럼 보입니다.
하지만 실제 운영 환경에서는 중간 장비와 구현 차이, 순서 문제 등으로 널리 정착하지 못했습니다.
실무에서 HTTP/1.1을 말할 때는 pipelining보다 persistent connection과 다중 TCP 연결 사용을 더 현실적인 기준으로 보는 편입니다.
HTTP/1.1의 장단점
가장 큰 장점은 단순함과 폭넓은 호환성입니다.
텍스트 기반 메시지 형식과 오랜 운영 경험 덕분에 구현, 분석, 디버깅에서 기준점 역할을 해왔습니다.
RFC 9112 역시 HTTP/1.1 메시지 파서와 중간 전달 장비가 지켜야 할 요구사항을 구체적으로 정의하고 있어, 웹 통신의 기본 문법을 이해하는 데 가장 직접적인 참고 문서가 됩니다.
반면 한계도 분명합니다.
요청과 응답마다 텍스트 헤더가 반복되고, 성능을 높이려면 연결 재사용이나 다중 연결 같은 전략에 의존해야 합니다.
단일 연결 안에서는 처리 순서로 인한 지연 문제가 생기기 쉽고, 한 페이지에 리소스가 많아질수록 비효율이 커집니다.
이것이 HTTP/2가 등장한 중요한 배경이 됩니다.
그럼에도 불구하고 HTTP/1.1은 여전히 중요합니다.
HTTP/2를 이해하려면 무엇이 어떻게 바뀌었는지 비교할 기준이 필요하고, 그 기준이 바로 HTTP/1.1이기 때문입니다.
실제 운영 환경에서 HTTP/2를 사용하고 있더라도, 문제를 분석할 때는 결국 HTTP/1.1의 요청/응답 구조와 연결 관리 개념부터 이해하고 있어야 흐름이 제대로 보입니다.
다음 포스팅에서는 HTTP/1.1을 기준으로, HTTP/2가 무엇을 바꾸었고 왜 더 효율적인 구조로 평가받는지 이어서 살펴보겠습니다.