Study

[HTTP 완벽 가이드] 15장 : 엔터티와 인코딩

이웃비 2021. 1. 25. 16:27

이 장에서는 엔터티 및 그와 연관된 엔터티 헤더들과 그들이 웹상의 화물을 수송하기 위해 어떤 일을 하는지에 대해 논의한다.

 


 

1 . 메시지는 컨테이너,  엔터티는 화물

 

엔터티 본문은 가공되지 않은 날 데이터에 불과하기 때문에 엔터티 헤더는 그 데이터의 의미에 대해 설명할 필요가 있다. 

 

 10가지 주요 엔터티 헤더 필드 

  • Content-Type : 엔터티에 의해 전달된 객체의 종류
  • Content-Length : 전달되는 메시지의 길이나 크기
  • Content-Language : 전달되는 객체와 가장 잘 대응되는 자연어
  • Content-Encoding : 객체 데이터에 대해 행해진 변형(압축 등)
  • Content-Location : 요청 시점을 기준으로, 객체의 또 다른 위치
  • Content-Range : 만약 이 엔터티가 부분 엔터티라면, 이 헤더는 이 엔터티가 전체에서 어느 부분에 해당하는지 정의한다
  • Content-MD5 : 엔터티 본문의 콘텐츠에 대한 체크섬
  • Last-Modified : 서버에서 이 콘텐츠가 생성 혹은 수정된 날
  • Expires : 이 엔터티 데이터가 더 이상 신선하지 않은 것으로 간주되기 시작하는 날짜와 시각
  • Allow : 이 리소스에 대해 어떤 요청 메서드가 허용되는지
  • ETag : 이 인스턴스에 대한 고유한 검사기. 엔터티 헤더는 아지미나 엔터티와 관련된 많은 동작을 위해 중요한 헤더
  • Cache-Control : 어떻게 이 문서가 캐시될 수 있는지에 대한 지시자

 

 

2. Content-Length : 엔터티의 길이

 

Content-length 헤더는 메시지의 엔터티 본문의 크기를 바이트 단위로 나타낸다. 어떻게 인코딩 되었든 상관없이 크기를 표현할 수 있다.

 

2.1 잘림 검출

 

Content-Length가 없다면 클라이언트는 커넥션이 정상적으로 닫힌 것인지 메시지 전송 중에 서버에 충돌이 발생한 것인지 구분하지 못한다. 클라이언트는 메시지 잘림을 검출하기 위해 Content-Length를 필요로 한다잘린 메시지를 캐시하는 위험을 줄이기 위해, 캐싱 프락시 서버는 명시적으로 Content-Length 헤더를 갖고 있지 않은 HTTP본문은 보통 캐시하지 않는다

 

2.2 잘못된 Content-Length

 

공식적으로 HTTP/1.1 사용자 에이전트는 잘못된 길이를 받고 그 사실을 인지했을 때 사용자에게 알려주게 되어 있다.

 

2.3 Content-Length와 지속 커넥션(Persistent Connection)

 

Content-Length헤더는 클라이언트에게 메시지 하나가 어디서 끝나고 다음 시작은 어디인지 알려준다.

Content-Length헤더 없는 지속 커넥션을 만날 수 있는 상황이 하나 있다. 바로 청크 인코딩을 사용할 때다. 청코 인코딩은 데이터를 각각이 특정한 크기를 갖는 일련의 청크들로 쪼개어 보낸다. 만약 헤더가 생성되는 시점에서 엔터티 전체의 크기를 알 수 없다하더라도, 서버는 청크 인코딩을 이용해 엔터티를 잘 정의된 크기의 조각들로 전송할 수 있다.

 

2.4 콘텐츠 인코딩

 

만약 본문의 콘텐츠가 인코딩되어 있다면, Content-Length 헤더는 인코딩 되지 않은 원본의 길이가 아닌 인코딩된 본문의 길이를 바이트 단위로 정의한다.

 

2.5 엔터티 본문 길이 판별을 위한 규칙

 

  1. 본문을 갖는 것이 허용되지 않는 특정 타입의 HTTP 메시지에서는, 본문 계산을 위한 Content-Length가 무시된다. 이 경우 Content-Length헤더는 부가정보에 불과하며, 실제 본문 길이를 서술하지 않는다.

  2. 메시지가 Transfer-Encoding헤더를 포함하고 있다면, 메시지가 커넥션이 닫혀서 먼저 끝나지 않는 이상 엔터티는 '0바이트 청크'라 불리는 특별한 패턴으로 끝나야 한다.
  3. 만약 Content-Length헤더 필드와 identity가 아닌 Transfer-Encoding 헤더 필드를 갖고 있는 메시지를 받았다면 반드시 Content-Length헤더를 무시해야. 왜냐하면 전송 인코딩은 엔터티 본문을 표현하고 전송하는 방식을 바꿀 것이기 때문이다. 
  4. 메시지가 'multipart/byteranges' 미디어 타입을 사용하고 엔터티 길이가 별도로 전의되지 않았다면, 멀티파트 메시지의 각 부분은 각자가 스스로의 크기를 정의할 것이다
  5. 위의 어떤 규칙에도 해당되지 않는다면, 엔터티는 커넥션이 닫힐 때 끝난다.
  6. HTTP/1.1 애플리케이션과의 호환을 위해, 엔터티 본문을 갖고 있는 HTTP/1.1 요청은 반드시 유효한 Content-Length헤더도 갖고 있어야 한다.

 

