[HTTP 완벽 가이드 15장] 엔터티와 인코딩
HTTP는 콘텐츠를 나르기 위한 잘 라벨링 된 엔터티를 사용한다.
이 장에서는 엔터티 및 그와 연관된 엔터티 헤더들과 그들이 웹상의 화물을 수송하기 위해 어떤 일을 하는지에 대해 논의한다.
이 장에서 다루는 것
- HTTP 데이터를 담는 컨테이너인 HTTP 메시지 엔터티의 포맷과 동작방식
- 어떻게 HTTP까 엔터티 본문의 크기를 기술하며, 크기를 측정하기 위해 HTTP가 무엇을 요구하는지
- 클라이언트가 콘텐츠를 바르게 처리할 수 있도록 제공되는 엔터티 헤더들(콘텐츠의 포맷, 문자, 언어를 기술하기 위해 사용된다)
- 공간을 적게 차지하고 더 안전하게 만들기 위해 발송자가 콘텐츠 데이터 포맷을 변형할 때 사용하는, 디코딩 가능한 콘텐츠 인코딩
- 클라이언트가 요청한 콘텐츠의 최신 버전을 가져올 수 있도록 도와주는 태그, 라벨, 시간, 체크섬의 모음
- 콘텐츠의 버전 번호처럼 동작하는 검사기들(웹 애플리케이션에게 그들이 최신 콘텐츠를 가지고 있음을 확신할 수 있게 해준다). 그리고 객체를 최신으로 유지하기 위해 설계된 HTTP 헤더 필드들
- 중단되었던 다운로드를 중단된 지점에서부터 재개하고자 할 때 유용한 범위 요청
- 클라이언트가 전에 본 적이 있었던 웹 페이지를 다시 볼 때, 그때 이후로 변경이 있는 부분만 요청할 수 있게 해주는 HTTP 델터 인코딩 확장
- 엔터티 콘텐츠가 프락시를 지나는 과정에서 변경된 곳이 있지 않은지 탐지하기 위해 사용하는, 엔터티 본문의 체크섬
15.1 메시지는 컨테이너, 엔터티는 화물
- HTTP 메시지를 인터넷 운송 시스템의 컨테이너라고 생각한다면, HTTP 엔터티는 메시지의 실질적인 화물이다.
- HTTP/1.1이 정의한 10가지 주요 엔터티 헤더 필드
Content-Type
- 엔터티에 의해 전달된 객체의 종류
Content-Length
- 전달되는 메시지의 길이나 크기
Content-Language
- 전달되는 객체와 가장 잘 대응되는 자연어
Content-Encoding
- 객체 데이터에 대해 행해진 변형(압축 등)
Content-Range
- 만약 이 엔터티가 부분 엔터티라면, 이 헤더는 이 엔터티가 전체에서 어느 부분에 해당하는지 정의한다.
Content-MD5
- 엔터티 본문의 콘텐츠에 대한 체크섬
Last-Modified
- 서버에서 이 콘텐츠가 생성 혹은 수정된 날
Expires
- 이 엔터티 데이터가 더 이상 신선하지 않은 것으로 간주되기 시작하는 날짜와 시각
Allow
- 이 리소스에 대해 어떤 메서드가 허용되는지. 예) GET과 HEAD
ETag
- 이 인스턴스에 대한 고유한 검사기. 엄밀히 말해 ETag 헤더는 엔터티 헤더로 정의되어 있지는 않지만 엔터티와 관련된 많은 동작을 위해 중요한 헤더이다.
Cache-Control
- 어떻게 이 문서가 캐시될 수 있는지에 대한 지시자. ETag 헤더와 마찬가지로 Cache-Control 헤더도 엔터티 헤더로 정의되어 있지는 않다.
1) 엔터티 본문
- 엔터티 본문은 가공되지 않은 데이터만을 담고 있기 때문에 엔터티 헤더는 그 데이터의 이미에 대해 설명할 필요가 있다.
- Content-Type 헤더는 그 데이터를 어떻게 해석해야 하는지, Content-Encoding 헤더는 그 데이터가 압축 되었거나 추가적인 인코딩이 되었는지 말해준다.
15.2 Content-Length: 엔터티의 길이
- Content-Length 헤더는 메시지의 엔터티 본문의 크기를 바이트 단위로 나타낸다.
- 메시지를 청크 인코딩으로 전송하지 않는 이상, 엔터티 본문을 포함한 메시지에서는 필수적으로 있어야 한다.
- 서버 충돌로 인해 메시지가 잘렸는지 감지하고자 할 때와 지속 커넥션을 공유하는 메시지를 올바르게 분할하고자 할 때 필요하다.
1) 잘림 검출
- Content-Length가 없다면 클라이언트는 커넥션이 정상적으로 닫힌 것인지 메시지 전송 중에 서버에 충돌이 발생한 것인지 구별하지 못한다.
- 클라이언트는 메시지 잘림을 검출하기 위해 Content-Length를 필요로 한다.
2) Content-Length와 지속 커넥션
- 응답이 지속 커넥션을 통해서 온 것이라면, HTTP 응답이 즉시 그 뒤를 이을 것이다.
- Content-Length 헤더는 클라이언트에게 메시지 하나가 어디서 끝나고 다음 시작은 어디인지 알려준다.
3) 콘텐츠 인코딩
- HTTP는 보안을 강화하거나 압축하기 위해 본문을 인코딩하는데, 콘텐츠가 인코딩되어 있다면 Content-Length는 인코딩된 본문의 길이를 바이트 단위로 정의한다.
4) 엔터티 본문 길이 판별을 위한 규칙
- 본문을 갖는 것이 허용되지 않는 특정 타입의 HTTP 메시지에서는, 본문 계산을 위한 Content-Length 헤더가 무시된다. 이 경우 Content-Length 헤더는 부가정보에 불가하며, 실제 본문 길이를 서술하지 않는다.
- 메시지가 Transfer-Encoding 헤더를 포함하고 있다면, 메시지가 커넥션이 닫혀서 먼저 끝나지 않는 이상 엔터티는 '0바이트 청크'라 불리는 특별한 패턴으로 끝나야 한다.
- 메시지가 Content-Length 헤더를 갖는다면(그리고 메시지 유형이 엔터티 본문을 허용한다면), Transfer-Encoding 헤더가 존재하지 않는 이상 Content-Length 값은 본문의 길이를 담게 된다. 만약 Transfer-Encoding 헤더 필드가 있다면 Content-Length 헤더는 무시해야 한다.
- 메시지가 'multipart/byteranges' 미디어 타입을 사용하고 엔터티 길이가 별도로 정의되지 않았다면(Content-Length 헤더로), 멀티파트 메시지의 각 부분은 각자 스스로의 크기를 정의할 것이다.
15.3 엔터티 요약
- 엔터티 본문 데이터 변경을 감지하기 위해, 최초 엔터티가 생성될 때 송신자는 데이터에 대한 체크섬을 생성할 수 있으며 수신자는 엔터티 변경을 잡아내기 위해 체크섬으로 기본적인 검사를 할 수 있다.
15.4 미디어 타입과 차셋(Charset)
- Content-Type 헤더 필드는 엔터티 본문의 MIME 타입을 기술한다.
- Content-Type의 값은 인터넷 할당 번호 관리기관에 등록된 표준화된 MIME 타입이다. MIME 타입은 주 미디어 타입(텍스트, 이미지, 오디오 등)으로 시작해서 뒤이어 빗금(/), 그리고 미디어 타입을 더 구체적으로 서술하는 부 타입으로 구성된다.
미디어 타입 | 설명 |
---|---|
text/html | HTML 문서 |
text/plain | 플레인 텍스트 문서 |
image/gif | GIF 이미지 |
image/jpeg | JPEG 이미지 |
audio/x-wav | WAV 음향 데이터를 포함 |
model/vrml | 삼차원 VRML 모델 |
application/vnd.ms-powerpoint | 마이크로소프트 파워포인트 프레젠테이션 |
mulipart/byteranges | 여러 부분으로 나뉘는데, 각 부분은 전체 문서의 특정 범위를 담고 있다. |
message/http | 완전한 HTTP 메시지 |
1) 텍스트 매체를 위한 문자 인코딩
- Content-Type 헤더는 내용 유형을 더 자세히 지정하기 위한 선택적인 매개변수도 지원한다.
- 엔터티의 비트 집합을 텍스트 파일의 글자들로 변환하기 위한 'charset' 매개변수가 대표적인 예이다.
Content-Type: text/html; charset=utf-8
2) 멀티파트 미디어 타입
- MIME '멀티파트' 이메일 메시지는 서로 붙어있는 여러 개의 메시지를 포함하며, 하나의 복합 메시지로 보내진다.
- HTTP는 멀티파트 본문도 지원한다. 그러나 일반적으로는 폼을 채워서ㅑ 제출할 때와 문서의 일부분을 실어 나르는 범위 응답을 할 때의 두 가지 경우에만 사용된다.
15.5 콘텐츠 인코딩
- HTTP 애플리케이션은 콘텐츠를 보내기 전에 인코딩 할 수 있다.
- 큰 HTML 문서를 전송하기 전 압축하거나 콘쳉츠를 암호화하여 보낸다.
1) 콘텐츠 인코딩 과정
- 웹 서버가 원본 Content-Type과 Content-Length 헤더를 수반한 원본 응답 메시지를 생성한다.
- 콘텐츠 인코딩 서버(원 서버 또는 다운스트림 프락시)가 인코딩 된 메시지를 생성한다. 인코딩 된 메시지는 Content-Type은 같지만 Content-Length는 다르다. 콘텐츠 인코딩 서버는 Content-Encoding 헤더를 인코딩 된 메시지에 추가하여 수신 측 애플리케이션이 디코딩 할 수 있도록 도와준다.
- 수신 측 애플리케이션은 인코딩 된 메시지를 받아서 디코딩 후 원본을 얻는다.
eg. Content-Encoding: gzip
Gzip 콘텐츠 인코더를 통해 인코딩 된 원본을 Gzip 콘텐츠 디코더를 통해 디코딩 하여 원본을 얻는다.
2) 콘텐츠 인코딩 유형
- HTTP는 몇 가지 표준 콘텐츠 인코딩 유형을 정의하고 확장 인코딩으로 인코딩을 추가하는 것도 허용한다.
- Content-Encoding 헤더는 표준화된 토큰 값을 이용해서, 인코딩에 사용된 알고리즘들에 대해 기술한다.
콘텐츠 인코딩 값 | 설명 |
---|---|
gzip | 엔터티에 GNU zip 인코딩이 적용되었음을 의미 |
compress | 엔터티에 대해 유닉스 파일 압축 프로그램인 'compress'가 실행었엇음을 의미 |
deflate | 엔터티가 zlib 포맷으로 압축되었음을 의미 |
identity | 엔터티에 어떤 인코딩도 수행되지 않았음을 의미 (Content-Encoding 헤더가 없을 경우 이 값) |
- gzip, compress, deflate 인코딩은 전송되는 메시지의 크기를 정보의 손실 없이 줄이기 위한 무손실 압축 알고리즘
- gzip이 가장 효율적이고 많이 사용됨
3) Accept-Encoding 헤더
- 서버에서 클라이언트가 지원하지 않는 인코딩을 사용하는 것을 막기 위해, 클라이언트는 자신이 지원하는 인코딩 목록을 Accept-Encoding 요청 헤더를 통해 전달한다.
- Accept-Encoding 헤더를 전달하지 않는다면 서버는 클라이언트가 어떤 인코딩이든 받아들일 수 있다고 간주한다. (= Accept-Encoding: *)
Accept-Encoding 헤더의 몇 가지 예
- Accept-Encoding: compress, gzip
- Accept-Encoding:
- Accept-Encoding: *
- Accept-Encoding: compress;q=0.5, gzip;q=1.0
- Accept-Encoding: gzip;q=1.0, identity;q=0.5, *;q=0
- 클라이언트는 각 인코딩에 Q(quality) 값을 매개변수로 더해 선호도를 나타낼 수 있다. (min: 0.0 ~ max:1.0)
15.6 전송 인코딩과 청크 인코딩
- 이전 절에서는
메시지 본문에 적용
된 가역적 변환인 콘텐츠 인코딩은콘텐츠 포맷
과 긴밀하게 연관되어 있다. - 예를 들어 텍스트 파일은 흔히 gzip으로 압축하지만 JPEG 파일은 gzip으로 잘 압축되지 않기 때문에 사용하지 않는다.
- 이 절에서는
전송 인코딩
에 대해 논의하는데, 전송 인코딩 또한 엔터티 본문에 적용되는 가역적 변환이지만, 그들은구조적인 이유 때문에 적용되는 것
이며 콘텐츠의 포맷과는 독립적이다. - 메시지 데이터가 네트워크를 통해
전송되는 방법
을 바꾸기 위해 전송 인코딩을 메시지에 적용할 수 있다. 콘텐츠 인코딩
된 메시지는 단지 엔터티 부분만 인코딩전송 인코딩
된 메시지는 전체 메시지를 인코딩하여 메시지 자체의 구조를 바꿈
1) 안전한 전송
- 역사적으로,
전송 인코딩
은 다른 프로토콜에서도 네트워크를 통한'안전한 전송'
을 위해 존재했다. - 표준화 된 전송 기반을 갖춘 HTTP는 '안전한 전송'의 초점을 다른 데에 맞추고 있다.
- HTTP에서 전송된
메시지의 본문
이문제
를 일으킬 수 있는 두 가지
알 수 없는 크기
- 몇몇
게이트웨이 애플리케이션
과콘텐츠 인코더
는 콘텐츠를 먼저 생성하지 않고서는메시지 본문
의최종 크기
를 판단할 수 없다. - 이 서버들은 그 사이즈를 알기 전에
데이터의 전송
을시작
하려고 한다. HTTP
는 데이터에 앞서Content-Length 헤더를 요구
하기 때문에, 몇몇 서버는데이터의 끝
을 알리는 특별한종결 꼬리말
을 포함시켜전송 인코딩
으로 데이터를 보내려 시도한다.
보안
공용 전송 네트워크
로 메시지 콘텐츠를 보내기 전에전송 인코딩
을 사용해 알아보기 어렵게 뒤섞는 방법도 있지만SSL 같은 전송 계층 보안 방식
을 주로사용
한다.
2) Tranfer-Encoding 헤더
전송 인코딩
을제어
하고서술
하기 위해 정의된 헤더 두 가지
Transfer-Encoding
- 안전한 전송을 위해
어떤 인코딩
이메시지에 적용
되었는지 수신자에게 알려준다.
TE
- 어떤
확장된 전송 인코딩
을 사용할 수 있는지서버
에게 알려주기 위해요청 헤더
에 사용 - Accept-Transfer-Encoding과 같은 의미이다.
TE 헤더 사용 예
GET /new_products.html HTTP/1.1
Host: www.joes-hardware.com
User-Agent: Mozilla/4.61
TE: trailers, chunked
[chunked-encoded 메시지와 메시지의 끝에 트레일러가 오는 것을 받아들일 수 있음을 서버에게 알려주기 위해 작성]
Transfer-Encoding 헤더 사용 예
HTTP/1.1 200 OK
Transfer-Encoding: chunked
Server: Apache/3.0
[이 기초 헤더 뒤에 메시지 구조가 변함]
3) 청크 인코딩
청크 인코딩
은 메시지를 일정 크기의 청크 여럿으로 쪼갠다. 서버는 각 청크를 순차적으로 보낸다.- 청크 인코딩을 이용하면
메시지
를 보내기 전에전체 크기
를 알 필요가 없어진다. - 청크 인코딩이 전송 인코딩의 한 형태이며
본문
이아닌
메시지
의속성
임에 주목해야 한다.
청크와 지속 커넥션
지속 커넥션
에서는 본문을쓰기 전
에 반드시Content-Length 헤더
에 본문의 길이를 담아서 보내줘야 한다.콘텐츠
가 서버에서동적으로 생성
되는 경우에는, 보내기 전에 본문의 길이를 알아내는 것이 불가능할 것이다.청크 인코딩
은서버
가 본문을여러 청크
로 쪼개 보낼 수 있게 해줌으로써 이것에 대한 해법을 제공한다.동적
으로 본문이생성
되면서, 서버는 그중일부를 버퍼
에 담은 뒤 그한 덩어리
를 그의 크기와 함께 보낼 수 있다.마지막 청크
는 본문의 끝을 의미하기 때문에 크기가 0이다.
청크 인코딩된 메시지의 트레일러
- 다음 중 하나 이상의 조건을 만족하면 청크 메시지에 트레일러를 추가할 수 있다.
클라이언트
의TE 헤더
가 트레일러를 받아들일 수 있음을 나타내는 경우- 트레일러가
응답을 만든 서버
에 의해 추가되었으며, 그트레일러의 콘텐츠
는 클라이언트가 이해하고 사용할 필요가 없는 선택적인 메타데이터이므로 클라이언트가 무시하고 버려도 되는 경우
트레일러
에는 본문의 콘텐츠가 먼저 생성되어야 한다거나 하는 등의 이유로메시지 시작 시점
에서는 그 값을 알 수 없는추가적인 헤더 필드
를 담을 수 있다.- 예로 Content-MD5 헤더가 있는데, Content-MD5 헤더는 문서가 생성되기 전에 그 문서의 MD5를 계산하기 어렵기 때문에 트레일러를 이용할 수 있다.
마지막 청크 다음
에 Trailer 헤더에 나열했던 헤더들이 온다.
Trailer 헤더에 담을 수 있는 Directives
- message framing headers: Transfer-Encoding, Content-Length
- routhing headers: Host
- request modifiers: Control-Cache, Max-Forwards, TF
- authentication headers: Authorization, Set-Cookie
- etc: Content-Encoding, Content-Type, Content-Range, Trailer(itself)
4) 콘텐츠 전송 인코딩의 조합
콘텐츠 인코딩
과전송 인코딩
은 동시에 사용될 수 있다.- 콘텐츠 인코딩을 사용해서 HTML 파일을 압축하고 그 청크 데이터를 전송 인코딩을 사용해서 전송
5) 전송 인코딩 규칙
- 전송 인코딩의 집합은 반드시 'chunked'를 포함해야 한다.
- 청크 전송 인코딩이 사용되었다면, 메시지 본문에 적용된 마지막 전송 인코딩이 존재해야 한다.
- 청크 전송 인코딩은 반드시 메시지 본문에 한 번 이상 적용되어야 한다.
15.7 시간에 따라 바뀌는 인스턴스
- 같은 URL의 리소스에 대해 시간에 따라 다른 인스턴스(객체)를 응답 받을 수 있다.
15.8 검사기와 신선도
- 클라이언트가 서버로부터 처음 받은 리소스를 캐시에 저장하는데, 만료되면 서버에게 최신 사본을 요구하고 서버는 둘을 비교 한 후 변경되었으면 새로 응답
1) 신선도
- 서버는 Expires와 Cache-Control 헤더를 통해 얼마나 콘텐츠를 캐시하고 있었는지, 그것이 신선하다고 할 수 있는지 정보를 제공한다.
2) 조건부 요청과 검사기
- 클라이언트가 같은 리소스에 한 번 이상 접근했을 때, 우선 현재 사본이 여전히 신선한지 판별
- 만약 그렇지 않다면, 클라이언트는 반드시 서버로부터 최신 버전을 얻어 와야 함
- 리소스가 변경되지 않은 상황에서 똑같은 사본을 다시 받아오는 상황을 피하기 위해, 클라이언트는 서버에 현재 사본을 유일하게 식별할 수 있는 검사기를 명시해서 조건부 요청을 보낼 수 있음
- 서버는 오직 클라이언트의 사본과 다를 때만 리소스의 사본을 보낼 것이다.
15.9 범위 요청
- HTTP 클라이언트는 받다가 실패한 엔터티를 일부 혹은 범위로 요청함으로써 다운로드를 중단된 시점에서 재개할 수 있다.
GET /bigfile.html HTTP/1.1
Host: www.joes-hardware.com
Range: bytes=4000-
User-Agent: Mozilla/4.61
[처음 4,000바이트 이후의 부분을 요청]
- 서버는 클라이언트에게 자신의 범위를 받아들일 수 있는지 응답에 Accpet-Ranges 헤더를 포함시켜 알려준다.
- 단위는 주로 바이트
HTTP/1.1 200 OK
Date: Fri........
Server: Apache/1.2.4
Accept-Ranges: bytes
- 클라이언트의 범위 요청은 오직 클라잉너트와 서버가 같은 버전의 문서를 갖고 있을 때만 의미가 있다.
15.10 델타 인코딩
- 만료된 웹 페이지에 대해 새 페이지 전체를 보내는 대신 변경된 부분만 서버가 보낸다면 클라이언트는더 빨리 페이지를 얻을 수 있다.