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

DARTZ·2022년 7월 31일
0

HTTP 완벽 가이드

목록 보기
9/11

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

HTTP 메시지를 인터넷 운송 시스템의 컨테이너라고 생각한다면, HTTP 엔터티는 메시지의 실질적인 화물이다. HTTP/1.1은 다음과 같이 10가지 주요 엔터티 헤더 필드를 정의하였다.

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

1) 엔터티 본문

엔터티 본문은 가공되지 않은 데이터만을 담고 있다. 다른 정보들은 모두 헤더에 담겨 있다.

엔터티 본문은 헤더 필드의 끝을 의미하는 빈 CRLF(줄바꿈을 입력하는 문자를 칭하는 표현) 줄 바로 다음부터 시작한다. 콘텐츠가 텍스트든 바이너리든, 문서든 이미지든, 압축되었든 안 되었든, 영어든 프랑스어든 일본어든 상관없이 항상 CRLF 바로 다음에 위치한다.

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

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

1) 잘림 검출

클라이언트는 메시지 잘림을 검출하기 위해 Content-Length를 필요로 한다. 메시지 잘림은 캐싱 프락시 서버에서 특히 취약하다. 잘린 메시지를 캐시하는 위험을 줄이기 위해, 캐싱 프락시 서버는 명시적으로 Content-Length 헤더를 갖고 있지 않은 HTTP 분문은 보통 캐시하지 않는다.

2) 잘못된 Content-Length

Content-Length가 잘못된 값을 담고 있을 경우 아예 빠진 것보다도 큰 피해를 유발할 수 있다.

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

Content-Length는 지속 커넥션을 위해 필수다. Content-Length헤더는 클라이언트에게 메시지 하나가 어디서 끝나고 다음 시작은 어디인지 알려준다.

4) 콘텐츠 인코딩

HTTP는 보안을 강화하거나 압축을 통해 공간을 절약할 수 있도록, 엔터티 본문을 인코딩할 수 있게 해준다.

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

엔터티 본문의 길이와 끝나는 위치를 바르게 판별하는 상황별 규칙들이다.
이 규칙들은 반드시 다음에 나열된 순서대로 적용도히어야 한다.

  1. 본문을 갖는 것이 허용되지 않는 특정 타입의 HTTP 메시지에서는, 본문 계산을 위한 Content-Length 헤더가 무시된다.

  2. 메시지가 Transfer-Encoding 헤더를 포함하고 있다면, 메시지가 커넥션이 닫혀서 먼저 끝나지 않는 이상 엔터티는 '0 바이트 청크'라 불리는 특별한 패턴으로 끝나야 한다.

  3. 메시지가 Content-Length 헤더를 갖는다면 Transfer-Encoding 헤더가 존재하지 않는 이상 Content-Length값은 본문의 길이를 담게 된다.

  4. 메시지가 'multipart/byteranges' 미디어 타입을 사용하고 엔터티 길이가 별도로 정의되지 않았다면, 멀티파트 메시지의 각 부분은 각자가 스스로의 크기를 정의할 것이다.

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

  6. HTTP/1.0 애플리케이션과의 호환을 위해, 엔터티 본문을 갖고 있는 HTTP/1.1요청은 반드시 유효한 Content-Length 헤더도 갖고 있어야 한다.

3. 엔터티 요약

HTTP가 일반적으로 TCP/IP와 같이 신뢰할 만한 전송 프로토콜 위에서 구현됨에도 불구하고, 불완전한 트랜스코딩 프락시나 버그 많은 중개자 프락시를 비롯한 여러가지 이유로 메시지의 일부분이 전송 중에 변형되는 일이 일어난다. 엔터티 본문 데이터에 대한 의도하지 않은 변경을 감지하기 위해, 최초 엔터티가 생성될 때 송신자는 데이터에 대한 체크섬을 생성할 수 있으며, 수신자는 모든 의도하지 않은 엔터티의 변경을 잡아내기 위해 그 체크섬으로 기본적인 검사를 할 수 있다.

4. 미디어 타입과 차셋

Content-Type 헤더 필드는 엔터티 본문의 MIME 타입을 기술한다. MIME 타입은 전달되는 데이터 매체의 기저 형식의 표준화된 이름이다. 클라이언트 애플리케이션은 콘텐츠를 적절히 해독하고 처리하기 위해 MIME 타입을 이용한다.

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

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

Content-Type 헤더는 내용 유형을 더 자세히 지정하기 위한 선택적인 매개변수도 지원한다. 엔터티의 비트 집합을 텍스트 파일의 글자들로 변환하기 위한 'charset' 매개변수가 그 대표적인 예이다.

2) 멀티파트 미디어 타입

MIME "멀티파트" 이메일 메시지는 서로 붙어있는 여러 개의 메시지를 포함하며, 하나의 복합 메시지로 보내진다.

3) 멀티파트 폼 제출

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

4) 멀티파트 범위 응답

범위 요청에 대한 HTTP 응답 또한 멀티파트가 될 수도 있다.

5. 콘텐츠 인코딩 과정