3. 엔터티 요약

 

엔터티 본문데이터에 대한 의도하지 않은 변경을 감지하기 위해, 최초 엔터티가 생성될 때 송신자는 데이터에 대한 체크섬을 생성할 수 있으며, 수신자는 모든 의도하지 않은 엔터티의 변경을 잡아내기 위해 그 체크섬으로 기본적인 검사를 할 수 있다.

Content-MD5 헤더는 서버가 엔터티 본문에 MD5 알고리즘을 적용한 결과를 보내기 위해 사용된다. Content-MD5 헤더는, 콘텐츠 인코딩의 적용은 끝났지만 전송 인코딩은 아직 적용 하지 않은 엔터티 본문에 대한 MD5를 담고있다. 

 HTTP의 확장들은 IETF 초안으로 다른 요약 알고리즘들을 제안했다. 이 확장들은 클라이언트가 응답에 대해 기대하는 요약 유형를 정의할 수 있는 새로운 헤더인 Want-Digest를 제안했다. 이 헤더에 품질값을 이용해 여러 요약 알고리즘을 제안하고 각각에 대한 선호도를 지정할 수 있다.

 

4. 미디어 타입과 차셋(Charset)

 

Content-Type 헤더 필드는 엔터티 본문의 MIME타입을 기술한다. MIME타입은 전달되는 데이터 매체의 기저 형식의 표준화된 이름이다.

MIME 타입은 주 미디어 타입으로 시작해서 뒤이어 빗금(/), 그리고 미디어타입을 더 구체적으로 서술하는 부 타입(subtype)으로 구성된다.

Content-Type헤더가 원본 엔터티 본문의 미디어 타입을 명시한다는 것은 중요하다. 예를 들어 엔터티가 콘텐츠 인코딩을 거친 경우에도 Content-Type 헤더는 여전히 인코딩 전의 엔터티 본문 유형을 명시할 것이다.

 

4.1 텍스트 매체를 위한 문자 인코딩

 

엔터티의 비트 집합을 텍스트 파일의 글자들로 변환하기 위한 'charset'매개변수는 Content-Type헤더의 내용 유형을 더 자세히 지정한다

Content-Type: text/html; charset=iso-8859-4

 

4.2 멀티파트 미디어 타입

 

MIME "멀티파트" 이메일 메시지는 서로 붙어있는 여러 개의 메시지를 포함하며, 하나의 복합 메시지로 보내진다. 각 구성요소는 자족적으로 자신에 대해 서술하는 헤더를 포함한다.

 

4.3 멀티파트 폼 제출

 

HTTP 폼을 채워서 제출하면, 가변 길이 텍스트 필드와 업로드 될 객체는 각각 멀티파트 본문을 구성하는 하나의 파트가 되어 보내진다. 멀티파트 본문은 여러 다른 종류와 길이의 값으로 채워진 폼을 허용한다. 이때, boundary는 본문의 서로 다른 부분을 구분하기 위한 구분자로 쓰인다.

Content-Type: multipart/form-data; boundary=[abcdefgawfjdls]

 10가지 주요 엔터티 헤더 필드 

4.4 멀티파트 범위 응답 

 

범위 요청에 대한 HTTP응답 또한 멀티파트가 될 수 있다. 그러한 응답은 Content-Type: multipart/byteranges 헤더 및 각각 다른 범위를 담고 있는 멀티파트 본문이 함께 온다.

 

5. 콘텐츠 인코딩

 

5.1 콘텐츠 인코딩 과정

 

  1. 웹 서버가 원본 Content-Type과 Content-Length 헤더를 수반한 원본 응답 메시지를 생성한다
  2. 콘텐츠 인코딩 서버가 인코딩된 메시지를 생성한다. 콘텐츠 인코딩 서버는 Content-Encoding헤더를 인코딩된 메시지에 추가하여, 수신 측 애플리케이션이 그것을 디코딩할 수 있도록 한다.
  3. 수신 측 프로그램은 인코딩된 메시지를 받아서 디코딩하고 원본을 얻는다.

