📚 목차
[Network] HTTP 1.0 VS 1.1 vs 2.0 vs 3.0 딥다이브
인프라는 백엔드 뿐만 아니라 프론트엔드 엔지니어 입장에서도 매우 중요하다고 최근에 느낀다.
"지금 **우리 요청이 실제로 어떤 길(프로토콜)**로 가는지조차 모를 때"
"HTTP라서 브라우저 기능(Service Worker, 일부 API)이 아예 안 켜질 때"
"혼합 콘텐츠(HTTPS 페이지에 HTTP 리소스) 때문에 이미지·폰트가 그냥 차단될 때"
"CORS/쿠키/헤더가 어쩌다 전송되고, 왜 어떤 요청만 막히는지 이해가 안 될 때"
"CDN이 뭘 캐시했고 왜 HIT/MISS인지, 백엔드 에러와 프록시 에러가 구분이 안 될 때"
"인증서가 만료되거나 체인이 꼬여서 그냥 접속 자체가 안 될 때"
이건 최적화의 문제가 아니라 웹이 굴러가는 최소 단위—HTTP와 HTTPS, 그리고 1.0/1.1/2/3 버전의 기본 규칙을 모르면 생기는 막힘이다.
그래서 이 글에서는 왜 요청이 통하고/막히는지, 어떤 제약에서 브라우저가 움직이는지 등 인프라를 이해하는데 필요한 웹의 핵심 프로토콜인 http의 진화와 특징에 대해 깊게 알아보게 되었다.
HTTPS (Hyper Text Transfer Protocol Secure)란?
HTTPS = HTTP + TLS
즉, 평문 프로토콜인 HTTP 위에 **TLS(Transport Layer Security)**를 덧씌워 암호화·무결성·서버 인증을 제공하는 방식이다.
그럼 HTTPS이 왜 필요한 것인가?
- 암호화(Confidentiality): 요청/응답 본문과 대부분의 헤더가 제3자에게 읽히지 않는다.
- 무결성(Integrity): 전송 중 데이터가 바뀌면 바로 탐지된다.
- 서버 인증(Authentication): 브라우저가 서버의 인증서를 검증해 "정말 그 도메인 맞다"를 확인한다.
HTTPS는 "빠르게 만들기 위한 옵션"이 아니라, 웹 기능의 전제이다. 혼합 콘텐츠 차단, 일부 브라우저 API(예: Service Worker), 쿠키 보안 속성 등도 HTTPS를 전제로 동작한다.
HTTP/1.0: 연결 비지속의 시대
HTTP/1.0은 1996년에 출시되었으며, 이전 버전인 0.9보다 훨씬 견고한 프로토콜이 되었다.
주요 특징
- HTTP/1.0은 **헤더(Header)**를 도입하여 프로토콜의 유연성과 확장성을 높였고, 메타데이터 전송이 가능해졌다.
- 요청 라인에 명시적으로 버전을 알리며, 응답에는 요청 처리 상태를 확인할 수 있는 **상태 코드(Status code)**가 포함되었다.
- GET 외에 서버에 데이터를 전송하는 POST와 메타데이터만 검색하는 HEAD 메서드가 추가되었다.
- Content-type 필드 덕분에 일반 HTML 파일 외의 다른 문서 유형을 전송할 수 있게 되었다.
단점
- HTTP/1.0은 서버와 클라이언트 간의 Connection을 지속하지 않는다
- 단 1개의 요청을 처리할 때마다 DNS 조회, TCP 3-way handshake, SSL/TLS handshake와 같이 네트워크 지연 시간을 늘리는 행위를 반복적으로 수행해야 했다. 이는 매우 불필요한 행위였다
HTTP/1.1: 지속 연결과 HOL Blocking의 시작
HTTP/1.1은 1997년, 1.0 출시 후 단 1년 만에 등장하여 1.0의 문제점을 개선한 버전이다
주요 개선점 (Keep-Alive)
- Keep-Alive 기능을 통해 매 요청마다 Connection을 새로 맺지 않기 위해 서버와 클라이언트 간의 연결을 유지한다.
- 이 덕분에 하나의 TCP Connection을 통해 여러 개의 요청과 응답을 처리할 수 있게 되었으며, Keep-Alive는 HTTP/1.1의 기본 동작에 포함되었다.
- 클라이언트가 연결을 끊고 싶다면 Connection: close를 헤더에 포함시켜 명시적으로 서버에 요청할 수 있다.
- HTTP/1.1에서는 Host Header가 사양에 따라 필수로 요구된다
파이프라이닝과 그 한계
HTTP/1.1은 클라이언트가 응답을 기다리지 않고도 단일 TCP 연결을 통해 여러 HTTP 요청을 보내는 파이프라이닝 기능도 있었다.
하지만 파이프라이닝은 요청 순서에 맞게 응답을 받아야 하는 치명적인 단점이 있었다.
만약 [요청1, 요청2, 요청3] 순서로 요청했으나 응답2가 먼저 도착했더라도, 응답2는 응답1이 오기 전까지 처리되지 않고 기다려야 했다.
이처럼 동일한 연결 내에서 특정 요청 때문에 후속 요청이 영향을 받는 현상을 **Head of Line Blocking (HOL Blocking)**이라고 한다.
파이프라이닝은 구현이 어려웠고 프록시 서버 처리 문제 때문에 크롬, 파이어폭스 같은 브라우저들은 결국 이 기능을 지원하지 않게 되었다.

