15. 엔터티와 인코딩

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

주요 엔터티 헤더 필드

헤더

설명

Content-Type

객체의 종류

Content-Length

메시지 길이

Content-Language

대응되는 자연어

Content-Encoding

압축 등 변형

객체의 또다른 위치

Content-Range

엔터티가 전체에서 어느 부분에 해당하는지

Content-MD5

본문에 대한 체크섬

Last-Modified

생성 혹은 수정된 날

Expires

엔터티가 유효하지 않기 시작하는 시

Allow

어떤 요청 메서드가 허용되는지 (ex. GET, HEAD)

엔터티 헤더로는 정의되어 있지 않으나, 중요한 것들

헤더

설명

Etag

인스턴스에 대한 고유 식별

Cache-Control

캐시되는 방법

15.1.1 엔터티 본문

  • 본문에는 데이터만 담고, 나머지 정보는 헤더에 담는다.

  • 헤더 필드의 끝을 의미하는 빈 CRLF 줄 바로 다음부터 시작한다.

15.2 Content-Length: 엔터티의 길이

  • 본문의 크기를 바이트 단위로 나타낸다.

  • 압축된 경우, 압축된 후의 크기를 나타낸다.

  • 청크 인코딩으로 전송될 경우 없어도 된다.

15.2.1 (Content-Length의 용도 1) 잘림 검출

  • 예전 HTTP에서는 커넥션이 닫히면 메시지가 끝난 것이라고 판단함.

  • 문제점: Content-Length가 없으면 커넥션이 정상적으로 닫힌 것인지, 서버에 문제가 생겨 전송이 끊긴 것인지 구분할 수 없음

  • 캐싱 프락시 서버: 메시지가 잘렸다는 것을 인식하지 못하면, 결함이 있는 콘텐츠를 계속해서 저장하고 제공할 수 있기 때문.

  • => 해결책: Content-Length가 없으면 보통 캐싱하지 않음

15.2.2 잘못된 Contnet-Length

몇몇 클라이언트, 서버, 프락시 등은 Content-Length가 잘못 계산되었을 때 이 사실을 알아내고 수정한다. HTTP/1.1 사용자 에이전트는 잘못된 길이를 받으면 사용자에게 알려주어야 한다.

15.2.3 (Content-Length의 용도 2) 지속 커넥션

커넥션이 지속적일 때는 Content-Length 헤더 없이 어디까지가 본문이고 어디부터가 다음 메시지인지 알 수 없다. 단, 청크 인코딩을 사용할 때는 Content-Length 없이 지속 커넥션을 사용할 수 있다.

15.2.4 인코딩된 Content-Length

보안, 압축 등 콘텐츠가 인코딩되어 있다면, (원본이 아닌) 인코딩된 본문의 길이를 Content-Length로 정의한다. HTTP/1.1 명세로는 원 본문의 길이를 알 수 없기 때문에, 클라이언트는 자신이 올바르게 디코딩했는지 검증할 수 없다.

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

  1. 본문을 갖지 않는(예: HEAD 응답) 메시지에서는 Content-Length 헤더가 무시된다.

  2. 메시지가 특정 종류의 Transfer-Encoding 헤더를 포함하고 있다면 Content-Length는 무시되고, 엔터티는 '0바이트 청크'로 끝나야 한다.

  3. 메시지가 multipart/byteranges 타입일 경우, 멀티파트 메시지의 각 부분이 스스로의 크기를 결정한다.

  4. 위의 규칙에 해당되지 않는다면 엔터티는 커넥션이 닫힐 때 끝난다.

  5. 본문을 갖고 있는 HTTP/1.1 요청은 Content-Length 헤더를 갖고 있어야 한다.

15.3 엔터티 요약

엔터티를 보낼 때 데이터에 대한 체크섬을 생성할 수 있다.

Content-MD5

  • 응답을 처음 만든 서버가 본문에 MD5 알고리즘을 적용한 결과

  • 콘텐츠 인코딩 적용 후, 전송 인코딩 적용 전

  • 프락시와 캐시는 그 헤더를 변경하거나 추가하지 않을 것

  • 그다지 자주 전송되지 않음 (...)

15.4 미디어 타입과 Charset

  • Content-Type: 엔터티 본문의 MIME 타입

  • 콘텐츠 인코딩 전 원문의 엔터티 본문 유형

  • 주 미디어 타입 + / + 부 타입의 구성

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

