[HTTP 완벽 가이드] HTTP 메시지

은승균·2022년 7월 6일
0

HTTP 완벽 가이드 의 3장을 읽고 정리한 내용입니다.

3장에서는 HTTP 메시지를 어떻게 만들고 이해하는지에 대해서 다루고 있습니다.

HTTP 메시지

메시지의 흐름

HTTP 메시지란 HTTP 애플리케이션 간에 주고 받은 데이터 블록들이다. 데이터 블록은 메시지의 내용과 의미를 설명하는 텍스트 메타 정보로 시작하고 그 다음에 선택적으로 데이터가 올 수 있다.

  • 업스트림:

  • 다운스트림:

    메시지는 원 서버 방향을 인바운드로 하여 송신된다.

    HTTP는 인바운드와 아웃바운드라는 용어를 트랜잭션 방향을 표현하기 위해 사용한다.

  • 인바운드: 메시지가 원 서버 방향으로 이동하는 것

  • 아웃바운드: 메시지가 사용자 에이전트 방향(클라이언트)으로 돌아오는 것

    다운 스트림으로 흐르는 메시지

    HTTP 메시지는 강물과 같이 흐른다(Stream). 요청 메시지냐 응답 메시지냐에 관계 없이 모든 메시지는 다운스트림으로 흐른다. 메시지의 발송자는 수신자의 업스트림이다.

메시지의 각 부분

HTTP의 메시지는 세 부분으로 이루어져 있다.

  • 시작줄: HTTP/1.0 200 OK
    • 시작줄은 어떤 메시지인지 서술한다.
  • 헤더: Content-type: text/plain
    • 속성을 서술한다.
  • 본문: Hi! I'm a message
    • 데이터를 담고 있다.

    • 텍스트나 단순 이진 데이터를 포함할 수도 있고, 비어있을 수도 있다.

      시작줄과 헤더는 줄 단위로 분리된 아스키 문자열이다. 각 줄은 캐리지 리턴과 개행문자로 구성된 두 글자의 줄바꿈 문자열(/r/n)으로 끝난다. CRLF라고도 부른다.
      오래된 HTTP 애플리케이션들 중에서는 캐리지 리턴과 개행 문자를 항상 전송하지 않고 개행 문자만 보내는 경우도 있다고 한다. 그래서 견고한 애플리케이션이라면 캐리지 리턴 없이 개행 문자만으로 이루어진 것도 받아들일 수 있어야 한다.

메시지 문법

요청 메시지응답 메시지시작줄을 제외한 부분의 형태가 똑같다.

요청 메시지의 형식은

    <메서드> <요청URL> <버전>
    <헤더>
         
    <엔티티 본문>

응답 메시지의 형식은

   <버전> <상태코드> <사유 구절>
   <헤더>
        
   <엔티티 본문>

헤더나 엔티티 본문이 없더라도 HTTP 헤더의 집합은 항상 빈 줄(CRLF)로 끝나야 한다. 하지만 이러한 규칙을 잘 지키지 않는 구현체와의 호환을 위해 클라이언트에서는 마지막 CRLF 없이 끝나는 메시지도 받아들일 수 있도록 해야한다.

메서드

메서드설명메시지 본문이 있는가?
GET서버에서 어떤 문서를 가져온다.X
HEAD서버에서 어떤 문서에 대해 헤더만 가져온다.X
POST서버가 처리해야 할 데이터를 보낸다.O
PUT서버에 요청 메시지의 본문을 저장한다.O
TRACE메시지가 프락시 서버를 거쳐 서버에 도달하는 과정을 추적한다.X
OPTIONS서버가 어떤 메서드를 수행할 수 있는지 확인한다.X
DELETE서버에서 문서를 제거한다.X

위의 메서드 뿐만 아니라 HTTP는 쉽게 확장할 수 있게 설계되어 다른 서버에서는 메서드를 추가로 구현(확장 메서드)했을 수도 있다.

상태 코드

