HTTP message

January 20, 2019 ·   13 mins to read

1. 인바운드 - 아웃바운드, 다운스트림

서버를 기준으로 유입되는 트래픽 / 요청등을 인바운드, 그에 대한 응답이나 직접 클라이언트에게 응답을 보내는 경우를 아웃바운드라고 한다. 즉, 서버를 기준으로 들어오는 것인바운드, 나가는 것아웃바운드라고 생각하면 된다.

HTTP 메시지는 항상 물처럼 흐르고 역류 하지 않는다. 메시지의 발신자는 수신자의 업스트림이 되며, 메시지는 다운스트림으로 보내진다. 서버인지 클라이언트인지에 상관없이 업스트림과 다운스트림은 상황에 따라 바뀌게 된다.

client(업스트림) -> server(다운스트림)
client(다운스트림) <- server(업스트림)

2. Message

1. 메시지의 세 부분

  • 메시지는 보통 [시작줄 - 헤더 - 본문]의 구조로 되어있다.

2. 메시지의 구조

  • Reqeust의 경우
<Method> <URL> <HTTP version> ] 시작줄
<Header>                      ] 헤더

<Content>                     ] 본문
  • Response의 경우
<HTTP version> <Status code> <Reason phase> ] 시작줄
<Header>                                    ] 헤더

<Content>                                   ] 본문
  • Method: 사용된 HTTP method의 종류.
  • URL: Request를 요청받는 측의 URL.
  • HTTP version: HTTP 버전을 나타내며, 어떤 어플리케이션이 지원하는 가능 높은 HTTP 버전을 나타낸다.
  • Status code: 어떤 request의 실행결과를 숫자로 보여준다.
  • Reason phase: 사람이 알아볼 수 있게, status code와 함께 리턴되는 간단한 메시지.
  • 본문: 있을수도 있고, 없을수도 있는 화물. HTTP가 이것을 운송하도록 설계되었다. 이미지, 비디오, 텍스트, 소프트웨어 어플리케이션 등 많은 것을 포함할 수 있다.

기억해야 할 점은 request, response 메시지의 본문은 있을수도 있고 없을수도 있다는 것이며, 메시지 본문의 유무와 상관없이 Header의 끝은 반드시 CRLF (opens new window)로 마무리 되어야 한다는 것이다.

3. Header

1. Header의 특징

  • 0개 혹은 그 이상의 헤더가 위치할 수 있다.
  • 각각 CRLF로 구분한다.
  • key-value의 구조를 가진다. Content-Type: text/html

2. Header의 종류

A. 일반 헤더

  • 일반 헤더는 클라이언트와 서버 양쪽 모두가 사용한다. 일반적으로, 메시지에 대한 아주 기본적인 정보를 제공하는 경우 사용하게 된다.
헤더설명
Connection클라이언트-서버가 요청/응답 연결에 대한 옵션. MDN (opens new window)
Date메시지가 만들어진 날짜와 시간.
MIME-Version발송자가 사용한 MIME의 version.
Trailer chunked transfer청크와 지속 커넥션을 위한 헤더(나중에 자세히 기술 예정).
Trasfer-Encoding메시지에 적용된 인코딩의 종류.
Upgrade발송자가 업그레이드하길 원하는 새 버전이나 프로토콜.
Via메시지가 거쳐온 중개자(proxy, gateway).

B. 일반 캐시 헤더

헤더설명
Cache-Control캐시 지시자를 전달. MDN (opens new window)
Pragmadeprecated.

C. 요청 헤더(Request Header)

  • 요청(Request) 메시지에서만 의미를 갖는 헤더로, 보통 클라이언트 측에서 자동으로 작성되어 보내지는 경우가 많다. 물론, 조작될 가능성도 있으니 주의해야 한다.
예시
Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36
헤더설명
Client-IP클라이언트의 IP.
From클라이언트 사용자의 메일 주소.
Host요청의 대상이 되는 서버의 호스트명과 포트.
Referer현재의 요청 URI가 들어있던 문서의 URL. 즉 현재 페이지 이전의 페이지 주소.
User-Agent요청을 보낸 어플리케이션의 이름.
  • Accept 관련 헤더는 주로 클라이언트에서 사용되는 미디어의 종류에 대해서 보내게 된다. 각 헤더는 콤마로 구분 가능하며, 와일드카드 역시 동작한다.
예시
Accept: text/html