charset: 텍스트 파일에 대한 인코딩 (ex. charset=utf-8)

15.4.2 멀티파트 미디어 타입

  • 멀티파트 메시지: 여러 개의 메시지가 붙어서 하나의 메시지로 보내지는 것.

  • ex. 1) 폼 제출 2) 문서의 일부분에 대한 범위 응답

  • 각 파트는 자신에 대한 헤더를 포함한다.

15.4.3 멀티파트 폼 제출

본문의 서로 다른 부분을 구분하기 위해 구분자 boundary가 사용된다.

15.4.4 멀티파트 범위 응답

범위 요청에 대한 HTTP 응답에 대해, 각각 다른 범위를 담고 있는 멀티파트 본문이 함께 온다.

15.5 콘텐츠 인코딩

발송하는 쪽에서 콘텐츠에 적용하는 인코딩 방법들 1. 압축: 전송 시간을 줄임 2. 콘텐츠 암호화

15.5.1 콘텐츠 인코딩 과정

  1. 서버가 Content-Type과 Content-Length 헤더가 있는 원본 응답 메시지를 생성한다.

  2. 인코딩 서버(원 서버 or 다음 프락시)가 인코딩된 메시지를 생성한다. Content-Type은 변화하지 않고, Content-Length는 달라진다.

  3. 인코딩 서버는 Content-Encoding 헤더를 추가한다.

  4. 수신자는 인코딩된 메시지를 디코딩하고 원본을 얻는다.

15.5.2 콘텐츠 인코딩 유형

gzip이 일반적으로 쓰인다. 확장 인코딩을 추가할 수 있다.

15.5.3 Accept-Encoding 헤더

클라이언트가 자신이 지원하는 인코딩의 목록을 요청 헤더 Accept-Encoding을 통해 전달한다. 이 헤더가 포함되어 있지 않으면 클라이언트가 어떤 인코딩이든 받아들일 수 있는 것으로 간주된다. 각 인코딩에 q값(0.0 원치 않음 <-> 1.0 가장 선호함)으로 선호도를 나타낼 수 있다.

15.6 전송 인코딩과 청크 인코딩

  • 콘텐츠 인코딩: 콘텐츠 포맷과 연관, 엔터티 부분에만 적용됨

  • 전송 인코딩: 메시지가 네트워크를 통해 전송되는 방법만 바꿈, 전체 메시지에 적용됨

15.6.1 안전한 전송

전송 인코딩은 안전한 전송을 위해서 존재함.

HTTP에서 안전하지 않은 전송

알 수 없는 크기

  1. 동적으로 콘텐츠가 생성되는 경우, 메시지 본문의 최종 크기를 미리 판단할 수 없음

  2. 서버는 사이즈를 알기 전에 데이터 전송을 시작하려고 함

  3. HTTP는 데이터에 앞서 Content-Length 헤더를 요구함

  4. 서버는 전송 인코딩으로 데이터를 보내고 종결 꼬리말로 데이터의 끝을 알림

보안

공용 네트워크로 보낼 때 전송 인코딩을 사용해 알아보기 어렵게 뒤섞음

15.6.2 Transfer-Encoding 헤더

  • Transfer-Encoding: (응답에서) 어떤 인코딩이 적용되었는지 알려줌

  • TE: (요청에서) 어떤 전송 인코딩을 사용할 수 있는지 알려줌

cf. HTTP/2에서는 chunked transfer encoding 매커니즘을 아예 사용하지 않음. (reference)

15.6.3 청크 인코딩

  • 메시지를 일정 크기의 청크로 쪼갬

    • 주의: 메시지 본문 뿐만 아니라 메시지 전체의 속성임. (cf. 멀티파트 인코딩은 본문의 속성)

  • 본문이 동적으로 생성될 때, 청크 단위로 담아서 해당 청크의 크기와 함께 보냄

  • 메시지를 보내기 전 전체 크기를 알 필요가 없어짐

청크와 지속 커넥션

  • 지속 커넥션일지라도 Content-Length 없이 메시지를 보낼 수 있다.

  • 크기가 0인 청크로 본문이 끝났음을 알리고, 커넥션을 열린 채로 유지한다.

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

Content-MD5 등 트레일러를 보낼 수 있다. Trailer 헤더가 포함되어 있으면, 마지막 청크 다음에 Trailer 헤더에 나열했던 헤더들이 온다.