상태코드는 클라이언트에게 무엇이 일어났는지 말해준다. 상태코드는 숫자로 된 코드와, 문자열로 이루어져 있다. 세 자리 숫자로 된 코드이며, 각 범위에 따른 의미는 아래와 같다

전체 범위정의 된 범위분류
100~199100~101정보
200~299200~206성공
300~399300~305리다이렉션
400~499400~415클라이언트 에러
500~599500~505서버 에러

지정되지 않은 해당 범위 내에서 프로토콜의 확장으로 정의하여 사용할 수 있다. 이때 상위 범주의 일반적인 구성원으로 가정하고 다루어야 한다.

사유 구절

HTTP/1.0 200 OK에서 사유 구절은 OK 부분이다. 상태코드와 1대 1로 대응되며, 애플리케이션 개발자들이 이것을 보고 사용자에게 요청중에 무슨 일이 일어났는지 알려준다.

HTTP 버전

버전은 HTTP/x.y의 형식으로 이루어져 있으며, x와 y 부분을 따로 보고 비교해야한다. 즉, HTTP/2.22 버전은 HTTP/2.3 버전보다 높은 버전이다. 2 부분이 같고, 22 > 3 이기 때문이다.

헤더

헤더 분류

  • 일반 헤더
    • 요청과 응답 양쪽에 모두 나타날 수 있음
  • 요청 헤더
    • 요청에 대한 부가 정보를 제공
  • 응답 헤더
    • 응답에 대한 부가 정보를 제공
  • Entity 헤더
    • 본문 크기와 콘텐츠, 혹은 리소스 그 자체를 서술
  • 확장 헤더
    • 명세에 정의되지 않은 새로운 헤더

Entity 본문

HTTP의 세번 째 부분, 선택적인 본문으로, 메시지의 화물이라고 할 수 있다. 이미지, 비디오, HTML문서, 신용카드 트랜잭션 등 여러 종류의 디지털 데이터를 실어 나를 수 있다.

메서드

모든 서버가 모든 메서드를 구현하지 않는다. HTTP/1.1과 호환되고자 한다면, 서버는 자신의 리소스에 대해서 GET, HEAD 만을 구현하는 것으로도 충분하다.
전부를 구현하지는 않아도 대부분 제한적으로 DELETE나 PUT과 같은 메서드들도 사용될 것이다.

안전한 메서드

보통 GET, HEAD와 같이 서버의 리소스를 요청하는 메서드는 안전한 메서드라고 한다. 이는 요청의 결과로 서버에 어떤 작용도 없음을 의미한다.
작용이 없다는 것은 요청 결과로 인해 서버에서 일어나는 일은 아무것도 없다는 의미이다.
유저가 안전하지 않은 메서드를 사용하려고 할 때 그 사실을 알려주는 HTTP 애플리케이션을 만들어야한다.

GET 메서드

리소스를 달라고 요청하기위해 쓰이는 메서드이다. HTTP/1.1은 서버가 이 메서드를 구현할 것을 요구한다.

HEAD 메서드

정확히 GET 처럼 행동한다. 대신 서버는 응답으로 헤더만을 보내준다.

  • 리소스를 가져오지 않고도 리소스가 무엇일지 알 수 있다.

  • 응답의 상태 코드를 통해 개체가 존재하는지 확인할 수 있다.

  • 헤더를 확인하여 리소스가 변경되었는지 검사할 수 있다.

    GET과 HEAD를 통해 반환되는 헤더는 정확히 일치함을 보장해야한다.
    HTTP/1.1 준수를 위해서는 HEAD가 반드시 구현되어있어야 한다.

PUT 메서드

서버에 문서를 쓴다. PUT 메서드의 의미는 요청 URL의 이름대로 새 문서를 만들거나, 이미 URL이 존재한다면 본문을 사용해서 교체하는 것이다. PUT을 위해서는 많은 서버가 사용자 로그인을 요구할 것이다.

POST