1) 콘텐츠 인코딩 과정

콘텐츠 인코딩 과정은 다음과 같다.

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

  2. 콘텐츠 인코딩 서버가 인코딩된 메시지를 생성한다.

  3. 수신 측 프로그램은 인코딩된 메시지를 받아서 디코딩하고 원본을 얻는다.

2) 콘텐츠 인코딩 유형

HTTP는 몇 가지 표준 콘텐츠 인코딩 유형을 정의하고 확장 인코딩으로 인코딩을 추가하는 것도 허용한다.

3) Accept-Encoding 헤더

서버에서 클라이언트가 지원하지 않는 인코딩을 사용하는 것을 막기 위해, 클라이언트는 자신이 지원하는 인코딩 목록을 Accept-Encoding 요청 헤더를 통해 전달한다.

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

콘텐츠 인코딩은 콘텐츠 포맷과 긴밀하게 연관되어 있다. 예를 들어 텍스트 파일은 흔히 gzip으로 압축하지만 jpeg파일은 그렇게 하지 않는다. 왜냐하면 jpeg는 gzip으로 잘 압축되지 않기 때문이다.

전송 인코딩 또한 엔터티 본문에 적용되는 가역적 변환이지만, 그들은 구조적인 이유 때문에 적용되는 것이며 콘텐츠의 포맷과는 독립적이다.

1) 안전한 전송

역사적으로, 전송 인코딩은 다른 프로토콜에서도 네트워크를 통한 '안전한 전송'을 위해 존재했다.

HTTP에서 전송된 메시지의 본문이 문제를 일으킬 수 있는 이유는 몇 가지 밖에 없다. 두가지를 예를 들면

  • 알수 없는 크기

  • 보안

2) Transfer-Encoding 헤더

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

  • Transfer-Encoding
    안전한 전송을 위해 어떤 인코딩이 메시지에 적용되었는지 수신자에게 알려준다.

  • TE
    어떤 확장된 전송 인코딩을 사용할 수 있는지 서버에게 알려주기 위해 요청 헤더에 사용한다.

3) 청크 인코딩

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

청크 인코딩이 전송 인코딩의 한 형태이며 따라서 본문이 아닌 메시지의 속성임을 주목해야한다. 멀티파트 인코딩은 본문의 속성이며 청크 인코딩과는 완전히 분리되어 있다.

청크와 지속 커넥션

클라이언트와 서버 사이의 커넥션이 지속적이지 않다면, 클라이언트는 자신이 읽고 있는 본문의 크기를 알 필요가 없다. 청크 인코딩은 서버가 본문을 여러 청크로 쪼개 보낼 수 있게 해줌으로써 이 딜레마에 대한 해법을 제공한다.

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

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

  • 클라이언트의 TE 헤더가 트레일러를 받아들일 수 있음을 나타내고 있는 경우

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

4) 콘텐츠와 전송 인코딩의 조합

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

5) 전송 인코딩 규칙

전송 인코딩이 메시지 본문에 적용될 때, 몇 가지 규칙이 반드시 적용되어야 한다.

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

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

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

이 규칙은 수신자가 메시지의 전송 길이를 알아낼 수 있게 해준다.

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

HTTP 프로토콜은 어떤 특정한 종류의 요청이나 응답을 다루는 방법들을 정의하는데, 이것은 인스턴스 조작이라 불리며 객체의 인스턴스에 작용한다. 이들 중 대표적인 두 가지가 범위 요청과 델타 인코딩이다.

8. 검사기와 신선도

1) 신선도

서버는 클라이언트에게 얼마나 오랫동안 콘텐츠를 캐시하고 그것이 신선하다고 가정할 수 있는지에 대한 정보를 줄 것이다. 서버는 Expires나 Cache-Control 헤더를 통해 이러한 정보를 제공할 수 있다.

2) 조건부 요청과 검사기

캐시의 사본이 요청되었을 때, 그것이 더 이상 신선하지 않다면 캐시는 자신이 갖고 있는 사본을 신선한 것으로 만들 필요가 있다. 만약 서버의 문서가 캐시가 갖고 있는 것과 같음에도 불구하고 항상 그 문서를 가져온다면 캐시는 네트워크 대역폭을 낭비하고, 캐시와 서버에 불필요한 부하를 주고, 모든 것을 느려지게 만들게 된다.

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

9. 범위 요청

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

모든 서버가 범위 요청을 받아들일 수 있는 것은 아니지만 많은 경우 가능하다.

10. 델타 인코딩

새 페이지 전체를 보내는 대신, 페이지에 대한 클라이언트의 사본에 대해 변경된 부분만을 서버가 보낸다면 클라이언트는 더 빨리 페이지를 얻을 수 있을 것이다. 델타 인코딩은 객체 전체가 아닌 변경된 부분에 대해서만 통신하여 전송량을 최적화하는, HTTP 프로토콜의 확장이다.

profile
사람들이 비용을 지불하고 사용할 만큼 가치를 주는 서비스를 만들고 싶습니다.

0개의 댓글