HTTP와 HTTPS — 웹을 움직이는 프로토콜

Tim Berners-Lee가 1991년 발명한 HTTP가 어떻게 진화해 HTTP/3까지 왔는지, 그리고 HTTPS가 왜 필요하고 TLS 핸드셰이크가 어떻게 동작하는지 설명한다.

Seobway · · 15분

웹을 발명하다 — HTTP의 탄생

1989년 CERN의 Tim Berners-Lee는 상사에게 제안서를 제출했다.
제목은 "Information Management: A Proposal".
상사는 여백에 "Vague but exciting(모호하지만 흥미롭다)"이라고 적었다.

그 제안이 월드와이드웹(World Wide Web)이 됐고,
그 위에서 문서를 전달하기 위해 만든 프로토콜이 HTTP(HyperText Transfer Protocol)다.[1]

1991년 8월 6일, Berners-Lee는 alt.hypertext 뉴스그룹에 첫 웹 서버를 공개했다.
이날이 웹의 공개 탄생일이다.

HTTP의 진화 — 버전별 역사

%% desc: HTTP 버전 진화 타임라인과 각 버전의 핵심 혁신
flowchart LR
  H09["HTTP/0.9\n1991\n단순 GET"]
  H10["HTTP/1.0\n1996\nRFC 1945\n헤더·상태코드"]
  H11["HTTP/1.1\n1997/1999\nRFC 2616\n지속 연결"]
  H2["HTTP/2\n2015\nRFC 7540\n멀티플렉싱"]
  H3["HTTP/3\n2022\nRFC 9114\nQUIC/UDP"]

  H09 --> H10 --> H11 --> H2 --> H3

HTTP/0.9 (1991) — 단 한 줄

최초의 HTTP는 놀랍도록 단순했다.
요청은 딱 한 줄: GET /index.html
응답은 HTML 본문만. 상태 코드도, 헤더도, 버전 번호도 없었다.

HTTP/1.0 — RFC 1945 (1996)

공식 표준이 아닌 정보 RFC로, 이미 현장에서 사용되던 관행을 문서화한 것이다.

도입된 것:

문제: 요청마다 새 TCP 연결을 열었다.
이미지 20개가 있는 페이지를 열면 21번의 TCP 핸드셰이크가 필요했다.

HTTP/1.1 — RFC 2616 (1999) / RFC 7230~7235 (2014)

HTTP의 첫 공식 인터넷 표준. 15년 이상 인터넷의 주력 프로토콜이었다.

핵심 개선:

%% desc: HTTP/1.0의 연결당 요청 vs HTTP/1.1의 지속 연결 비교
flowchart LR
  subgraph HTTP10["HTTP/1.0 — 매번 새 연결"]
    direction TB
    C1[TCP 연결] --> R1[GET index.html] --> X1[연결 종료]
    C2[TCP 연결] --> R2[GET style.css] --> X2[연결 종료]
    C3[TCP 연결] --> R3[GET image.png] --> X3[연결 종료]
  end

  subgraph HTTP11["HTTP/1.1 — 지속 연결"]
    direction TB
    CC[TCP 연결 1회] --> RR1[GET index.html]
    RR1 --> RR2[GET style.css]
    RR2 --> RR3[GET image.png]
    RR3 --> XX[연결 재사용 or 종료]
  end

HTTP/2 — RFC 7540 (2015)

Google의 내부 프로토콜 SPDY(2009)에서 영감을 받아 표준화됐다.
HTTP의 의미(메서드, 상태 코드, 헤더)는 그대로 유지하면서 전송 방식을 완전히 바꿨다.

바이너리 프레이밍(Binary Framing)
텍스트 기반이던 HTTP를 이진 프레임 구조로 변환한다.

멀티플렉싱(Multiplexing)
하나의 TCP 연결에서 여러 스트림(Stream)이 동시에 동작한다.
각 스트림은 고유한 스트림 ID를 가지며 독립적으로 처리된다.

%% desc: HTTP/2 멀티플렉싱 — 하나의 TCP 연결로 여러 요청/응답이 동시에 교환되는 구조
sequenceDiagram
  participant C as 클라이언트
  participant S as 서버

  Note over C,S: 하나의 TCP 연결

  C->>S: HEADERS [Stream 1] GET /index.html
  C->>S: HEADERS [Stream 3] GET /style.css
  C->>S: HEADERS [Stream 5] GET /script.js

  S-->>C: HEADERS [Stream 1] 200 OK
  S-->>C: DATA [Stream 3] style.css 본문
  S-->>C: DATA [Stream 1] index.html 본문
  S-->>C: HEADERS [Stream 5] 200 OK
  S-->>C: DATA [Stream 5] script.js 본문

HPACK 헤더 압축 (RFC 7541)
반복되는 헤더(User-Agent, Accept, Cookie 등)를 정적/동적 테이블로 압축한다.
헤더 크기를 약 76% 감소시킨다.