서버에 입력 데이터를 전송하기 위해서 설계되었다. HTML 폼(form)을 지원하기 위해 흔히 사용된다.

PUT은 서버의 리소스에 입력하기 위해 사용되고,
POST는 서버에 데이터를 보내기 위해 사용된다.

TRACE

클라이언트의 요청은 서버로 보내질 때 방화벽, 프락시, 게이트웨이등의 애플리케이션을 지날 수 있다. TRACE는 클라이언트에게 자신의 요청이 서버에 도착했을 때 어떻게 보이는지 알려준다.

서버는 자신이 받은 요청의 메시지를 다시 본문에 넣어 응답으로 되돌려 준다.

주로 진단을 위해 사용된다.

  • 요청이 의도한 요청/응답 연쇄를 거쳐가는지 검사
  • 프락시나 다른 애플리케이션들이 요청에 어떤 영향을 미치는지 확인

중간 애플리케이션이 여러 다른 종유의 요청을 일관되게 다룬다고 가정한다.
프락시는 POST 요청을 바로 서버로 통과시키는 반면, GET 요청은 웹 캐시와 같은 다른 HTTP 애플리케이션으로 전송한다.
메서드에 따라 일관되게 동작하지 않으므로 문제가 될 수 있다.

OPTIONS

웹서버에게 여러 종류의 지원 범위에 대해 물어본다. 특정 리소스에 대해 어떤 메소드가 지원되는지 물어볼 수 있다. 실제 리소스에 접근하지 않고도 해당 리소스에 어떻게 접근하는것이 가장 좋은지 알 수 있다.

DELETE

요청한 URL의 리소스에 대해 삭제 요청을 한다. 하지만 삭제를 보장하지는 못하는데, HTTP 명세는 서버가 클라이언트에게 알리지 않고 요청을 무시하는 것을 허용하기 때문이다.

확장 메서드

HTTP는 필요에 따라 확장해도 문제가 없도록 설계되어있다. 프락시는 end-to-end 행위를 망가뜨리지 않을 수 있다면, 알려지지 않은 메서드가 담긴 메시지를 다운스트림 서버로 전달하려고 시도한다. 그렇지 않다면 501 Not Implemented 상태코드로 응답한다.

엄격하게 보내고 관대하게 받아들여라 라는 오랜 규칙을 따르는 것이 좋다.

상태코드

HTTP 상태코드는 크게 다섯 가지로 나뉜다.

100 - 199: 정보성 상태코드

HTTP/1.1에서 도입된 상태 코드이다. 약간 복잡하기 때문에 복잡함을 감수할만 한지 논의되고 있다고 한다.

상태코드사유구절의미
100Continue요청 시작 부분의 일부가 받아들여짐. 클라이언트는 나머지를 계속 이어서 보내야 함. 서버는 반드시 요청을 받아 응답해야 함
101Switching Protocol클라이언트가 Upgrade 헤더에 나열한 것 중 하나로 서버가 프로토콜을 바꾸었음을 의미함

100번 코드는 서버에 엔티티 본문을 전송하기 전서버가 그 엔티티 본문을 받아들일 것인지 확인하려고 할 때 확인 작업 최적화를 위한 의도로 도입되었다.

200 - 299: 성공 상태 코드

우리가 많이 보는 200번대 응답코드이다. 기본적으로 요청이 성공했음을 알려준다.

300 - 399: 리다이렉션 상태 코드

300 번대 코드는 클라이언트가 관심있어하는 리소스에 대해 다른 위치에 있다고 말해주거나 다른 대안 응답을 제공한다. 다른 위치에 있다는 것은 헤더의 Location 필드를 통해서 알려줄 수 있다. 로컬 복사본(캐시)과 비교하여 변경사항이 없다면 로컬 복사본을 보여주는 동작을 할 수 도 있다(304).

300번대에는 HTTP/1.0과 HTTP/1.1의 차이점 때문에 혼란스러운 점이 하나 있다.

