본 내용은 "HTTP 완벽 가이드" 내용을 참고하여 기록한 정리본입니다.
게시할 내용
- 메시지는 어떻게 흘러가는가
- HTTP 메시지의 세 부분
- 시작줄
- 헤더
- 바디
- 요청과 응답 메시지의 차이
- 요청 메시지가 지원하는 여러 메소드들
- 응답 메시지가 반환하는 여러 상태 코드들
- HTTP 헤더들은 각각 무슨일을 하는가
메시지는 어떻게 흘러가는가
- 요청과 응답이라는 두 가지 형식으로 통신하며, 클라이언트-서버 간의 데이터를 교환한다.
- 메시지는 크게 시작줄, 헤더, 바디 세 부분으로 이루어져 있다.
- 요청 메시지와 응답 메시지는 기본 구조는 유사하지만, 시작줄에서 사용하는 구문이 다르다.
- 요청 메시지는
메소드
,URL
,버전
으로 시작한다. - 응답 메시지는
버전
,상태코드
,사유구절
로 시작한다.
- 요청 메시지는
HTTP 메시지의 세 부분
- 시작줄
- 요청 메시지:
메소드
URL
HTTP 버전
- 응답 메시지:
HTTP 버전
상태코드
사유구절
- 요청 메시지:
- 헤더
- 요청 헤더와 응답 헤더는 유사한 구조를 가지나, 포함된 항목이 달라진다.
- 바디
- 실제 데이터를 담는 부분으로, 요청 시 전송할 내용 또는 응답 시 반환할 내용이 들어간다.
요청과 응답 메시지의 차이
- 요청 메시지의 시작줄은 어떤 동작을 수행할지 결정하는 메소드와 URL을 포함한다.
- 응답 메시지의 시작줄에는 서버가 처리한 결과를 나타내는 상태코드와 사유구절이 포함된다.
요청 메시지가 지원하는 여러 메소드들
- GET, POST, HEAD, PUT, PATCH, TRACE, OPTIONS, DELETE 등이 있다.
- 각 메소드는 안전성, 멱등성, 캐시 가능 여부 등에 차이가 있으므로 용도에 맞게 사용해야 한다.
응답 메시지가 반환하는 여러 상태 코드들
- 1xx(정보), 2xx(성공), 3xx(리다이렉션), 4xx(클라이언트 오류), 5xx(서버 오류)와 같이 범주화된다.
- 세부 코드에 따라 의미가 달라지므로, 시나리오에 맞게 정확한 상태 코드를 설정하는 습관이 중요하다.
HTTP 헤더들은 각각 무슨 일을 하는가
- 일반 헤더, 요청 헤더, 응답 헤더, 표현 헤더 등으로 구분된다.
- 캐시 제어, 인증 정보, 언어 및 인코딩 정보, 쿠키, 서버 정보 등을 주고받기 위해 사용한다.
- 적절히 활용하면 네트워크 사용량 절감 및 보안, 성능 개선에 도움이 된다.
메시지의 흐름
인바운드(Inbound)
- 클라이언트에서 서버로 요청이 들어가는 흐름이다.
- 서버 입장에서는 “인바운드”로 요청을 받아 처리한다.
아웃바운드(Outbound)
- 서버에서 클라이언트로 응답이 나가는 흐름이다.
- 서버 입장에서는 “아웃바운드”로 결과를 전송한다.
업스트림(Upstream)
- 메시지를 송신하는 주체를 의미한다.
- 예를 들어, 클라이언트→서버로의 요청 흐름에서 업스트림은 클라이언트이다.
다운스트림(Downstream)
- 메시지를 수신하는 주체를 의미한다.
- 예를 들어, 클라이언트→서버로의 요청 흐름에서 다운스트림은 서버이다.
주의: 업스트림/다운스트림의 오해
- 업스트림/다운스트림은 요청/응답 개념이 아니다.
- 업스트림/다운스트림은 송신자/수신자 개념이다.
- 클라이언트-서버 모델 간, 어떨 때는 업스트림이 될 수 있고, 어떨 때는 다운스트림이 될 수 있다.
메시지의 구조
시작줄
요청
- 메소드
- GET, POST 등과 같이 서버가 수행해야 할 동작을 정의한다.
- URL
- 서버 자원의 위치를 표시한다.
- 버전
- 예:
HTTP/1.1
- 요청 메시지의 HTTP 버전 정보를 나타낸다.
- 예:
응답
- 버전
- 서버가 받을 수 있는 최대 버전을 기준으로 한다.
- 실제 메시지는 요청자의 버전에 맞춰서 응답을 내보낸다.
- 상태코드
- 클라이언트 요청 처리 결과를 숫자로 표현한다.
- 사유구절
- 숫자 상태코드를 사람이 알아볼 수 있도록 간단히 설명한 문구다.
- 클라이언트 측 로직에서 이 구절을 근거로 처리하면 안 된다. (예:
200 NOT OK
라도 200이면 성공)
헤더 블록
- 일반 헤더
- 캐시, 연결 유지 여부 등과 같이 전반적인 정보를 다룬다.
- 요청 헤더
- 클라이언트가 서버에게 전달하는 추가 정보들을 포함한다 (Host, User-Agent 등).
- 응답 헤더
- 서버가 클라이언트에게 전달하는 추가 정보들을 포함한다 (Server, Retry-After 등).
- 표현 헤더
- 실제 데이터(컨텐츠)의 형식, 인코딩, 길이 등을 설명한다.
- obs-folding
- 오래된 사양에서 사용하는 헤더 접기 방식. 최신 사양에서는 권장되지 않는다.
본문
- 요청 혹은 응답의 실제 데이터를 담는 영역이다.
CRLF
- 시작줄/헤더/본문을 구분하기 위한 개행 문자(
\r\n
)를 의미한다. - 명세상으로는 캐리지 리턴+라인 피드(Windows 개행 방식)를 포함해야 하지만, 유연성을 고려하여 다양한 개행 방식을 수용하기도 한다.
요청 메시지 구조
응답 메시지 구조
버전
- 서버가 받을 수 있는 최대 버전을 기준으로 동작하지만, 실제 메시지는 요청자의 버전에 맞춘다.
- 메이저 / 마이너 버전으로 구성되며, 예를 들어
HTTP/2.0
에서 2가 메이저, 0이 마이너에 해당한다. - 숫자가 하나의 정수로 판단되지 않고 독립적으로 비교되므로,
HTTP/2.22
는HTTP/2.3
보다 더 높은 버전이 된다. - 요청의 HTTP 버전과 응답의 HTTP 버전이 다를 수 있으므로 주의한다.
HTTP 메소드
안전한 메소드
- 서버 자원에 아무런 변화를 일으키지 않는 메소드를 의미한다.
- 여러 번 호출해도 서버 상태가 변하지 않는다.
- GET, HEAD가 해당된다.
GET
- 데이터 조회를 요청하는 메소드다.
- 멱등성을 보장해야 하며, 캐시가 가능하다.
POST
- 서버가 정의한 방식대로 데이터 처리를 요청하는 메소드다.
- 멱등성을 보장하지 않는다.
- 응답 결과를 캐시할 수 있으나, 본문까지 캐시 키로 고려해야 하므로 일반적으로 잘 사용되지 않는다.
HEAD
- GET과 유사하되, 헤더만 응답으로 받는다.
- 리소스를 실제로 가져오지 않고 존재 여부나 변경 여부를 확인하고자 할 때 유용하다.
- HTTP/1.1 준수를 위해 반드시 구현되어야 한다.
PUT
- 데이터 덮어쓰기를 요청하는 메소드다.
- 리소스 전체를 업데이트하며, 멱등성을 보장해야 한다.
- 클라이언트가 서버 내 파일의 정확한 위치를 알고 있어야 한다.
PATCH
- 데이터의 부분 업데이트를 요청한다.
- PUT과 달리 멱등성을 보장하지 않는다.
- 캐시가 가능하지만, 본문까지 캐시 키로 봐야 해서 일반적으로 잘 쓰이지 않는다.
TRACE
- 루프백(Loopback) 기능을 수행하기 위한 메소드다.
- 메시지가 훼손되지 않았는지 그대로 되돌려받아 확인한다.
- 보안 취약점이 있어 대부분의 서버에서는 비활성화되어 있다.
- 악의적 사용자가 본문이나 헤더를 몰래 확인할 목적으로 쓸 수 있기 때문이다.
OPTIONS
- 서버가 어떤 메소드, 통신 옵션 등을 지원하는지 확인하는 메소드다.
- 주로 CORS(Cross-Origin Resource Sharing) 검증 시 사용된다.
DELETE
- 데이터 삭제를 요청한다.
- 멱등성을 보장해야 하므로, “마지막 데이터를 삭제”와 같은 불명확한 요청은 포함되면 안 된다.
참고: 캐시 가능 여부
- 클라이언트가 요청 시, 서버로 직접 가지 않고 내부 캐시(로컬 혹은 중간 캐시)를 사용할 수 있는지 여부를 의미한다.
- 서버 측 내부 캐싱과는 다른 개념이므로 혼동하지 않아야 한다.
참고 2: 멱등성
- 함수를 한 번 적용하나 여러 번 적용하나 결과가 같다는 성질을 말한다.
- 다른 메소드나 로직에 의한 변경은 고려 대상이 아니다.
상태 코드
100번대 (Informational)
- 정보성 상태 코드로, 주로 커넥션 유지와 성능 최적화 목적을 가진다.
- 예: 100 Continue
- 프록시 서버 등이 다운 홉 서버와 통신 시, 요청의 일부만 먼저 전송받고 처리 가능 여부를 확인하는 용도로 사용한다.
- 일반적인 클라이언트-서버 통신에서는 거의 사용되지 않는다.
200번대 (Success)
- 성공을 의미하는 상태 코드.
- 200
- 요청이 정상 처리되었으며, 본문에는 요청한 리소스가 들어 있다.
- 201
- 자원(개체)을 성공적으로 생성했다는 의미.
- POST 등으로 서버에 새 자원을 만들었을 때 사용한다.
- 202
- 요청을 받아들였으나, 아직 처리가 완료되지 않았음을 의미한다.
- 처리가 언제 완료될지에 대한 정보를 함께 담는 경우가 많다.
- 204
- 요청은 정상 처리되었으나, 본문이 없다는 의미.
- 브라우저 화면 전환 없이 간단한 갱신을 할 때 활용된다.
300번대 (Redirection)
- 리다이렉션 관련 상태 코드.
- 301
- 영구적으로 리소스가 이동되었음을 나타낸다.
Location
헤더에 새 URL을 명시하고, 클라이언트는 향후 요청 시 이 새 주소를 사용한다.
- 302
- 일시적으로 다른 위치로 이동했다는 의미.
- 원래는 메소드 유지가 원칙이나, 많은 브라우저가 GET으로 변경해 버린다.
- HTTP/1.1에서 303(메소드 변경)과 307(메소드 유지)로 분화되었으나, 실제 현장에서는 302를 자주 쓴다.
- 303
- 리다이렉트 시 요청 메소드를 GET으로 바꿔서 재요청하도록 안내한다.
- 304
- 캐시 목적으로 사용된다.
- 요청된 리소스가 수정되지 않았다고 응답할 때 사용하며, 본문을 포함해서는 안 된다.
- 307
- 리다이렉트 시 기존의 메소드와 본문을 유지해야 함을 명시한다.
400번대 (Client Error)
- 클라이언트 측 오류 상태 코드.
- 400
- 요청 형식, 파라미터 등이 잘못되었을 때 사용한다.
- 401
- 인증이 되지 않았음을 의미한다. (Authorization 헤더가 없거나 잘못됨)
- 응답에
WWW-Authenticate
헤더를 포함해 인증 방법을 안내해야 한다.
- 403
- 인증 자격은 있지만, 인가(권한)가 부족할 때 사용한다.
- 접근 권한이 없는 자원에 대한 접근 시 발생한다.
- 404
- 요청 리소스가 존재하지 않을 때 사용한다.
- 리소스 존재 여부를 숨기기 위해 의도적으로 404를 반환하기도 한다.
- 405
- 지원하지 않는 메소드를 요청받았음을 의미한다.
Allow
헤더에 가능한 메소드 목록을 안내해야 한다.
- 406
- 허용되지 않는 응답 형식일 때 발생한다.
- 클라이언트의 Accept 헤더와 서버 응답이 불일치할 때 발생한다.
- 또는, 서버 측에서 Json 응답 처리(@ResponseBody)를 안했을 때 발생할수도 있다.
- 409
- Conflict
- 리소스 버전에 충돌이 발생했을 시 사용한다.
- 낙관적 락 버전 충돌 시 응답 코드로 사용한다.
500번대 (Server Error)
- 서버 측 오류 상태 코드.
- 500
- 서버 내부에서 오류가 발생했음을 의미한다.
- 원인을 특정하기 어려울 경우 일단 500을 응답한다.
- 502
- 게이트웨이나 프록시 서버가 다음 링크로부터 잘못된 응답을 받았을 때 사용한다.
- 상위 게이트웨이의 네트워크가 불가능하거나 응답이 비정상인 경우에 발생한다.
- 503
- 일시적으로 서버가 요청을 처리할 수 없음을 의미한다.
- 과부하 혹은 점검 중일 때 사용하며,
Retry-After
헤더로 재시도 시점을 안내하기도 한다.
헤더
헤더의 양식
일반 헤더
일반 정보 헤더
- Connection
- 클라이언트-서버 간 연결 유지 방식을 결정한다.
Connection: keep-alive
로 설정하면 여러 요청을 끊김 없이 처리할 수 있다.
- Date
- 메시지가 언제 생성되었는지 알려준다.
- 요청, 응답 모두에서 기록할 수 있으며, 로그나 캐시 처리 시 유용하다.
- Transfer-Encoding
- 본문 데이터를 인코딩하는 방식을 정의한다.
chunked
인코딩은 본문을 여러 덩어리로 잘라 전송하는 기법으로, 대용량 혹은 동적 데이터를 전송할 때 유리하다.
일반 캐시 헤더
- Cache-Control
- 캐싱 동작을 제어하는 지시자를 담는다.
Cache-Control: no-cache, no-store, must-revalidate
등을 통해 캐시 정책을 세밀히 조정할 수 있다.
- Pragma
- HTTP/1.0 하위 호환용으로, 캐시 제어에 쓰인다.
Pragma: no-cache
가 대표 예시지만, 최신 환경에서는Cache-Control
이 더 우선된다.
요청 헤더
요청 정보 헤더
- From
- 사용자 이메일 주소 등을 표시하기 위한 헤더이지만, 보안 문제로 거의 사용되지 않는다.
- Host
- HTTP/1.1부터 필수이며, 요청 대상 서버 호스트명과 포트를 담는다.
- 가상 호스팅(하나의 IP로 여러 도메인을 운영) 환경에서 반드시 필요하다.
- Referer
- 현재 요청이 어떤 페이지에서 유입되었는지 나타낸다.
- 트래픽 분석 등에 유용하지만, 보안 및 개인정보 문제로 빈 값 혹은 마스킹될 때도 있다.
- User-Agent
- 클라이언트 애플리케이션(브라우저 등)에 대한 정보를 담는다.
- 브라우저별 사용자 경험 개선, 로그 분석 등에 활용된다.
Accept 관련 헤더
- Accept
- 클라이언트가 받을 수 있는 MIME 타입을 제시한다 (예:
text/html, application/json
).
- 클라이언트가 받을 수 있는 MIME 타입을 제시한다 (예:
- Accept-Charset
- 수용 가능한 문자 인코딩을 나타낸다 (예:
utf-8, iso-8859-1;q=0.7
).
- 수용 가능한 문자 인코딩을 나타낸다 (예:
- Accept-Encoding
- gzip, deflate 등 콘텐츠 인코딩 방식을 통해 전송 효율을 높일 수 있음을 알린다.
- Accept-Language
- 클라이언트가 선호하는 언어를 명시한다 (예:
ko, en-US;q=0.8
).
- 클라이언트가 선호하는 언어를 명시한다 (예:
조건부 요청 헤더
- If-Modified-Since
- 지정된 시점 이후 수정되었을 때만 새로 다운로드하도록 유도해 트래픽을 절약한다.
- If-Unmodified-Since
- 특정 시점 이후 변경되지 않았다면 요청을 진행하고, 변경되었다면 412(Precondition Failed)로 처리한다.
- If-Match
- 리소스의 ETag 값과 일치하는 경우에만 작업을 진행하도록 제한한다.
- If-None-Match
- ETag와 일치하지 않을 경우에만 작업을 진행하도록 제한한다.
- If-Range
- 리소스가 변경되지 않았다면 Range 요청으로 부분만 받고, 변경되었다면 전체를 다시 받도록 한다.
- Range
- 대용량 파일 일부만 재전송하거나 스트리밍 시 특정 바이트 범위만 요청하기 위해 사용한다.
요청 보안 헤더
- Authorization
- HTTP 인증에 필요한 정보를 담는다 (Basic, Bearer 등).
- 서버는 이 정보를 기반으로 사용자 인증을 수행한다.
- Cookie
- 클라이언트 측에 저장된 쿠키 데이터를 서버에 전송한다.
- 보안 헤더는 아니나, 세션이나 사용자 추적 등에 영향이 크므로 주의해야 한다.
프록시 요청 헤더
- Max-Forwards
- 프록시를 지날 때마다 1씩 감소시키며, 요청이 몇 번 중계될지를 제한한다. 무한 루프 방지용이다.
- Proxy-Authorization
- 프록시 서버 접근 시 필요한 인증 정보를 제공한다.
- Proxy-Connection
- 프록시와의 연결 유지 여부를 제어한다. 최신 사양에서는
Connection
헤더와 함께 다루는 경우가 많다.
- 프록시와의 연결 유지 여부를 제어한다. 최신 사양에서는
응답 헤더
응답 정보 헤더
- Age
- 캐시된 응답이 얼마나 오래됐는지(초 단위) 나타낸다.
- 캐시 유효성 검증에 도움을 준다.
- Retry-After
- 재시도 전 대기 시간을 나타낸다. (예:
Retry-After: 120
) - 503(Service Unavailable) 등이 발생했을 때 재시도 시점 안내에 사용된다.
- 재시도 전 대기 시간을 나타낸다. (예:
- Server
- 서버 애플리케이션 정보를 담는다.
- 보안상 노출을 최소화하는 경우도 있다.
협상 헤더
- Accept-Ranges
- 부분 요청(Range 요청)을 지원하는지 여부를 나타낸다. (예:
Accept-Ranges: bytes
)
- 부분 요청(Range 요청)을 지원하는지 여부를 나타낸다. (예:
응답 보안 헤더
- WWW-Authenticate
- 401 Unauthorized 응답 시, 서버가 지원하는 인증 방식을 안내한다.
- Proxy-Authenticate
- 407 Proxy Authentication Required 응답 시, 프록시가 요구하는 인증 방식을 안내한다.
- Set-Cookie
- 서버에서 클라이언트에게 쿠키를 설정하도록 지시한다.
- 쿠키 속성(만료, 경로, HttpOnly 등)을 함께 지정한다.
표현 헤더
표현 정보 헤더
- Allow
- 특정 리소스에서 지원하는 메소드를 나열한다.
- 405 오류 응답 시, 사용할 수 있는 메소드를 안내하기 위해 사용된다.
- Location
- 3xx 리다이렉트 시 이동할 주소나, 201 응답 시 새로 생성된 리소스의 주소를 안내한다.
콘텐츠 헤더
- Content-Encoding
- 본문이 어떤 방식으로 압축 또는 인코딩되었는지 표시한다.
- Content-Length
- 응답 본문의 바이트 길이를 나타낸다.
- Content-Range
- 부분 요청에 대한 응답 시, 현재 전송 범위와 전체 크기를 표기한다.
- Content-Type
- 본문의 MIME 타입과 문자 인코딩 등을 나타낸다 (예:
text/html; charset=UTF-8
).
- 본문의 MIME 타입과 문자 인코딩 등을 나타낸다 (예:
유효성 검사 헤더
- Expires
- 캐시가 만료되는 시점을 명시한다.
- 정적 리소스 등에서 미리 기간을 설정하면, 해당 시간 전까지 클라이언트는 캐시를 재사용한다.
- ETag
- 리소스의 고유 버전 식별자 역할을 하며,
If-None-Match
등과 함께 사용한다. - 변경 검증 로직을 서버가 주도적으로 관리할 수 있다는 장점이 있다.
- 리소스의 고유 버전 식별자 역할을 하며,
- Last-Modified
- 리소스가 마지막으로 수정된 시점을 나타낸다.
If-Modified-Since
와 함께 사용하며, 날짜 비교를 통해 캐시 적중 여부를 판단한다.
더욱 자세한 내용은 RFC 9110에서 확인 가능하다.
'CS Repo > HTTP 완벽 가이드' 카테고리의 다른 글
웹 서버 (0) | 2025.04.04 |
---|---|
HTTP 커넥션 관리 최적화 기법 (0) | 2025.04.03 |
HTTP에서 바라본 TCP 커넥션 관리 방식 (0) | 2025.03.27 |
URL과 리소스 (0) | 2025.03.24 |
HTTP란? (0) | 2025.03.24 |