5.2 콘텐츠 인코딩 유형

콘텐츠 인코딩 토큰들

콘텐츠 인코딩 값 설명
gzip 엔터티에 GNU zip 인코딩이 적용되었음을 의미한다
compress 엔터티에 대해 유닉스 파일 압축 프로그램인 'compress'가 실행되었음을 의미한다
deflate 엔터티가 zlib 포맷으로 압축되었음을 의미한다
identity 엔터티에 어떤 인코딩도 수행되지 않았음을 의미한다. Content-Encoding 헤더가 존재하지 않는다면 이 값인 것으로 간주한다.

 

5.3 Accept-Encoding 헤더

 

서버에서 클라이언트가 지원하지 않는 인코딩을 사용하는 것을 막기 위해, 클라이언트는 자신이 지원하는 인코딩의 목록을 Accept-Encoding 요청 헤더를 통해 전달한다. 만약 HTTP 요청에 Accept-Encoding 헤더를 포함하지 않는다면, 서버는 클라이언트가 어떤 인코딩이든 받아들일 수 있는 것으로 간주한다.

클라이언트는 각 인코딩에 Q(quality)값을 매개변수로 더해 선호도를 나타낼 수 있다. 토큰 '*'은 '그 외 모두'를 의미한다. 

identity 인코딩 토큰은 오직 Accept-Encoding 헤더에만 존재할 수 있고 클라이언트에 의해 다른 콘텐츠 인코딩 알고리즘에 대한 상대적 선호도를 정의하는 데 이용할 수 있다.

 

6. 전송 인코딩과 청크 인코딩

이 절에서는 전송 인코딩에 대해 논의한다. 전송인코딩 또한 엔터티 본문에 적용되는 가역적 변환이지만, 그들은 구조적인 이유 때문에 적용되는 것이며 콘텐츠의 포맷과는 독립적이다. 메시지 데이터가 네트워크를 통해 전송되는 방법을 바꾸기 위해 전송 인코딩을 메시지에 적용할 수 있다.

예를들어, 콘텐츠 인코딩된 메시지는 만지 메시지의 엔터티 부분만 인코딩한다. 전송 인코딩된 메시지에서는, 인코딩은 전체 메시지에 대해 적용되어 메시지 자체의 구조를 바꾼다.

 

6.1 안전한 전송

역사적으로, 전송 인코딩은 다른 프로토콜에서도 네트워크를 통한 '안전한 전송' 을 위해 존재했다.  그러나 몇몇 게이트웨이 애플리케이션과 콘텐츠 인코더는 콘텐츠를 먼저 생성하지 않고서는 메시지 본문의 최종 크기를 판단할 수 없다.

또한 공용 전송 네트워크로 메시지 콘텐츠를 보내기 전에 전송 인코딩을 사용해 알아보기 어렵게 뒤섞어버리는 방법도 있다. 그러나 이미 SSL과 같은 유명한 전송 계층 보안 방식이 있기 때문에 전송 인코딩 보안은 흔하지 않다.

 

6.2 Transfer-Encoding 헤더

전송 인코딩을 제어하고 서술하기 위해 정의된 헤더는 단 두 개뿐이다.

  • Transfer-Encoding : 안전한 전송을 위해 어떤 인코딩이 메시지에 적용되었는지 수신자에게 알려준다
  • TE : 어떤 확장된 전송 인코딩을 사용할 수 있는지 서버에게 알려주기 위해 요청 헤더에 사용한다.

모든 전송 인코딩값은 대소문자가 구별된다. 최신 HTTP명세는 오직 하나의 전송 인코딩, 즉 청크 인코딩만을 정의했다.TE헤더는 Accept-Encoding 헤더와 마찬가지로 어떤 형태의 전송 인코딩을 선호하는지 표현하는 Q값을 가질 수 있다.

 

6.3 청크 인코딩

 

청크 인코딩은 메시지를 일정 크기의 청크 여럿으로 쪼갠다. 서버는 각 청크를 순차적으로 보낸다. 청크 인코딩을 이용하면 메시지를 보내기 전에 전체 크기를 알 필요가 없어진다.

 

 청크와 지속 커넥션 

지속 커넥션에서는, 본문을 쓰기 전에 반드시 Content-Length 헤더에 본문의 길이를 담아서 보내야 한다.청크 인코딩은 서버가 본문을 여러 청크로 쪼개 보낼 수 있게 해준다. 동적으로 본문이 생성되면서, 서버는 그 중 일부를 버퍼에 담은 뒤 그 한덩어리를 그의 크기와 함께 보낼 수 있다. 본문을 전부 보내고, 서버는 크기가 0인 청크로 본문이 끝났음을 알리고 다음 응답을 위해 커넥션을 열린 채로 유지할 수 있다.

 

 청크 인코딩된 메시지의 트레일러 