HTTP/1.0에서는 POST요청에 대해 302 리다이렉트 코드를 응답으로 받으면 클라이언트는 Location 헤더에 있는 URL을 GET요청으로 따라갈 것이다.

즉, HTTP/1.0 서버는 302 코드에 대해 클라이언트가 GET요청을 보내올 것을(리다이렉트 할 것을) 기대한다.

하지만 HTTP/1.1에서는 이러한 리다이렉션(POST -> 302 코드 -> GET)을 위해 303 상태코드를 사용한다.

두 코드의 혼란을 막기위해 HTTP/1.1 명세에는 HTTP/1.1 클라이언트의 일시적인 리다이렉트를 위해 302코드 대신 307코드를 사용하라고 한다.

302는 HTTP/1.0 을 위해서 사용되도록 남겨둔다.
서버는 302를 보낼지 307을 보낼지 결정하기 위해 HTTP 버전을 확인할 필요가 있다.

400 - 499: 클라이언트 에러 상태 코드

잘못 구성된 요청 메시지, 서버가 다룰 수 없는 것, 존재하지 않는 URL에 대한 요청 등 에러에 대한 상태코드를 위한 범위이다.

상태코드사유구절
400Bad Request
401Unauthorized
403Forbidden
404Not Found
405Method Not Allowed
406Not Acceptable
407Proxy Athentication Required
408Request Timeout
415Unsupported Media Type

이외에도 많은 코드가 있는데, 주로 처리하지 못한 요청과 받아들이지 못하는 요청에 대한 에러 코드이다.

500 - 599: 서버 에러 상태 코드

서버 자체에서 발생하는 에러에 대한 상태 코드를 나타낸다. 클라이언트가 서버의 제한에 걸린 것일 수도 있고, 서버 보조 구성요소에서 발생한 에러일 수도 있다.

상태코드사유구절의미
500Internal Server Error서버가 요청을 처리할 수 없게 만드는 에러
501Not Implemented서버의 능력을 넘은 요청에 대한 에러(지원하지 않는 메서드 사용 등)
502Bad Gateway프락시나 게이트웨이처럼 행동하는 서버가 요청 응답 연쇄에 있는 다음 링크로부터 가짜 응답에 맞닥뜨렸을 때. (부모 게이트 웨이에 접속하지 못할 때, 서버가 꺼져있을 때 등)
503Service Unavailable현재는 요청을 처리할 수 없을 때, 나중에는 가능함을 의미, Retry-After 헤더를 통해 언제 사용할 수 있는지 알릴 수 있음
504Gateway Timeout408과 비슷하지만, 다른 서버에서 요청을 보내고 응답을 기다리다 타임아웃이 발생한 경우
505HTTP Version NOT Supported지원하지 않는 프로토콜로 된 요청에 대한 에러 코드

헤더

헤더메서드클라이언트와 서버가 무엇을 하는지 결정하기 위해 함께 사용된다.

일반 헤더

서버, 클라이언트 양쪽 모두 사용.

  • Connection: 클라이언트와 서버가 요청/응답 연결에 대한 옵션 정할 수 있다.
  • Date*: 메시지가 언제 만들어졌는지에 대한 시간
  • MIME-Version: 발송자가 사용한 MIME의 버전
  • Trailer chunked transfer: 인코딩으로 인코딩된 메시지의 끝 부분에 위치한 헤더들의 목록 나열
  • Transfer-Encoding: 수신자에게 메시지에 어떤 인코딩이 적용되었는지 알려준다.
  • Upgrade: 업그레이드하길 원하는 새 버전이나 프로토콜 명시

일반 캐시 헤더

HTTP/1.0은 애플리케이션에게 매번 원 서버로부터 객체를 가져오는 대신 로컬 복사본으로 캐시할 수 있도록 해주는 최초의 헤더를 도입했다.

  • Cache-Control : 메시지와 함께 캐시 지시자를 전달
  • Pragma: 메시지와 함께 지시자를 전달하는 또 다른 방법, 캐시에 국한되지 않는다.

