전체 목록
네트워크Hard#25

HTTP/1.1, HTTP/2, HTTP/3의 주요 차이점을 설명해주세요.

#네트워크#HTTP#프로토콜#성능
힌트

멀티플렉싱, HOL 블로킹, QUIC 프로토콜을 생각해보세요.

정답 및 해설

HTTP/1.1, HTTP/2, HTTP/3의 주요 차이점을 설명해주세요.

HTTP는 웹의 근간이 되는 프로토콜로, 버전이 올라갈수록 성능과 효율이 크게 향상되었습니다. 각 버전은 이전 버전의 한계를 극복하기 위해 설계되었으며, 네트워크 계층 수준의 근본적인 변화를 포함합니다.

HTTP/1.1

1997년 표준화된 HTTP/1.1은 현재도 널리 사용됩니다.

특징

텍스트 기반 프로토콜

요청과 응답이 사람이 읽을 수 있는 ASCII 텍스트 형태입니다.

GET /index.html HTTP/1.1
Host: example.com
User-Agent: Mozilla/5.0
Accept: text/html

HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 1234

<html>...</html>

Keep-Alive (지속 연결)

HTTP/1.0은 요청마다 TCP 연결을 새로 맺었지만, HTTP/1.1은 Keep-Alive로 하나의 TCP 연결을 재사용합니다.

-- 연결 재사용 --
Connection: keep-alive
Keep-Alive: timeout=5, max=100

HOL 블로킹 (Head-of-Line Blocking)

HTTP/1.1의 가장 큰 문제입니다. 하나의 TCP 연결에서 이전 요청의 응답이 오기 전에 다음 요청을 보낼 수 없습니다.

TCP 연결 1:
요청1 →
← 응답1 (대용량 이미지, 3초 소요)
요청2 →  ← 요청1이 끝나야 시작 가능!
← 응답2

이를 극복하기 위해 브라우저는 도메인당 6개의 병렬 TCP 연결을 사용합니다. 이를 이용해 여러 리소스를 동시에 받지만, 연결 수 제한이 있습니다.

워터폴 문제

타임라인:
────────────────────────────────────→ 시간
|  HTML  |
         | CSS | JS |
                     | 이미지1 | 이미지2 | 이미지3 |

리소스들이 순차적으로 다운로드되어 전체 페이지 로드 시간이 길어집니다.

도메인 샤딩 우회 기법

<!-- HTTP/1.1 시대의 꼼수: 여러 서브도메인으로 병렬 연결 수 증가 -->
<img src="https://img1.cdn.com/a.jpg">
<img src="https://img2.cdn.com/b.jpg">
<img src="https://img3.cdn.com/c.jpg">
<!-- 각 도메인마다 6개 연결 → 18개 병렬 연결 -->

HTTP/2

2015년 Google의 SPDY 프로토콜을 기반으로 표준화된 HTTP/2는 성능을 대폭 향상시켰습니다.

바이너리 프레임 계층

HTTP/1.1의 텍스트 기반 대신 바이너리 프레임으로 데이터를 전송합니다.

HTTP/1.1: 텍스트 파싱 → 에러 가능성, 처리 복잡
HTTP/2:   바이너리 → 파싱 효율적, 에러 감소

멀티플렉싱 (Multiplexing)

단일 TCP 연결에서 여러 요청/응답을 동시에 처리합니다. 각 요청은 독립적인 스트림(stream) 으로 관리됩니다.

HTTP/1.1:
TCP 연결:  [요청1]→ ←[응답1] [요청2]→ ←[응답2]  (순차)

HTTP/2:
TCP 연결:  [스트림1: 요청1]→ [스트림2: 요청2]→ [스트림3: 요청3]→
           ←[스트림2: 응답2] ←[스트림1: 응답1] ←[스트림3: 응답3]
           (응답 순서 상관없이 완료 순으로 반환)

HOL 블로킹이 애플리케이션 계층에서는 해결됩니다.

헤더 압축 (HPACK)

HTTP/1.1은 매 요청마다 동일한 헤더를 반복 전송합니다. HTTP/2는 HPACK 압축으로 헤더 오버헤드를 크게 줄입니다.

HTTP/1.1 (매 요청마다 반복):
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64)...  -- 500바이트
Accept: text/html,application/xhtml+xml...                 -- 300바이트
Cookie: session=abc123; preferences=dark...                -- 200바이트

HTTP/2 (HPACK으로 압축):
이전에 보낸 헤더는 인덱스로 참조 → 수십 바이트로 압축

서버 푸시 (Server Push)

클라이언트가 요청하기 전에 서버가 필요한 리소스를 미리 전송합니다.

클라이언트: GET /index.html
서버: 응답 + CSS 푸시 + JS 푸시 + 폰트 푸시
      (클라이언트가 HTML을 파싱하기 전에 이미 리소스 수신 시작)

실무에서는 예측이 어렵고 불필요한 데이터를 전송할 수 있어 많이 사용되지 않습니다. HTTP/3에서는 제거되었습니다.

스트림 우선순위

// 중요한 CSS를 JS보다 우선 전송
// 브라우저가 자동으로 우선순위 협상
// 서버는 가능하면 높은 우선순위 스트림을 먼저 처리