서버 푸시(Server Push)
클라이언트가 요청하기 전에 서버가 PUSH_PROMISE 프레임으로 리소스를 미리 전송한다.

한계: TCP 레벨의 헤드-오브-라인(HOL) 블로킹은 여전히 존재.
TCP 패킷 하나가 손실되면 그 연결의 모든 스트림이 대기한다.

HTTP/3 — RFC 9114 (2022)

TCP HOL 블로킹을 근본적으로 해결하기 위해 TCP를 버리고 QUIC(RFC 9000) 위에서 동작한다.
QUIC은 UDP 기반이지만 신뢰성·순서·혼잡 제어를 user space에서 구현한다.[2]

HTTP/1.1 HTTP/2 HTTP/3
전송 프로토콜 TCP TCP QUIC (UDP)
연결 수 도메인당 6~8개 1개 1개
헤더 압축 없음 HPACK QPACK
HOL 블로킹 있음 (요청) 있음 (TCP) 없음
연결 설정 1 RTT (TCP) + 1~2 RTT (TLS) 동일 0~1 RTT
연결 이동성 불가 불가 Connection ID로 가능

HTTPS — 왜 암호화가 필요한가

HTTP는 모든 데이터를 평문(Plaintext)으로 전송한다.
중간에서 패킷을 가로채면 로그인 정보, 카드 번호, 개인 정보가 그대로 노출된다.

이를 해결하기 위해 Netscape가 1994년 SSL(Secure Sockets Layer)을 개발했다.
이후 IETF가 SSL을 계승해 TLS(Transport Layer Security)로 표준화했다.[3]

HTTPS = HTTP + TLS

TLS는 세 가지를 보장한다.

보장 의미
기밀성(Confidentiality) 데이터를 암호화해 도청자가 내용을 알 수 없다
무결성(Integrity) 전송 중 데이터가 변조되면 즉시 탐지한다
인증(Authentication) 서버가 진짜 해당 도메인의 서버임을 인증서로 증명한다

TLS 핸드셰이크 (TLS 1.2 기준)

%% desc: TLS 1.2 핸드셰이크 — 클라이언트와 서버가 세션 키를 협상하는 4단계 과정
sequenceDiagram
  participant C as 클라이언트 (브라우저)
  participant S as 서버

  C->>S: ClientHello (지원 TLS 버전, 암호 스위트 목록, 랜덤 값 A)
  S-->>C: ServerHello (선택된 암호 스위트, 랜덤 값 B)
  S-->>C: Certificate (서버 공개키 포함 인증서, CA 서명)
  Note over C: CA 서명 검증, 도메인 확인, 만료일 확인
  C->>S: Pre-master secret (서버 공개키로 암호화)
  Note over C,S: 양쪽 모두 (A + B + Pre-master)로 동일한 세션 키 생성
  C->>S: Finished (세션 키로 암호화된 검증 메시지)
  S-->>C: Finished (세션 키로 암호화된 검증 메시지)
  Note over C,S: 이후 모든 HTTP 데이터는 세션 키로 암호화

TLS 1.3 (RFC 8446, 2018)은 핸드셰이크를 1 RTT로 줄이고 (TLS 1.2는 2 RTT),
재방문 클라이언트는 0-RTT로 연결을 복원할 수 있다.
TLS 1.0·1.1은 RFC 8996(2021)으로 공식 폐기됐다.

인증서(Certificate) 체계

서버의 신원은 X.509 인증서로 증명된다.
인증서에는 도메인명, 공개키, 발급자(CA), 유효기간이 포함된다.
브라우저는 사전에 신뢰하는 CA 목록을 가지고 있으며, 그 CA가 서명한 인증서만 신뢰한다.

%% desc: 인증서 체인 — 루트 CA → 중간 CA → 서버 인증서의 신뢰 관계
flowchart TD
  ROOT[루트 CA<br/>브라우저가 사전 신뢰]
  INT[중간 CA<br/>루트 CA가 서명]
  CERT[서버 인증서<br/>example.com<br/>중간 CA가 서명]

  ROOT -->|서명| INT
  INT -->|서명| CERT

HTTP 메서드와 상태 코드

주요 메서드

메서드 의미 멱등성
GET 리소스 조회
POST 리소스 생성
PUT 리소스 전체 교체
PATCH 리소스 부분 수정
DELETE 리소스 삭제
HEAD GET과 동일하나 본문 없음
OPTIONS 지원 메서드 조회

주요 상태 코드

범위 의미 예시
2xx 성공 200 OK, 201 Created, 204 No Content
3xx 리다이렉션 301 Moved Permanently, 304 Not Modified
4xx 클라이언트 오류 400 Bad Request, 401 Unauthorized, 404 Not Found
5xx 서버 오류 500 Internal Server Error, 503 Service Unavailable

참고

  1. Hypertext Transfer Protocol, Wikipedia
  2. M. Bishop, "HTTP/3", RFC 9114, June 2022, IETF
  3. Transport Layer Security, Wikipedia

관련 글