HTTP/2.0: 멀티플렉싱으로 애플리케이션 계층 해결
HTTP/2.0은 2015년에 공식 출시되었으며, 프로토콜 성능 개선에 중점을 두었다
바이너리 프로토콜 및 스트림 도입
HTTP/1.1이 메시지를 텍스트(text)로 보냈다면, HTTP/2.0은 메시지를 바이너리화하여 전송한다.
메시지는 **헤더 프레임(header frame)**과 **데이터 프레임(data frame)**이라는 데이터 단위로 만들어지며, 각 프레임에 Stream Sequence 번호를 붙여 구분한다.
같은 번호를 가진 프레임들을 묶어 **스트림(Stream)**이라는 개념으로 구분 짓는다.

멀티플렉싱 (Multiplexing)
스트림 개념을 도입한 덕분에 HTTP/2.0은 멀티플렉싱을 통해 단일 연결(TCP Connection)에서 여러 개의 요청과 응답을 비동기적으로 처리할 수 있게 되었다.
이로써 HTTP/1.1에서 응답 순서 때문에 후속 요청이 영향을 받던 Application Layer의 HOL Blocking 문제를 해결할 수 있었다.
남겨진 문제 (TCP HOL Blocking)
HTTP/2.0은 여전히 TCP Connection 위에서 프레임들을 주고받기 때문에, Transport Layer(전송 계층)에서 발생하는 HOL Blocking은 해결할 수 없었다.
예를 들어, 특정 스트림의 패킷이 손실되면, 해당 패킷이 올 때까지 뒤따르는 다른 스트림의 패킷들(데이터)까지 여전히 기다리게 되었다
예시를 간단히 적어보자면
HTTP/1.1 (한 연결, 줄 서기)
[ AAAAAAA ] [ BBB ] [ CCCCC ] ← A 끝나야 B, B 끝나야 C
HTTP/2/3 (한 연결, 멀티플렉싱)
[ A A A A ]
[ B B ] ← A/B/C 조각(프레임)들이 번갈아 섞여 흐름
[ C C C ]- 요청·응답은 더 작은 프레임으로 쪼개져서, 스트림 ID로 구분되어 한 연결 안에서 섞여 흐른다.
- 서버와 클라이언트는 각 스트림마다 **흐름 제어(Flow Control)**와 우선순위 힌트로 어떤 걸 먼저 많이 보내줄지 조율할 수 있다.
Server Push
클라이언트가 요청하기 전에 서버가 클라이언트에 미리 리소스를 보내 네트워크 요청을 줄일 수 있을 것으로 예상되는 Server Push 기능도 있었다.
하지만 클라이언트가 서버가 보낸 리소스를 알지 못하고 다시 요청하는 등의 문제로 인해, Google은 2022년 10월 Chrome에서 Server push 기능을 제거했다.

