본문으로 건너뛰기

안동민 개발노트

본문 시작

HTTP 기본 구조

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

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

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

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


요청과 응답 포맷

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

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

HTTP 메시지는 시작 줄, 헤더, 빈 줄, 본문으로 읽는다

HTTP/2와 HTTP/3는 바이너리 프레임을 쓰지만 논리적 의미는 메서드, URI, 상태 코드, 헤더, 본문으로 유지된다.

  1. Request

    Start line GET /api/users HTTP/1.1 Headers Host, Accept, Authorization Blank line 헤더와 본문 경계 Body POST/PUT/PATCH에서 주로 사용

  2. 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 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)에 포함
  * 히스토리에 안 남음
  * 북마크 불가
  * 크기 제한 없음 (서버 설정에 따라)
  * 기본적으로 캐시 활용이 어렵지만, 명시적 캐시 조건을 둘 수 있음
  * 뒤로 가기 시 "다시 제출?" 확인

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


멱등성과 안전성

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

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

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

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

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

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

안전성과 멱등성은 서버 상태 변화 기준으로 구분한다

안전성은 상태 변경을 요구하지 않는지, 멱등성은 같은 요청을 반복해도 의도한 효과가 같은지를 본다.

  1. GET 예 조회 의미이며 반복해도 리소스 변경

    요구하지 않는다.

  2. POST 아니오 생성/처리 요청

    반복 시 중복 효과가 생길 수 있다.

  3. PUT 아니오 예 같

    표현으로 전체 대체하면 최종 상태가 같다.

  4. PATCH 아니오 설계별 증

    연산인지 값 지정인지에 따라 달라진다.

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.01996요청마다 새 연결비효율적
HTTP/1.11997Keep-Alive (연결 재사용)파이프라이닝 지원, 실무 채택 제한
HTTP/22015멀티플렉싱 (1연결, 병렬 전송)바이너리, 헤더 압축, 서버 푸시(효용 제한)
HTTP/32022QUIC (UDP 기반)스트림 독립성, TLS 1.3, 0-RTT
HTTP 의미는 유지되고 전송 방식이 바뀌었다

메서드, 상태 코드, 헤더, 콘텐츠 의미는 유지된다. 버전 차이는 연결을 어떻게 쓰고 손실을 어디까지 전파하는지에서 갈린다.

  1. Semantics

    메서드와 상태 코드 의미는 버전이 바뀌어도 같다.

  2. Mapping

    같은 HTTP 의미를 텍스트, 프레임, QUIC 스트림으로 매핑한다.

  3. Fallback

    HTTP/3은 빠르지만 네트워크 정책상 HTTP/2와 함께 운영될 수 있다.

버전전송 모델좋아진 점남은 병목
HTTP/1.1텍스트 메시지, 연결 재사용단순하고 널리 호환됨요청 줄서기와 연결 수 제한
HTTP/2바이너리 프레임, 스트림 멀티플렉싱한 연결에서 여러 요청 병렬화TCP 손실은 연결 전체에 영향
HTTP/3QUIC 위 스트림스트림별 손실 복구, 빠른 재연결UDP 443 차단과 폴백 고려

HTTP/3는 TCP 연결 단위의 HOL Blocking을 QUIC 스트림 구조로 크게 완화합니다.

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

HTTP/3는 TCP 연결 단위 HOL을 QUIC 스트림으로 줄인다

HTTP/2도 요청은 다중화하지만 TCP 패킷 손실은 연결 전체를 지연시킬 수 있다.

  1. HTTP/2 over TCP

    다중화 여러 HTTP stream을 한 TCP 연결에 싣는다. 손실 TCP는 순서 있는 바이트 스트림이라 손실 패킷 뒤 데이터가 기다린다.

  2. HTTP/3 over QUIC

    다중화 QUIC stream이 전송 계층에서 분리된다. 주의 같은 stream 내부 순서 보장은 여전히 필요하다.

HTTP 기본 구조는 요청 라인, 헤더, 본문, 응답 상태 기준으로 점검합니다.

HTTP 설계는 메서드, 상태, 헤더, 캐시를 함께 맞춘다

HTTP는 요청 메서드와 상태 코드만 외우는 것이 아니다. 안전성, 멱등성, 본문 형식, 캐시 가능성을 한 계약으로 맞춰야 한다.

  1. 요청

    method, path, request header, body가 의도와 자격을 보낸다.

  2. 응답

    status, response header, body가 결과와 표현 형식을 돌려준다.

  3. 운영

    proxy, CDN, observability가 캐시와 장애 판단에 영향을 준다.

결정봐야 할 기준대표 선택
메서드조회, 생성, 전체 교체, 부분 변경GET / POST / PUT / PATCH
상태 코드성공, 클라이언트 오류, 서버 오류, 재시도 여부200, 201, 204, 4xx, 5xx
헤더인증, 본문 형식, 조건부 요청, 캐시 정책Authorization, Content-Type, If-Match, Cache-Control
관측지연, upstream, request id로그와 응답 헤더를 연결

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