요청 헤더

요청 메시지를 위한 헤더. 데이터 타입이 무엇인지와 같은 부가정보를 제공

  • Client-IP

  • From: 클라이언트 사용자의 메일 주소

  • Host: 요청 대상이 되는 서버의 호스트명과 포트 번호

  • Referer: 현재으 요청 URI가 들어있던 문서의 URL을 제공

  • User-Agent: 요청을 보낸 애플리케이션의 이름

    이외에도 UA-Color, UA-CPU 등 다양한 클라이언트의 정보를 알려주는 헤더가 존재

Accept 관련 헤더

클라이언트는 Accept 관련 헤더를 통해 서버에게 자신의 선호와 능력을 알려줄 수 있다. 무엇을 원하고, 무엇을 할 수 있는지, 무엇을 원치 않는지 등

헤더설명
Accept보내도 되는 미디어 종류
Accept-Charset보내도 되는 문자 집합
Accept-Encoding보내도 되는 인코딩
Accept-Language보내도 되는 언어
TE보내도 되는 확장 전송 코딩

TE: Tranfer Encoding

조건부 요청 헤더

클라이언트가 요청에 제약을 걸 수 있다.

헤더
Expect
If-Match
If-Modified-Since
If-None-Match
If-Range
If-Unmodified-Since
Range

요청 보안 헤더

요청을 위한 간단한 인증요구/응답 체계.

헤더설명
Authorization인증 그 자체에 대한 정보.
Cookie토큰을 전달할 때 사용. 보안에 영향을 줄 수 있다.
Cookie2지원하는 쿠키의 버전을 알려줄 때 사용

프락시 요청 헤더

프락시가 점점 흔해지면서 그들의 기능을 돕기 위해 몇몇 헤더들이 정의 됨.

Max-Forwards, Proxy-Authorization, Proxy-Connection 등이 있다.

응답 헤더

응답 메시지는 클라이언트에게 정보를 제공하기 위한 자신만의 헤더를 가지고 있다.
어떤 종류의 서버와 대화하는지 등

클라이언트가 응답을 잘 다룰 수 있도록 한다.

Age, Public, Retry-After, Server, Title, Warning 등이 있다.

협상헤더

여러 언어로 HTML 문서를 제공해준다면 어떤 것을 선택할 것인지 협상할 수 있도록 도와준다.

Accept-Range, Vary 등이 있다.

응답 보안 헤더

기본적으로 Proxy-Authenticated, Set-Cookie, Set-Cookie2, WWW-Authenticate 등이 있다.

엔티티 헤더

엔티티 본문에 대한 헤더를 말한다. Content-Type 헤더 등
메시지에는 엔티티에 대해 설명하는 헤더들이 많다. 요청과 응답 양쪽 모두 엔티티를 포함할 수 있기 때문에, 양 타입의 메시지에 모두 나타날 수 있다.

엔티티 헤더는 엔티티, 개체의 타입, 주어진 리소스에 대해 요청할 수 있는 유효한 메서드 등 광범위한 정보를 제공한다.

Allow, Location 등 엔티티에 대해 수행될 수 있는 메서드와 리소스에 대한 URL을 알려준다.

콘텐츠 헤더

엔티티의 콘텐츠에 대한 구체적인 정보를 제공한다.
Content-??? 형식으로 되어있어 본문 콘텐츠에 대해 설명한다.

엔티티 캐싱 헤더

리소스에 대해 사본이 아직 유효한지에 대한 정보, 캐시된 리소스가 유효하지 않게 되는 시점을 추정하기 위한 단서 등이 있다.

ETag, Expires, Last-Modified 등이 있다.

확장 헤더

애플리케이션 개발자들이 만들었지만 아직 승인된 HTTP 명세에는 추가되지 않은 비표준 헤더

HTTP 메시지

profile
3대 500을 향해서

0개의 댓글