네트워크 용어 사전
HTTP상태 코드 · 멱등성 · 쿠키 · HTTP/2 · HTTP/3

HTTP

요청과 응답 한 쌍으로 도는 무상태 프로토콜. 버전 진화는 head-of-line 블로킹과의 싸움이었다.

웹의 대화 규약. 메서드 + URL + 헤더 + 본문의 요청과 상태 코드 + 헤더 + 본문의 응답 한 쌍이 전부다.

GET /users/1 HTTP/1.1
Host: api.shop.com
Accept: application/json

HTTP/1.1 200 OK
Content-Type: application/json
{ "id": 1 }

메서드에는 의미상의 약속이 있다

  • 안전(safe) — 서버 상태를 바꾸지 않는다 GET · HEAD · OPTIONS

  • 멱등(idempotent) 여러 번 보내도 결과가 같다 — GET · PUT · DELETE · HEAD

  • POST 는 둘 다 아니다 → 두 번 보내면 자원이 둘 생길 수 있다

    • 재시도가 잦은 환경에서는 멱등 키 같은 보완이 필요하다

상태 코드

  • 2xx 성공 — 200 OK · 201 Created · 204 No Content
  • 3xx 리다이렉트 — 301 영구 · 302 임시 · 304 Not Modified(캐시 유효)
  • 4xx 클라이언트 — 400 잘못된 요청 · 401 미인증 · 403 권한 없음 · 404 없음 · 429 과다 요청
  • 5xx 서버 — 500 내부 오류 · 502 게이트웨이 오류 · 503 일시 불가 · 504 게이트웨이 타임아웃

401과 403의 구분이 자주 틀린다 — 401은 "누구인지 모른다", 403은 "누구인지는 아는데 권한이 없다"다.

무상태 — 그래서 쿠키

HTTP 는 각 요청이 서로를 모른다

  • 어느 서버가 받아도 되므로 확장에 유리하다
  • 대신 로그인 같은 연속성은 따로 얹어야 한다

Set-Cookie 로 식별자를 심으면 브라우저가 이후 요청마다 자동으로 실어 보낸다

  • 이 '자동 전송' 성질이 CSRF 공격이 노리는 지점이다

버전 진화 = HoL 블로킹과의 싸움

  • HTTP/1.1 — 한 연결에서 요청을 한 줄로 처리한다

    • 앞 요청이 느리면 뒤가 다 막힌다 (응용 계층 HoL)
    • 브라우저는 연결을 6개쯤 열어 우회했다
  • HTTP/2 — 바이너리 프레이밍 + 한 연결에 여러 스트림 멀티플렉싱

    • 응용 계층 HoL 해소. 헤더 압축(HPACK)도 추가
    • 그러나 TCP 가 한 패킷을 잃으면 모든 스트림이 함께 막힌다 (전송 계층 HoL)
  • HTTP/3 — 전송을 QUIC(UDP 위)으로 바꿨다

    • 스트림이 진짜 독립적이라 한 스트림의 손실이 다른 걸 안 막는다
    • TLS 1.3 통합으로 연결 수립이 빠르다 (0-RTT)

서버가 먼저 말하려면

폴링주기적으로 되묻는다트래픽↔지연 맞바꿈
롱 폴링응답을 붙잡고 기다린다이벤트마다 연결이 끝난다
SSE응답을 끝내지 않는다단방향 · 자동 재연결이 규격에 있다
WebSocket101 로 프로토콜을 바꾼다양방향 · 재연결은 직접 구현

캐시 헤더

Cache-Control: max-age=3600, public 얼마나 캐시할까

  • ETag / If-None-Match — 안 바뀌었으면 304 로 본문을 생략 Last-Modified / If-Modified-Since 시각 기반 조건부 요청

면접 함정

  • "HTTP/2면 연결을 여러 개 열 필요가 없어 항상 빠르다" → 손실이 있는 회선에서는 TCP HoL 때문에 오히려 1.1의 다중 연결이 나을 수 있다.
  • "POST는 캐시되지 않는다" → 조건이 맞으면 캐시할 수 있다. 실무에서 드물 뿐이다.

헤더로 성능을 조율한다

curl -I -H "Accept-Encoding: gzip, br" https://example.com
# content-encoding: br              압축
# cache-control: max-age=31536000   캐시 기간
# etag: "a1b2c3"                    조건부 요청용 지문
# vary: Accept-Encoding             이 헤더가 다르면 다른 캐시 항목

Vary를 빠뜨리면 압축된 응답을 압축을 못 받는 클라이언트에게 주는 사고가 난다.

조건부 요청

  • 클라이언트 — If-None-Match: "a1b2c3"

  • 서버 — 304 Not Modified (본문 없음)

  • 본문 전송이 통째로 생략된다. 대역폭을 크게 아낀다

버전 확인

curl -sI --http2 https://example.com | head -1     # HTTP/2 200
curl -sI --http3 https://example.com | head -1     # HTTP/3 200 (지원 시)

실무에서 자주 만나는 상태 코드

  • 502 Bad Gateway — 프록시가 업스트림에서 잘못된 응답을 받았다 (앱이 죽었다)
  • 503 Service Unavailable 일시적 과부하·점검 (Retry-After 를 함께 준다)
  • 504 Gateway Timeout — 업스트림이 제때 응답하지 않았다 (앱이 느리다)

502 와 504 의 구분이 장애 원인을 가른다 — 죽었나 느린가

함께 보면 좋은 용어

노트에서 맥락과 함께 보기 — HTTP — 요청/응답·메서드·1.1/2/3·HoL