HTTP/2의 한계: TCP 수준 HOL 블로킹

멀티플렉싱으로 애플리케이션 계층의 HOL 블로킹은 해결했지만, TCP 계층의 HOL 블로킹은 여전히 존재합니다.

TCP 패킷 손실 시:
패킷 1 ✓
패킷 2 ✗ (손실)  ← 재전송 대기
패킷 3 ✓ (버퍼에서 대기)
패킷 4 ✓ (버퍼에서 대기)

→ 패킷 2가 재전송될 때까지 패킷 3,4도 사용 불가
→ 모든 HTTP/2 스트림이 블로킹됨

특히 패킷 손실이 잦은 불안정한 네트워크(모바일, Wi-Fi)에서 HTTP/1.1보다 오히려 느릴 수 있습니다.

HTTP/3

2022년 표준화된 HTTP/3는 TCP 대신 QUIC(Quick UDP Internet Connections) 프로토콜을 사용합니다.

QUIC: UDP 기반의 새로운 전송 계층

HTTP/1.1, HTTP/2: IP → TCP → TLS → HTTP
HTTP/3:           IP → UDP → QUIC(TLS 1.3 내장) → HTTP/3

연결 수립 속도 향상

HTTP/1.1 + TLS 1.2:
TCP SYN → TCP SYN-ACK → TCP ACK         (1.5 RTT)
TLS Hello → TLS Hello → TLS Finished... (2 RTT)
총 3.5 RTT 후 데이터 전송 시작

HTTP/2 + TLS 1.3:
TCP 3-way handshake (1.5 RTT)
TLS 1.3 handshake (1 RTT)
총 2.5 RTT

HTTP/3 + QUIC:
QUIC Initial (0-RTT 또는 1-RTT) — TLS가 QUIC에 통합
첫 연결: 1 RTT
재연결: 0-RTT (이전 연결 정보 재사용)

독립 스트림 (TCP HOL 블로킹 완전 해결)

QUIC는 각 스트림을 완전히 독립적으로 관리합니다.

QUIC 스트림:
스트림 1: 패킷 A ✓, 패킷 B ✓
스트림 2: 패킷 C ✗ (손실)
스트림 3: 패킷 D ✓, 패킷 E ✓

→ 스트림 2의 패킷 C 재전송을 기다리는 동안
  스트림 1과 스트림 3은 계속 진행!

연결 마이그레이션 (Connection Migration)

TCP는 IP 주소와 포트 기반으로 연결을 식별합니다. Wi-Fi에서 LTE로 전환되면 연결이 끊깁니다. QUIC는 Connection ID로 연결을 식별하므로 네트워크가 바뀌어도 연결이 유지됩니다.

TCP:  Wi-Fi 연결 → LTE 전환 → IP 변경 → 연결 끊김 → 재연결 필요
QUIC: Wi-Fi 연결 → LTE 전환 → IP 변경 → Connection ID로 연결 유지

세 버전 종합 비교

항목HTTP/1.1HTTP/2HTTP/3
표준화 연도199720152022
전송 프로토콜TCPTCPUDP (QUIC)
데이터 형식텍스트바이너리바이너리
멀티플렉싱없음있음 (TCP HOL 남음)있음 (완전 해결)
헤더 압축없음HPACKQPACK
서버 푸시없음있음없음 (제거됨)
TLS선택선택 (실질적 필수)내장 필수
연결 수립3.5 RTT2.5 RTT0-1 RTT
연결 마이그레이션없음없음있음
브라우저 지원전체전체약 95%

실무에서의 HTTP 버전 확인

// Next.js / Node.js에서 HTTP 버전 확인
// HTTP/2는 next.js 자동 지원 (HTTPS 환경에서)

// 브라우저 Network 탭 → Protocol 컬럼
// h1: HTTP/1.1
// h2: HTTP/2
// h3: HTTP/3

// curl로 확인
// curl -I --http2 https://example.com
// curl --http3 https://example.com

nginx에서 HTTP/2 활성화

server {
    listen 443 ssl http2;
    server_name example.com;

    ssl_certificate /etc/ssl/example.crt;
    ssl_certificate_key /etc/ssl/example.key;
    ssl_protocols TLSv1.2 TLSv1.3;
}

nginx에서 HTTP/3 활성화

server {
    listen 443 ssl;
    listen 443 quic reuseport;  # HTTP/3

    ssl_certificate /etc/ssl/example.crt;
    ssl_certificate_key /etc/ssl/example.key;

    add_header Alt-Svc 'h3=":443"; ma=86400';  # HTTP/3 광고
}

정리

HTTP/1.1은 텍스트 기반으로 간단하지만 HOL 블로킹과 헤더 오버헤드가 문제입니다. HTTP/2는 바이너리 멀티플렉싱과 헤더 압축으로 성능을 크게 향상시켰지만 TCP HOL 블로킹은 남았습니다. HTTP/3는 QUIC 프로토콜로 TCP의 한계를 근본적으로 해결하고, 불안정한 네트워크에서도 빠른 성능을 제공합니다.