Accept: image/*

Accept: text/html, application/xhtml+xml
헤더설명
Accept서버가 클라이언트에 보내도 상관없는 미디어의 종류. MDN (opens new window)
Accept-Charset서버가 클라이언트에 보내도 상관없는 문자셋의 종류.
Accept-Encoding서버가 클라이언트에 보내도 상관없는 인코딩 타입.
Accept-Language서버가 클라이언트에 보내도 상관없는 언어.
  • 조건부 요청 헤더는 클라이언트가 요청에 대해 몇몇 제약을 넣고자 할 때 사용한다. 예를들어 클라이언트가 이미 어떤 문서의 사본을 가지고 있는 상태라면, 클라이언트는 서버에게 이 문서의 사본과 원본이 다를때만 전송해 달라고 요청 할 수 있다.
헤더설명
If-Match문서의 엔터티 태그가 일치하는 경우에만 문서를 가져온다.
If-Modified-since주어진 날짜 이후 리소스가 변경되지 않았다면 요청을 제한.
If-None-Match문서의 엔터티 태그가 일치하지 않는 경우에만 문서를 가져온다. ETag와 함께 쓰이기도 한다.
If-Range문서의 특정 범위에 대한 요청
If-Unmodified-Since주어진 날짜 이후 리소스가 변경되었다면 요청을 제한.
Range서버가 range-request를 지원하는 경우 리소스에 대한 특정 범위를 요청(나중에 자세히 기술 예정).
  • 보안 헤더는 간단한 인증요구/응답을 위해 사용된다. 보안 헤더의 종류는 아니지만, Cookie역시 이러한 역할을 한다고 볼 수 있다.
헤더설명
Authorization클라이언트가 서버에 제공하는 인증 그 자체에 대한 정보.
  • proxy 요청 헤더
헤더설명
Max-ForwardProxy될 수 있는 최대 회수. TRACE method와 함께 쓰인다.
Proxy-AuthorizationAuthorization과 같으나, proxy인증 시 쓰인다.
Proxy-ConnectionConnection과 같으나, proxy인증 시 쓰인다.

D. 응답 헤더(Response Header)

  • 응답(Response) 헤더는 클라이언트에게 부가 정보를 제공한다.
헤더설명
Age응답이 경과된 시간.
Public서버가 특정 리소스에 대해 지원하는 요청 method의 목록.
Retry-After현재 리소스가 사용불가능한 상태일때, 사용 가능해지는 시각.
Server서버의 어플리케이션 이름과 버전.
WarningReason phase 보다 더 자세한 경고 메시지.
  • 협상 헤더
헤더설명
Accept-Ranges서버가 자원에 대해 받아들일 수 있는 범위의 형태.
Vary서버가 확인해 보아야 하고 응답에 영향을 줄 수 있는 헤더들의 목록.
  • 응답 보안 헤더
헤더설명
Proxy-AuthenticateProxy에서 클라이언트로 보낸 인증요구의 목록.
Set-Cookie서버에서 사용자 브라우저에 쿠키를 전송하기 위해 사용. 이 헤더를 받았을 경우 브라우저는 Cookie를 저장하고, 다음번 요청의 Cookie에 해당 내용을 포함한다. MDN (opens new window)
WWW-Authenticate서버에서 클라이언트로 보낸 인증요구의 목록.

E. 엔터티 헤더

  • HTTP message의 엔터티(본문)에 대해 설명하는 헤더들로, 요청과 응답 양쪽 모두에서 사용할 수 있다.
  • 정보 헤더
헤더설명
Allow이 엔터티에 대해 수행될 수 있는 요청 method들을 나열.
Location엔터티가 실제로 위치하고 있는 곳. 리소스에 대한 실제 URL을 알려줄 때 사용.
  • 콘텐츠 헤더
헤더설명
Content-BaseBase URL.
Content-Encoding엔터티에 적용된 인코딩.
Content-Language본문을 이해하는데 가장 적절한 언어.
Content-Length본문의 길이나 크기.
Content-Location리소스의 실제 위치.
Content-MD5본문의 MD5 checksum.
Content-Range전체 리소스에서 엔터티가 해당하는 범위를 바이트 단위로 표현.
Content-type본문의 객체 타입.
  • 엔터티 캐싱 헤더
헤더설명
ETag엔터티에 해당하는 엔터티 태그. 참고 링크에 따르면, 엔터티를 식별할 수 있는 hash value가 필요함. 참고 (opens new window)
Expires원본을 다시 받아와야하는 일시.
Last-Modified가장 최근에 엔터티가 변경된 일시.

4. Method

Method는 클라이언트가 서버측에 특정한 동작을 요청하는데 쓰이는 것으로, 서버마다 구현되어있는 method는 각각 다를 수 있지만, 개발자는 최대한 method의 목적에 맞는 기능을 구현해야 한다.

A. 안전한 method

HTTP에는 안전한 method의 집합이 있다. 안전한 method란 다음과 같은 method를 의미한다.

  • HTTP 요청으로 인해 서버 혹은 DB에 아무런 작용이 일어나지 않는 method.
  • 작용이란 DB에 새로운 값이 입력, 수정, 삭제되거나 신용카드로 대금이 청구되는 등의 동작을 이야기 한다.
  • 안전한 method에는 GET, HEAD등이 있다.

B. Method의 종류

method기능
GET단순한 자원의 요청.
HEADGET과 비슷하지만, header만 반환.
PUT요청한 URL과 본문으로 서버는 새로운 문서를 만들거나, 기존 URL에 해당하는 문서를 변경.
POST서버에 데이터를 보내기위해 사용.
OPTIONS서버가 지원하는 method를 반환.
DELETE자원을 삭제
TRACE주로 진단시에 사용. 클라이언트에게 자신의 요청이 서버에 도달했을 때 어떻게 보이기 되는지 알려줌.
PATCHPUT과 유사하나, 문서 전체를 바꾸지 않고 일부만 바꿀때 사용.
  • HEAD method를 사용하게 되면, 리소스를 직접 가져오지 않고 리소스의 존재 여부, 타입 등을 알아낼 수 있다. HTTP/1.1 스펙을 준수하기 위해서는 HEAD가 반드시 구현되어 있어야 하고, HEAD를 통해 반환되는 header와 GET을 통해 반환되는 header는 반드시 일치해야 한다.
  • PUT과 POST method가 하는 일은 조금 다른데, 실제로 api서버를 개발할 때 POST는 새로 생성 PUT은 변경 혹은 수정에 사용했었던 기억이 있다.
  • PATCH라는 method는 책에 소개되어있지는 않지만 예전에 api서버를 개발할 때의 기억이 있어 추가해 보았다. PATCH는 PUT과 비슷한 역할을 하지만, PUT은 문서 전체를 변경하는 대신 PATCH는 일부분만 변경하기 때문에 update기능을 구현하는데에 의미적으로 조금 더 적합하지 않나 하는 생각이 든다.

5. Status code, Reason phase

Status code와 reason phase는 response message에 포함되어 반환되는 값으로, 클라이언트의 요청에 대해 서버가 처리한 결과이다. Status code는 보통 세자리의 숫자기 때문에 코드상에서 에러 처리등의 용도로 사용한다. Reason phase는 status에 대해서 사람이 좀 더 알아보기 쉬운 짧은 readable text 형태이기 때문에 status code를 좀 더 쉽게 이해하도록 도와준다.

Status code는 상태에 따라 반환하는 code와 범위를 미리 지정해 놓았다 (RFC 7231 (opens new window)).

범위Predefined range분류
100-199100-101정보
200-299200-206성공
300-399300-305Redirection
400-499400-415Client error
500-599500-505Server error

미리 정의된 code를 제외하고 status code를 새로 기술할 때는 두 가지 규칙을 따라야 한다.

  • 상태코드의 약속된 범위내에 포함되는 에러라고 간주할 수 있어야 한다. 즉 성공을 나타내는 200번대 status code에 서버 에러에 대한 code를 정의하면 안된다.
  • 미리 정의된 status code를 임의로 변경하지 않는다.

A. 200번대 status code

200번대의 status code는 요청에 대해 성공했음을 알려주는 code로 구성되어 있다.

코드Reason phase의미
200OK요청은 정상이고, 엔터티 본문은 요청된 리소스를 포함하고 있음.
201Created개체를 생성하는데 성공함. 서버는 응답 메시지에 생성된 리소스의 URL을 Location헤더와 엔터티 본문에 포함해야 함.
202Accepted요청은 받아들여졌으나 서버는 아직 동작을 수행하지 않음. 서버는 응답 메시지에 요청에 대한 상태와 처리 완료 시점에 대해 엔터티본문에 기술해 주면 좋음.
203Non-Authoitative Information엔터티 헤더에 들어있는 정보가 원래 서버가 아닌 리소스의 사본에서 왔음.
204No Content응답 메시지에 엔터티 본문을 포함하고 있지 않음.
205Reset Content브라우저에게 현재 form에 채워진 모든 값을 비우라고 지시.
206Partial Content부분 혹은 범위 요청 성공. 서버는 응답 메시지에 Content-Range와 Date를 반드시 포함해야 하며, ETag와 Content-Location중 하나의 헤더도 반드시 포함해야 함.

B. 300번대 status code

300번대의 status code는 요청에 대한 리소스가 옮겨지거나 다른 위치를 참조해야할 때 사용되며, 이는 브라우자가 사용자를 귀찮게 하지 않고 알아서 새 위치로 이동할 수 있게 해준다.

코드Reason phase의미
300Multiple Choice클라이언트가 동시에 여러 리소스를 가리키는 URL을 요청한 경우, 리소스의 목록과 함께 반환됨. 예를들면, 어떤 서버가 하나의 HTML문서를 한국어와 영어로 제공하는 경우 등에 사용 가능. 서버는 Location 헤더에 선호하는 URL을 포함할 수 있음.
301Moved Permanently클라이언트가 요청한 리소스가 응답 메시지의 Location 헤더에 주어진 URL에 일시적으로 이동되었음. 브라우저는 응답 메시지의 Location 헤더에 주어진 URL로 이동하고 검색엔진은 링크를 갱신함.
302Found301과 동일함. 브라우저는 응답 메시지의 Location 헤더에 주어진 URL로 이동하지만, 검색엔진은 링크를 갱신하지 않음.
303See Other새로운 리소스로 연결되는 것이 아닌, 확인 페이지 또는 업로드 진행 페이지등과 같은 곳으로 연결됨. 일반적으로 PUT, POST 요청에 대한 응답으로 클라이언트에게 리소스의 위치를 알려줌.
304Not Modified주로 캐시를 목적으로 사용됨. If-None-Match 또는 If-Modified-Since 같은 조건부 헤더를 사용하였을때, 최근에 문서가 수정된 적이 없을 경우 이 code가 반환되며 클라이언트는 계속해서 기존에 캐시된 버전을 사용할 수 있음. 해당 code의 응답 메시지는 엔터티 본문을 가져서는 안됨.
305Use Proxy리소스가 반드시 proxy를 통해 접근되어야 함. Proxy의 위치는 Location 헤더를 통해 주어짐. 현재 proxy의 in-band 설정에 대한 보안상의 걱정으로 인하여 권장하지 않음.
306현재 사용되지 않음
307Temporary Redirect301과 동일함. 원래 요청의 메서드와 본문은 리디렉션 된 요청을 수행하기 위해 다시 사용됨. 302를 사용할 경우, 예전의 클라이언트들은 GET 방식을 잘못 변경했지만 307은 method와 엔터티 본문이 변하지 않는 것을 보장함.

C. 400번대 status code

400번대의 status code는 클라이언트의 에러를 나타내며, 404와 같은 몇몇 에러를 제외하면 브라우저에 의해 처리된다. 400번대의 status code는 종류가 많기때문에, 주로 사용되는 것에 대해서만 설명하고자 한다. 나머지 status code에 대해서는 이곳 (opens new window)을 참고하면 좋을 것 같다.

코드Reason phase의미
400Bad Request클라이언트의 요청을 서버가 이해할 수 없음.
401Unauthorized클라이언트가 스스로를 인증해야 함.
403Forbidden클라이언트의 접근 권한이 없음. 401과 다른점은 서버가 클라이언트가 누구인지 알고있음.
404Not Found요청한 URL을 찾을 수 없음.
405Method Not Allowed현재 요청한 method를 사용할 수 없음. GET과 HEAD는 제거될 수 없으며 따라서 이 code를 반환할 수 없음.
408Request Timeout클라이언트의 요청을 완수하기에 시간이 오래 걸리는 경우.

D. 500번대 status code

500번대의 status code는 서버의 에러를 나타낸다.

코드Reason phase의미
500Internal Server Error서버가 요청을 처리할 수 없게 만드는 에러에 봉착함.
502Bad GatewayProxy나 gateway 역할을 하는 서버가 요청을 처리하는 데 필요한 응답을 얻기 위해 작업하는 동안 잘못된 응답을 수신했음 (상위 gateway 접속 불가 등).
503Service Unavailable서버가 요청을 처리할 준비가 되지 않음. 유지보수 혹은 과부하가 원인. 서버는 응답 메시지에 Retry-After헤더를 사용하는 것이 좋다.
504Gateway Timeout408과 비슷하지만, 다른 서버에 요청을 보내고 응답을 기다리다 timeout이 발생한 상황.
505HTTP Version Not Supported서버가 지원할 수 없거나 지원하지 않는 버전의 프로토콜로 된 요청을 받음.

6. Conclusion

HTTP 완벽 가이드 (opens new window)의 3장을 가볍게 정리해 보았다. 저번과 마찬가지로 대충 알고 있던 부분을 채울수 있어서 좋았고, 몰랐던 부분을 알수 있게되어 더 느낌이 좋았다. 다만 이번의 글은 “공부했다!”라는 느낌 보다는 단순한 정보의 나열처럼 보이는 것이 조금은 아쉽다.

특히 header부분을 공부하고 나서보니 개발자 도구의 network탭이 새롭게 보이는 효과를 보았다. 생각보다 header가 큰 역할을 하고 있으며, 적절히 사용하면 앞으로의 프로젝트에도 도움이 될 것이라 생각한다.


참고


© 2021, Built with Gatsby