다음 중 하나 이상의 조건을 만족하면 청크 메시지에 트레일러를 추가할 수 있다.

  • 클라이언트의 TE헤더가 트레일러를 받아들일 수 있음을 나타내고 있는 경우
  • 트레일러가 응답을 만든 서버에 의해 추가되었으며, 그 트레일러의 콘텐츠는 클라이언트가 이해하고 사용할 필요가 없는 선택적인 메타데이터이므로 클라이언트가 무시하고 버려도 되는 경우

6.4 전송 인코딩 규칙 

  • 전송 인코딩의 집합은 반드시 'chunked'를 포함해야 한다. 유일한 예외는 메시지가 커넥션의 종료로 끝나는 경우뿐이다.

  • 청크 전송 인코딩이 사용되었다면, 메시지 본문에 적용된 마지막 전송 인코딩이 존재해야 한다.

  • 청크 전송 인코딩은 반드시 메시지 본문에 한 번 이상 적용되어야 한다.

 

7. 시간에 따라 바뀌는 인스턴스

HTTP 프로토콜은 어떤 특정한 종류의 요청이나 응답을 다루는 방법들을 정의하는데, 이것은 인스턴스 조작이라 불리며 객체의 인스턴스에 작용한다. 이들 중 대표적인 두 가지가 범위 요청과 델타 인코딩이다. 이들 모두가, 클라이언트가 자신이 갖고 있는 리소스의 사본이 서버가 갖고 있는 것과 정확히 같은지 판단하고. 상황에 따라서는 새 인스턴스를 요청 할 수 있는 능력을 가질 것을 요구한다.

 

8. 검사기와 신선도

 

8.1 신선도 

 서버는 Expires나 Cache-Control 헤더를 통해 이러한 정보를 제공할 수 있다.

Expires 헤더는 문서가 만료되어 더 이상 신선하다고 간주 할 수 없게 되는 정확한 날짜를 명시한다. Cache-Control 헤더는 서버와 클라이언트 양쪽에서, 더 많은 지시자들과 함께, 단지 수명이나 유효기간 뿐 아니라 신선도를 서술하기 위해 사용된다. 

 

8.2 조건부 요청과 검사기

 HTTP는 클라이언트에게 리소스가 바뀐 경우에만 사본을 요청하는 조건부 요청이라 불리는 특별한 요청을 할 수 있는 방법을 제공한다. 조건부 요청은 평범한 HTTP요청 메시지이지만, 특정 조건이 참일 때에만 수행된다.

조건부 요청은 'If-' 로 시작하는 조건부 헤더에 의해 구현된다. 각 조건부 요청은 특정 검사기 위에서 동작한다. 검사기는 문서의 테스트된 특정 속성이다. 개념적으로, 일련번호나 버전 번호 혹은 문서의 최종 변경일과 같은 검사기를 생각해 볼 수 있다.

 요약하면, 클라이언트가 같은 리소스에 한 번 이상 접근했을 때, 우선 현재 사본이 여전히 신선한지 판별한다. 만약 그렇지 않다면, 클라이언트는 반드시 서버로부터 최신 버전을 얻어와야 한다. 리소스가 변경되지 않은 상황에서 똑같은 사본을 다시 받아오는 상황을 피하기 위해서, 클라이언트는 서버에 현재 사본을 유일하게 식별할 수 있는 검사기를 명시해서 조건부 요청을 보낼 수 있다. 서버는 오직 클라이언트의 사본과 다를 때만 리소스의 사본을 보낼 것이다. 

 

 

9. 범위 요청

 범위 요청을 이용하면, HTTP 클라이언트는 받다가 실패한 엔터티를 일부 혹은 범위로 요청함으로써 다운로드를 중단된 시점에서 재개할 수 있다.

클라이언트가 하나의 요청으로 여러 범위를 요청했을 때, 응답은 멀티파트 본문과 Content-Type: multipart/byteranges 헤더와 함께 하나의 엔터티로 돌아온다.

 Range헤더는 피어 투 피어 파일 공유 클라이언트가 멀티미디어 파일의 다른 부분을 여러 다른 피어로부터 동시에 다운받을 때도 널리 사용된다.

10. 델타 인코딩

델타 인코딩은 객체 전체가 아닌 변경된 부분에 대해서만 통신하여 전송량을 최적화하는, HTTP 프로토콜의 확장이다. 

 


출처 : 데이빗 골리 외 4인HTTP 완벽 가이드 :웹은 어떻게 동작하는가이응준 , 정상일 옮김, 인사이트, 2014