트레일러를 추가할 수 있는 경우

  1. 클라이언트가 TE에 트레일러를 받아들일 수 있다고 한 경우

  2. 트레일러가 클라이언트가 이해할 필요 없는 선택적인 메타데이터여서 무시하고 버려도 되는 경우

15.6.4 콘텐츠 인코딩과 전송 인코딩의 조합

콘텐츠 인코딩과 전송 인코딩이 동시에 사용될 수 있다.

15.6.5 전송 인코딩 규칙

  1. 전송 인코딩 집합에 반드시 chunked가 포함되어야 한다. (예외: 메시지가 커넥션 종료로 끝나는 경우)

  2. 청크 전송 인코딩은 전송 인코딩들 중에 가장 마지막으로 적용되어야 한다.

  3. 청크 전송 인코딩은 메시지 본문에 한 번만 적용되어야 한다.

전송 인코딩은 HTTP/1.1에서의 새로운 기능이므로, 비 HTTP/1.1에 전송 인코딩 메시지를 보내지 않도록 주의해야 한다.

15.7 시간에 따라 바뀌는 인스턴스

인스턴스 조작

특정한 종류의 요청이나 응답을 다루는 방법. 클라가 자신이 갖고 있는 사본이 서버가 갖고 있는 것과 정확히 같은지 판단하고, 새 인스턴스를 요청해야 한다.

인스턴스 조작의 종류

  1. 범위 요청

  2. 델타 인코딩

15.8 검사기와 신선도

조건부 요청: 클라이언트가 서버에게 자신이 갖고 있는 버전을 말해주고, 검사기로 자신의 버전이 더 이상 유효하지 않을 때만 새로운 사본을 보내달라고 요청하는 것

15.8.1 신선도

신선도: 클라이언트가 얼마나 오랫동안 콘텐츠를 캐시하고, 그것이 신선하다고 가정할 수 있는지에 대한 정보

  1. Expires: 정확한 날짜. 클라이언트와 서버의 시계가 동기화되어 있어야 해서 어려움.

  2. Cache-Control: 상대시간을 이용. 서버가 떠난 후로부터의 시간을 초단위로 정한다. 시계 동기화에 의존하지 않아서 더 정확하다.

ref. 7.9 캐시 제어 참고

15.8.2 조건부 요청과 검사기

리소스가 바뀐 경우에만 사본을 요청한다. 'If-'로 시작하는 조건부 헤더에 의해 구현된다.

  • 약한 검사기: 인스턴스가 고유하게 식별되지 않는 검사기 (ex. 바이트 단위의 크기, 최종 변경 시각)

  • 강한 검사기: 인스턴스를 고유하게 식별하는 검사기 (ex. MD5 체크섬, ETag)

cf. 때로는 검사기를 통과하지 못한 버전을 채택하기도 한다. (ex. 같은 내용을 겉모양만 바꾸는 경우) 서버는 태그 앞에 'W/'를 붙여 약한 엔터티 태그임을 알린다.

15.9 범위 요청

Range 헤더를 이용해 문서의 일부분이나 특정 범위만 요청한다.

  1. 처음 몇 바이트만 받고 실패했을 경우

    1. 여러 범위로 요청을 하고 싶은 경우 (ex. P2P)

=> 응답은 Content-Type: multipart/byteranges 헤더와 함께 하나의 엔터티로 돌아온다.

서버는 응답에 Accept-Range헤더를 포함시켜 자신이 범위 요청을 받아들일 수 있는지 알려준다.

15.10 델타 인코딩

객체 전체가 아닌, 변경된 부분에 대해서만 통신하는 HTTP 확장 전송량을 최적화하고, 전송 시간을 빠르게 한다.

  1. 클라이언트가 어떤 버전을 가지고 있는지, 델타를 적용하기 위해 어떤 알고리즘을 알고 있는지를 말해준다.

  2. 서버는 자신이 그 버전을 가지고 있는지, 그리고 어떻게 델타를 계산할 것인지를 확인한다.

  3. 서버는 델타를 클라이언트에 보내주고, 최신 버전에 대한 새 식별자를 명시한다.

  4. (클라이언트의) A-IM 헤더: 자신이 델타 응답을 받아들일 수 있음을 알림

15.10.1 인스턴스 조작, 델타 생성기, 델타 적용기

델타 인코딩의 단점

  1. 구현이 까다롭다.

  2. 서버가 사본의 모든 버전을 유지하고 있어야 한다. 디스크 공간이 더 많이 필요하다.

Last updated