HTTP/3.0: QUIC으로 전송 계층의 한계를 돌파
HTTP/3.0은 2020년에 첫 드래프트가 발표되었으며, TCP에 의존했던 이전 버전들과 달리 새로운 전송 계층 프로토콜을 사용하는 것이 핵심이다
QUIC 프로토콜 사용
- HTTP/3.0은 TCP HOL Blocking을 해결하기 위해 TCP 대신 UDP에 기반한 QUIC (Quick UDP Internet Connections) 프로토콜을 사용한다.
- QUIC은 네이티브 멀티플렉싱 기능과 암호화(built-in encryption) 기능을 내장한 전송 계층 프로토콜이다

HOL Blocking의 종식 (Transport Layer)
QUIC 프로토콜을 사용하면서 각 스트림들이 독립적이게 되었다.
HTTP/2에서 TCP 기반에서는 패킷 하나가 손실되면 후속 패킷 전체가 막히지만, HTTP/3에서 QUIC 기반에서는 손실된 패킷과 관련된 일부 패킷만 Blocking 되고 나머지 스트림은 영향을 받지 않는다. 이로써 Transport Layer에서의 HOL Blocking 문제를 해결했다.
Zero RTT Connection 달성
HTTP/3.0의 QUIC은 서버와 클라이언트 간의 연결을 맺는 데 **0 RTT(Round-Trip Time)**를 달성한다.
TCP 연결은 1 RTT, TCP + TLS 연결은 2~3 RTT가 걸리는 것에 비해, HTTP/3.0은 연결과 동시에 데이터를 전송할 수 있게 되었다.
HTTP/3.0은 항상 암호화된 연결을 생성하므로, HTTP/2.0에서 HTTPS를 항상 사용하는 것과 유사하다.
마무리
이번 글에서는 웹이 기본적으로 어떻게 통신하는지에 대해 알아보았다.
HTTP는 웹이 “통하는 방식” 그 자체다. 메서드·헤더·버전·보안·중간자 규칙을 이해하면, 기능이 왜 켜지고/막히는지 설명할 수 있고, 팀과 같은 언어로 문제를 풀 수 있다.
이때까지 배운 내용들을 아래와 같이 정리해보았다.
- HTTP/1.0/1.1은 “연결을 어떻게 열고 유지하나”, “왜 줄을 서는가”를 보여준다.
- HTTP/2는 “한 연결 안에서 여러 일을 동시에” 하게 만든 멀티플렉싱의 의미를 알려준다.
- HTTP/3는 “왜 TCP를 벗어나 QUIC으로 갔는가”—손실/모바일 환경에서 덜 막히게 하려는 시도의 결과다.
| 구분 | 전송 방식 | 다중화 | 헤더 압축 | 우선순위 | HOL Blocking | 핸드셰이크 | 서버푸시 |
|---|---|---|---|---|---|---|---|
| HTTP/1.0 | TCP 1요청=1연결 | ✗ | ✗ | ✗ | 심각(요청/연결 단위) | TCP | ✗ |
| HTTP/1.1 | TCP 지속 연결(keep-alive) | 파이프라이닝(비권장) | ✗ | (사실상 없음) | 연결 단위 HOL 지속 | TCP | ✗ |
| HTTP/2 | TCP 1연결 다중화(스트림) | 멀티플렉싱 | HPACK | (우선순위/가중치, 구현차) | TCP HOL 존재(연결 단위) | TCP + TLS 보편 | △(사양 존재, 실전 비권장) |
| HTTP/3 | QUIC(UDP 기반) | 멀티플렉싱 | QPACK | 개선됨 | HOL 완화(스트림 독립) | TLS 1.3 내장(0-RTT) | (사양 無; 푸시는 사실상 폐기 수순) |
| HTTPS | HTTP 위에 TLS | – | – | – | – | TLS 핸드셰이크 | – |