HTTP 기본 구조
HTTP 요청·응답 메시지와 메서드의 의미·안전성·멱등성을 익히고 HTTP 버전별 전송 방식의 차이를 이해합니다.
DNS가 도메인 이름을 IP 주소로 변환해 주었으니, 이제 실제로 서버와 데이터를 주고받을 차례입니다.
웹에서 이 통신을 담당하는 프로토콜이 HTTP(Hypertext Transfer Protocol)입니다.
웹 개발자가 매일 사용하는 프로토콜이지만, GET과 POST의 차이가 뭔가요?를 넘어서 HTTP의 구조를 정확히 이해하면, API 설계, 성능 최적화, 보안 설정에서 훨씬 나은 판단을 내릴 수 있습니다.
요청과 응답 포맷
HTTP는 요청-응답(Request-Response) 패턴으로 동작합니다.
클라이언트가 요청을 보내면 서버가 응답을 돌려보냅니다.
HTTP/2와 HTTP/3는 바이너리 프레임을 쓰지만 논리적 의미는 메서드, URI, 상태 코드, 헤더, 본문으로 유지된다.
- Request
Start line GET /api/users HTTP/1.1 Headers Host, Accept, Authorization Blank line 헤더와 본문 경계 Body POST/PUT/PATCH에서 주로 사용
- Response
Status line HTTP/1.1 200 OK Headers Content-Type, Cache-Control, Set-Cookie Blank line 메타데이터와 본문 경계 Body HTML, JSON, 이미지 등 표현 데이터
HTTP/1.1 메시지는 텍스트 기반으로 표현됩니다.
다만 HTTPS라면 TLS로 암호화되므로 패킷 캡처에서 본문을 그대로 읽을 수 없습니다.
HTTP/2와 HTTP/3는 바이너리 프레이밍을 사용하지만, 메서드·URI·상태 코드·헤더·본문이라는 논리적 의미는 HTTP Semantics로 유지됩니다.
HTTP 메서드
HTTP 메서드는 클라이언트가 서버에 어떤 동작을 원하는지 표현합니다.
| 메서드 | 용도 | 본문 | 멱등 | 안전 | 사용 예 |
|---|---|---|---|---|---|
| GET | 조회 | 보통 없음 | ✓ | ✓ | 페이지 로드, API 데이터 조회 |
| POST | 처리/생성 | 있음 | ✗ | ✗ | 회원가입, 게시글 작성, 파일 업로드 |
| PUT | 전체 대체 | 있음 | ✓ | ✗ | 프로필 전체 수정 |
| PATCH | 부분 수정 | 있음 | 설계에 따라 | ✗ | 이메일만 변경 |
| DELETE | 삭제 | 보통 없음 | ✓ | ✗ | 계정 삭제, 게시글 삭제 |
| OPTIONS | 메서드 확인 | 보통 없음 | ✓ | ✓ | CORS 프리플라이트 |
| HEAD | 헤더만 조회 | 응답 본문 없음 | ✓ | ✓ | 리소스 존재 확인, 크기 확인 |
GET /search?q=network&page=1 HTTP/1.1
* 데이터를 URL 쿼리스트링에 포함
* 브라우저 히스토리에 남음
* 북마크 가능
* 실무상 브라우저/서버/프록시별 URL 길이 제한에 영향
* 캐시 가능
* 브라우저 뒤로 가기 시 재요청 없음
POST /api/users HTTP/1.1
Content-Type: application/json
{"name": "홍길동"}
* 데이터를 본문(Body)에 포함
* 히스토리에 안 남음
* 북마크 불가
* 크기 제한 없음 (서버 설정에 따라)
* 기본적으로 캐시 활용이 어렵지만, 명시적 캐시 조건을 둘 수 있음
* 뒤로 가기 시 "다시 제출?" 확인GET 요청에도 메시지 본문 자체를 붙이는 것이 문법적으로 완전히 불가능한 것은 아니지만, 표준 의미가 일반적으로 정의되어 있지 않아 실무에서는 쓰지 않는 편이 안전합니다.
멱등성과 안전성
HTTP 메서드를 분류하는 두 가지 중요한 속성이 있습니다.
안전성(Safety): 클라이언트가 요청한 의미가 서버 상태 변경을 요구하지 않는 메서드입니다.
GET, HEAD, OPTIONS가 안전합니다.
서버가 로그를 남기거나 통계를 갱신하는 부수 효과까지 모두 금지한다는 뜻은 아닙니다.
멱등성(Idempotency): 같은 요청을 한 번 보내든 여러 번 보내든 서버에 남는 의도한 효과가 동일한 메서드입니다.
응답 코드나 응답 본문이 매번 완전히 같아야 한다는 뜻은 아닙니다.
안전성은 상태 변경을 요구하지 않는지, 멱등성은 같은 요청을 반복해도 의도한 효과가 같은지를 본다.
- GET 예 조회 의미이며 반복해도 리소스 변경
요구하지 않는다.
- POST 아니오 생성/처리 요청
반복 시 중복 효과가 생길 수 있다.
- PUT 아니오 예 같
표현으로 전체 대체하면 최종 상태가 같다.
- PATCH 아니오 설계별 증
연산인지 값 지정인지에 따라 달라진다.
import json
from http.client import HTTPSConnection
def http_request(method, host, path, body=None):
"""다양한 HTTP 메서드로 요청 전송"""
conn = HTTPSConnection(host)
headers = {
"Content-Type": "application/json",
"Accept": "application/json",
}
json_body = json.dumps(body) if body else None
conn.request(method, path, body=json_body, headers=headers)
response = conn.getresponse()
data = response.read().decode()
print(f"{method} {path}")
print(f" Status: {response.status} {response.reason}")
print(f" Content-Type: {response.getheader('Content-Type')}")
if data and len(data) < 200:
print(f" Body: {data}")
print()
conn.close()
return response.status, data
# 사용 예시 (httpbin.org는 HTTP 테스트 서비스)
# http_request("GET", "httpbin.org", "/get")
# http_request("POST", "httpbin.org", "/post", {"name": "test"})
# http_request("PUT", "httpbin.org", "/put", {"name": "updated"})
# http_request("DELETE", "httpbin.org", "/delete")HTTP 버전별 차이
| 버전 | 연도 | 연결 방식 | 특징 |
|---|---|---|---|
| HTTP/1.0 | 1996 | 요청마다 새 연결 | 비효율적 |
| HTTP/1.1 | 1997 | Keep-Alive (연결 재사용) | 파이프라이닝 지원, 실무 채택 제한 |
| HTTP/2 | 2015 | 멀티플렉싱 (1연결, 병렬 전송) | 바이너리, 헤더 압축, 서버 푸시(효용 제한) |
| HTTP/3 | 2022 | QUIC (UDP 기반) | 스트림 독립성, TLS 1.3, 0-RTT |
HTTP/3는 TCP 연결 단위의 HOL Blocking을 QUIC 스트림 구조로 크게 완화합니다.
다만 같은 스트림 내부에서는 순서 있는 전달이 필요하므로, 손실의 영향이 완전히 사라지는 것은 아닙니다.
HTTP/2도 요청은 다중화하지만 TCP 패킷 손실은 연결 전체를 지연시킬 수 있다.
- HTTP/2 over TCP
다중화 여러 HTTP stream을 한 TCP 연결에 싣는다. 손실 TCP는 순서 있는 바이트 스트림이라 손실 패킷 뒤 데이터가 기다린다.
- HTTP/3 over QUIC
다중화 QUIC stream이 전송 계층에서 분리된다. 주의 같은 stream 내부 순서 보장은 여전히 필요하다.
HTTP 기본 구조는 요청 라인, 헤더, 본문, 응답 상태 기준으로 점검합니다.
HTTP는 요청 메서드와 상태 코드만 외우는 것이 아니다. 안전성, 멱등성, 본문 형식, 캐시 가능성을 한 계약으로 맞춰야 한다.
- 요청
method, path, request header, body가 의도와 자격을 보낸다.
- 응답
status, response header, body가 결과와 표현 형식을 돌려준다.
- 운영
proxy, CDN, observability가 캐시와 장애 판단에 영향을 준다.
| 결정 | 봐야 할 기준 | 대표 선택 |
|---|---|---|
| 메서드 | 조회, 생성, 전체 교체, 부분 변경 | GET / POST / PUT / PATCH |
| 상태 코드 | 성공, 클라이언트 오류, 서버 오류, 재시도 여부 | 200, 201, 204, 4xx, 5xx |
| 헤더 | 인증, 본문 형식, 조건부 요청, 캐시 정책 | Authorization, Content-Type, If-Match, Cache-Control |
| 관측 | 지연, upstream, request id | 로그와 응답 헤더를 연결 |
다음 절에서는 서버가 응답할 때 사용하는 상태 코드와 요청/응답에 포함되는 헤더를 살펴보겠습니다.