금일 주제는 백엔드 개발자라면 기본적으로 잘 알고 있어야하는 HTTP입니다. 평소엔 잘 알고 있다고 생각했지만, 막상 HTTP에 관한 질문을 만나면 답변이 잘 안 나왔던 거 같습니다. 오늘 HTTP에 대해 좀 더 다져보겠습니다.
HTTP(HyperText Transfer Protocol)는 클라이언트와 서버가 데이터를 주고받기 위한 약속이다.
인터넷이 생기기 전, 컴퓨터끼리 통신하려면 서로 어떤 형식으로 보낼 것인지를 미리 맞춰야 했다. 매번 각자 형식을 정하면 혼돈이 와서, 팀 버너스 리가 1991년에 "우리 이 형식으로 통일하자"고 만든 것이 HTTP이다.
HTTP가 해결하는 핵심 문제
[브라우저] ──── TCP 연결 ────► [서버]
──── HTTP 요청 ───►
◄─── HTTP 응답 ────
HTTP는 그 자체로 전송하지 않는다. TCP라는 더 낮은 계층 위에 올라탄다. TCP가 데이터를 안전하게, 순서대로 전달해주는 역할을 하고, HTTP는 그 위에서 무엇을 요청하고 응답할지 형식만 정한다.
HTTP는 사실 그냥 텍스트 모음이다.
요청
GET /users/1 HTTP/1.1 ← 요청 라인 (메서드 + 경로 + 버전)
Host: api.example.com ← 헤더 시작
Accept: application/json
Authorization: Bearer eyJhbGc...
← 빈 줄 (헤더 끝을 알림)
← 바디 (GET은 보통 없음)
응답
HTTP/1.1 200 OK ← 상태 라인
Content-Type: application/json
Content-Length: 43
← 빈 줄
{"id": 1, "name": "홍길동"} ← 바디
| 버전 | 연결 방식 | 핵심 문제 | 해결책 |
|---|---|---|---|
| HTTP/1.0 | 요청마다 TCP 새로 연결 | 매번 3-Way handshake = 느림 | - |
| HTTP/1.1 | Keep-Alive(연결 재사용) | HOL Blocking 발생 | 파이프라이닝 도입했지만 실패 |
| HTTP/2 | 하나의 연결에 다중 스트림 | 바이너리 프레이밍, 헤더 압축 | 멀티플렉싱 |
| HTTP/3 | UDP 기반 QUIC | TCP의 근본적 HOL 해결 | 연결 자체 혁신 |
HOL blocking이란?
HTTP/1.1에서 파이프라이닝을 쓰면 요청을 여러 개 보낼 수 있지만, 응답은 반드시 순서대로 와야 한다. 첫 번째 응답이 느리면 뒤 응답들이 다 막힌다.
HTTP/2는 이 문제를 스트림으로 해결한다. 하나의 TCP 연결 위에 독립적인 채널 여러 개를 논리적으로 만들어서, 서로 블로킹하지 않고 동시에 주고받는다.
메서드는 두 가지 속성으로 이해해야 한다.
멱등성: 같은 요청을 N번 해도 결과가 같다.
안정성: 서버 상태를 변경하지 않는다.
| 메서드 | 멱등성 | 안정성 | 용도 |
|---|---|---|---|
| GET | ✅ | ✅ | 조회 |
| HEAD | ✅ | ✅ | 헤더만 조회 |
| PUT | ✅ | ❌ | 전체 교체 |
| DELETE | ✅ | ❌ | 삭제 |
| POST | ❌ | ❌ | 생성/처리 |
| PATCH | ❌ | ❌ | 부분 수정 |
1xx — 정보 (처리 중)
2xx — 성공
3xx — 리다이렉션 (다른 곳으로 가라)
4xx — 클라이언트 잘못 (네 요청이 문제야)
5xx — 서버 잘못 (내가 문제야)
단순히 TCP 위에 정의하는 텍스트 모음이라고 접근하니까 좀 더 쉽다는 생각이 들었습니다. 너무 어렵게 생각하지 않고, TCP라는 터널을 뚫고, 그 위에 텍스트들을 이동시킨다라는 생각으로 접근하면 좀 더 가까이 다가갈 수 있다고 생각듭니다.
오늘도 기본기에 한 걸음 더 나아갑니다.