안동민 개발노트

본문 시작

HTTP 기본 구조

HTTP 요청·응답 메시지와 메서드의 의미·안전성·멱등성을 익히고 HTTP 버전별 전송 방식의 차이를 이해합니다.

DNS가 도메인 이름을 IP 주소로 변환해 주었으니, 이제 실제로 서버와 데이터를 주고받을 차례입니다.

웹에서 이 통신을 담당하는 프로토콜이 HTTP(Hypertext Transfer Protocol)입니다.

웹 개발자가 매일 사용하는 프로토콜이지만, GET과 POST의 차이가 뭔가요?를 넘어서 HTTP의 구조를 정확히 이해하면, API 설계, 성능 최적화, 보안 설정에서 훨씬 나은 판단을 내릴 수 있습니다.


요청과 응답 포맷

HTTP는 요청-응답(Request-Response) 패턴으로 동작합니다.

클라이언트가 요청을 보내면 서버가 응답을 돌려보냅니다.

HTTP/1.1 요청 형식 예
POST /api/users HTTP/1.1
Host: example.com
Content-Type: application/json
Content-Length: 2

{}
HTTP/1.1 응답 형식 예
HTTP/1.1 201 Created
Location: /api/users/1
Content-Type: application/json
Content-Length: 2

{}

위 메시지는 빈 JSON 객체 2바이트를 사용하는 형식 예시입니다. 실행 응답이 아니며, 줄 끝은 실제 HTTP/1.1 전송에서 CRLF를 사용합니다.

HTTP/1.1의 시작 줄과 헤더는 텍스트 형식이고, 본문에는 이미지 같은 바이너리도 올 수 있습니다. 시작 줄 뒤의 헤더 목록은 빈 줄로 끝납니다.

다만 HTTPS라면 TLS로 암호화되므로 패킷 캡처에서 본문을 그대로 읽을 수 없습니다.

HTTP/2와 HTTP/3는 바이너리 프레이밍을 사용하지만, 메서드·URI·상태 코드·헤더·본문이라는 논리적 의미는 HTTP Semantics로 유지됩니다.


HTTP 메서드

HTTP 메서드는 클라이언트가 서버에 어떤 동작을 원하는지 표현합니다.

메서드의 의도와 안전성·멱등성

메서드의 의도와 안전성·멱등성의 비교 기준과 해석 범위입니다.

메서드의 의도와 안전성·멱등성
메서드요청 의미와 본문안전 / 멱등
GET조회; 페이지 로드, API 데이터 조회. 보통 없음예 / 예
POST처리/생성; 회원가입, 게시글 작성, 파일 업로드. 있음아니오 / 아니오
PUT전체 대체; 프로필 전체 수정. 있음아니오 / 예
PATCH부분 수정; 이메일만 변경. 있음아니오 / 설계에 따라
DELETE삭제; 계정 삭제, 게시글 삭제. 보통 없음아니오 / 예
OPTIONS메서드 확인; CORS 프리플라이트. 보통 없음예 / 예
HEAD헤더만 조회; 리소스 존재 확인, 크기 확인. 응답 본문 없음예 / 예
GET
요청 의미와 본문: 조회; 페이지 로드, API 데이터 조회. 보통 없음
안전 / 멱등: 예 / 예
POST
요청 의미와 본문: 처리/생성; 회원가입, 게시글 작성, 파일 업로드. 있음
안전 / 멱등: 아니오 / 아니오
PUT
요청 의미와 본문: 전체 대체; 프로필 전체 수정. 있음
안전 / 멱등: 아니오 / 예
PATCH
요청 의미와 본문: 부분 수정; 이메일만 변경. 있음
안전 / 멱등: 아니오 / 설계에 따라
DELETE
요청 의미와 본문: 삭제; 계정 삭제, 게시글 삭제. 보통 없음
안전 / 멱등: 아니오 / 예
OPTIONS
요청 의미와 본문: 메서드 확인; CORS 프리플라이트. 보통 없음
안전 / 멱등: 예 / 예
HEAD
요청 의미와 본문: 헤더만 조회; 리소스 존재 확인, 크기 확인. 응답 본문 없음
안전 / 멱등: 예 / 예

예/아니오는 메서드가 정의한 의도에 대한 분류입니다. GET의 부수적 로깅이나 반복 요청의 응답 코드 차이까지 없다는 뜻은 아닙니다.

GET vs POST 상세 비교
GET /search?q=network&page=1 HTTP/1.1
  * 데이터를 URL 쿼리스트링에 포함
  * 브라우저 히스토리에 남음
  * 북마크 가능
  * 실무상 브라우저/서버/프록시별 URL 길이 제한에 영향
  * 캐시 가능
  * 뒤로 가기 시 캐시·이력 복원 정책에 따라 재요청할 수 있음

POST /api/users HTTP/1.1
Content-Type: application/json
{"name": "홍길동"}
  * 데이터를 본문(Body)에 포함
  * URL과 달리 POST 본문은 주소 표시줄에 나타나지 않음
  * 북마크 불가
  * 본문 크기는 서버·프록시·애플리케이션의 제한을 받음
  * 기본적으로 캐시 활용이 어렵지만, 명시적 캐시 조건을 둘 수 있음
  * 뒤로 가기에서 재전송이 필요하면 재제출 확인이 나타날 수 있음

GET 요청에도 메시지 본문 자체를 붙이는 것이 문법적으로 완전히 불가능한 것은 아니지만, 표준 의미가 일반적으로 정의되어 있지 않아 실무에서는 쓰지 않는 편이 안전합니다.


멱등성과 안전성

HTTP 메서드를 분류하는 두 가지 중요한 속성이 있습니다.

안전성(Safety): 클라이언트가 요청한 의미가 서버 상태 변경을 요구하지 않는 메서드입니다.

GET, HEAD, OPTIONS가 안전합니다.

서버가 로그를 남기거나 통계를 갱신하는 부수 효과까지 모두 금지한다는 뜻은 아닙니다.

멱등성(Idempotency): 같은 요청을 한 번 보내든 여러 번 보내든 서버에 남는 의도한 효과가 동일한 메서드입니다.

응답 코드나 응답 본문이 매번 완전히 같아야 한다는 뜻은 아닙니다.

http_methods.py
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 스트림 구조로 크게 완화합니다.

다만 같은 스트림 내부에서는 순서 있는 전달이 필요하므로, 손실의 영향이 완전히 사라지는 것은 아닙니다.

다음 절에서는 서버가 응답할 때 사용하는 상태 코드와 요청/응답에 포함되는 헤더를 살펴보겠습니다.