이병록의 개발 블로그

HTTP/1.1 RFC 2616과 개정된 RFC 7230, 7231, 7232, 7233, 7234 차이점 정리 본문

RFC

HTTP/1.1 RFC 2616과 개정된 RFC 7230, 7231, 7232, 7233, 7234 차이점 정리

이병록 2020. 5. 18. 14:39

이 글 최종수정일 : 2020-08-05

 

개정된 점을 요약하면 아래와 같습니다.

1) 헤더의 분류가 좀 더 명확히 분류되고 설명하기 위해, ABNF가 바뀐 점

2) 개념을 좀 더 명확히 구체화 하기 위해 용어가 변경되며, ABNF가 바뀐 점

3) 그러므로 인해 ABNF가 바뀌고, 연결된 최신 문서를 따라가는 점

4) 개념 또는 내용이 없어지거나, 또는 명확해지는 점

 

 

쉽게 말해, 기존에는 개념이나 설명을 통째로 하나의 문서를 때려 박은 것을, 분리해서 좀 더 명확히 힘을 줘서 설명하는 것으로 볼 수 있습니다.

당연히 프로토콜 버전 업데이트가 아니기 때문에 성능향상보다는, 커뮤니케이션의 규칙을 좀 더 명확히 하려고 개정되었습니다.

 

 

 


 

RFC 7230, 7231, 7232, 7233, 7234 번역문서 링크

 

RFC 2616은 구글에서 번역 pdf를 찾아보시면 잘 되어있으므로 찾아보시면 됩니다.

다만, 시중에 나와있는 번역본과 현재 RFC 2616문서는 내용이 좀 다릅니다. 이미 원문보시고 번역본 보시는 분들은 금방 알아차리시겠지만 

기존 RFC 2616에서 변경된 부분이 있습니다. 그 부분은 원문과 번역본을 같이 보셔야 합니다.

가급적이면 원문으로..^^;;

 

 

RFC 7230 - HTTP/1.1 : Message Syntax and Routing - 번역
RFC 7231 - HTTP/1.1 : Semantics and Content - 번역
RFC 7232 - HTTP/1.1 : Conditional Requests - 번역
RFC 7233 - HTTP/1.1 : Range Requests - 번역

RFC 7234 - HTTP/1.1 : Caching - 번역

RFC 7235 - HTTP/1.1 : Authentication - 번역

 


 

첫 번째로

 

헤더의 분류가 좀 더 명확히 분류되는 부분입니다.

ABNF도 일반, 요청, 응답, 엔티티 헤더로 나눴으나 개정된 문서에서는 좀 더 간소화되었습니다.

그리고 헤더들을 한 표로 정리해봤습니다.

 

1. HTTP-message의 변경

 

1) RFC 2616

 

HTTP-message   = Request | Response

generic-message = start-line
                 *(message-header CRLF)
                 CRLF
                 [ message-body ]

Request       = Request-Line
                *(( general-header
                | request-header
                | entity-header ) CRLF)
                CRLF
                [ message-body ]

Response      = Status-Line
                *(( general-header
                | response-header
                | entity-header ) CRLF)
                CRLF
                [ message-body ]

 

2) RFC 7230

 

HTTP-message   = start-line
                 *( header-field CRLF )
                 CRLF
                 [ message-body ]

 

 

2. 헤더를 분류 해보기

 

RFC2616의 메세지 헤더를 RFC 7230, 7231 기준으로 분류해 봄

 

그리고 헤더가 제거되거나 사용용도에 따라 다른 카테고리로 이동되었습니다.

 

 

3. 제거된 헤더

 

Proxy-Connection (Request Header)

 

Content-Base (Entity Header)

 

Content-MD5 (Entity Header)

 

Public (Response Header)

 

 

 

4. 성격상 이동된 헤더

 

Cache-Control (General Header -> Request Header)

 

Date (General Header -> Response Header)

(다만, 클라이언트도 보낼 수 있으나 서버에 유용한 정보를 전달하는 것이 아닌 한, 그렇게 하지 않는다. ([RFC7231] Section 7.1.1.2)

 

 

Warning (General Header -> Response Header)

 

Pragma (General Header -> Request Header)

 

Allow (Entity Header -> Response Header)

 

Location (Entity Header -> Response Header)

 

Expires (Entity Header -> Response Header)

 

Last-Modifed (Entity Header -> Response Header)

 

ETag (Entity Header -> Response Header)

 

 

이동된 것들을 보면, 재미있는 부분이 있습니다.

General Header에서 Response Header로 성격이 옮겨진 Date 헤더 필드를 보면 실제로 사용할 때 요청 메시지에서 Date 헤더 필드가 굳이 필요하지 않았다는 것을 볼 수 있겠네요.

 

 

 

사실 카테고리를 특정하기가 사실 애매모호합니다. 이 헤더는 꼭 요청 헤더다, 응답 헤더다, 뭐다 하기가 쉽지 않은 듯합니다.

개인적으로 이번 개정 문서에서는 이 헤더는 좀 더 성격이 이런 부분이 있다 이런 느낌이 강했습니다.

 


 

두 번째로

 

용어가 변경되고, 문법이 바뀐 점

 

 

1. 메시지 헤더(message-header) - > 헤더 필드(header-field)로 변경된 것은 ABNF를 따라갑니다.

 

 

2. 엔티티라는 명칭에서 보다 Representation(표현)으로 변경되었습니다.(다만, 개념이 동일하지는 않음)

단순히 명칭만 바뀌었다기보다는 Representation(표현)도 더 자세하게 분리되었습니다.

 

 

1) RFC2616 (이전)

 

message-body = entity-body
              | <entity-body encoded as per Transfer-Encoding>

entity-body := Content-Encoding( Content-Type( data ) ) ; (Section 7.2.1)

entity-body = *OCTET

 

메세지 본문 = 엔티티 본문

엔티티 본문 = Content-Encoding( Content-Type( data ) ) ; (Section 7.2.1)

 

 

 

2) RFC 7230, RFC7231 (이후)

 

message-body = *OCTET

representation-data := Content-Encoding( Content-Type( bits ) ) ; (Section 3.2)

 

메세지 본문 = 페이로드 본문(표현 데이터가 제공)

표현 데이터 = Content-Encoding( Content-Type( bits ) )

 

표현의 의미는 두 가지를 포함한 것을 얘기합니다.

Representation(표현) = 표현 메타데이터(관련 header field) + 표현 데이터

 

 

 

3. 리소스와 내용이 정의되었습니다.([RFC7231 Section 2)

 

HTTP 요청의 대상은 “resource(이하 리소스)”라고 불린다. HTTP는 리소스의 특성을 제한하는 것이 아니라 단지 리소스와 상호작용하는 데 사용될 수 있는 인터페이스를 정의한다. 각 리소스는 [RFC7230]의 Section 2.7에서 설명한 대로 Uniform Resource Identifier(URI)로 식별된다.

 

 

4. “Effective Request URI”라는 용어가 도입되었습니다.

 

request-target이라는 ABNF와 “Effective Request URI(이하 유효한 요청 URI)라는 용어가 생김으로써, 단순

 

 

(1) RFC 2616

Request-Line   = Method SP Request-URI SP HTTP-Version CRLF ; RFC 2616 Section 5.1

Request-URI    = "*" | absoluteURI | abs_path | authority ; RFC 2616 Section 5.1.2

 

(2) RFC 7230

 

request-line   = method SP request-target SP HTTP-version CRLF ; RFC 7230 Section 3.1.1

request-target = origin-form                    ; RFC 7230 Section 5.3
               / absolute-form 
               / authority-form 
               / asterisk-form

 

 


 

세 번째로

최신 ABNF 문서를 따라가며, 의존된 다른 RFC문서를 따라가므로 대부분의 구문이 변경되었습니다.

처음에는 정리했었으나.. 음.. 엄청 많아서 이 부분은 정리해서 올리지 않기로 했습니다. 그냥 최신 문서를 새롭게 보는 것이 낫습니다..^^;;

 

 

 


 

네 번째로

여러 부분이 변경되거나 추가되거나 삭제되어서 정리가 실제로 쉽지 않았습니다.

그래서 카테고리를 나눠서 정리하기도 쉽지 않을 정도로 그냥 대부분이 바뀌었다고 보시면 됩니다.

모든 내용을 포함하고 있진 않으나,  줄줄이 작성해봤습니다.

 

 

1. HTTPS URI scheme 명세가 정의됨

 

1) RFC 2818 Section 2.4 

 

HTTP URIs에서 단순히 http에서 https로 사용되는 것을 얘기했으나

 

https://www.example.com/~smith/home.html

 

 

2) RFC 7230 Section 2.7.2 (정의됨)

 

RFC 7230에 들어서서 ABNF로 정의되었습니다.

 

https-URI = "https:" "//" authority path-abempty [ "?" query ] [ "#" fragment ]

 

 

2. method에 대한 ABNF 변경

 

문법이 굉장히 간소화되었습니다.

최초는 메서드를 문자로 지정한 후 확장 헤더에 대해서 고려했다면, RFC7230 들어와서는 모든 것을 열어버린 느낌입니다.

 

1) RFC2616 Section 5.1.1

 

Method         = "OPTIONS"
               | "GET"
               | "HEAD" 
               | "POST"    
               | "PUT"
               | "DELETE"
               | "TRACE" 
               | "CONNECT" 
               | extension-method

extension-method = token

 

 

2) RFC7230 Section 3.1.1

 

method = token

 

 

 

3. Header 관련 ABNF 변경 및 라인 폴딩 규칙 제거 (RFC 7230 Section 3.2)

 

헤더 필드는 단순히 필드 값만 나열하는 것으로 변경, 라인 폴딩 규칙 제거됨

 

 

(1) 개정 전

 

message-header = field-name ":" [ field-value ]

 

 

(2) 개정 후

 

header-field   = field-name ":" OWS field-value OWS

 

 

4. Transfer-Encoding에서 transfer-coding “identity” 토큰이 제거됨 ([RFC 7230] Section 4)

 

 

5. chunk-size에 대한 내용이 변경됨([RFC 7230] Section 4.1)

 

chunk-size를 계산함에 있어서, “chunk”에서 “chunk-data”로 변경됨에 따라 청크 헤더와 트레일러의 octet 수를 포함되지 않는다.

 

1) RFC 2616 Section 3.6.1 (이전)

 

The chunk-size field is a string of hex digits indicating the size of the chunk

 

 

2) RFC 7230 Section 4.1 (이후)

 

The chunk-size field is a string of hex digits indicating the size of the chunk-data in octets.

 

 

6. 영속적 커넥션에 대해 내용이 더 자세히 되고 변경되는 부분이 있습니다.

 

RFC 7230에 들어서서 “close” 커넥션 옵션을 언제 사용하는지 명확히 명세되었으며

그 외, 요청 재시도, 커넥션 개수, 실패 또는 타임아웃에 대한 내용이 좀 더 자세히 작성되었습니다.

 

 

1) RFC 2616 Section 8.1.x (이전)

 

지속적인 접속을 사용하는 클라이언트는 특정 서버로의 동시 접속 숫자에 제한을 두어야 한다. 단독 사용자 클라이언트는 최대 2 개의 서버나 프락시 접속을 유지해야 한다.

 

 

2) RFC 7230 Section 6.3.x, Section 6.4, Section 6.5, Section 6.6 (이후)

 

HTTP의 이전 개정 버전에서는 커넥션의 특정 수를 최대 한계로서 지정했지만, 대부분의 애플리케이션에서는 불가능한 것으로 확인되었다. 결과적으로, 이 명세는 지정된 최대 커넥션 수를 의무화하지 않는 대신 다중 커넥션을 열 때 클라이언트에게 보수적이 될 것을 권장한다.

 

자세한 내용은 RFC 7230 Section 6에서 확인할 수 있습니다.

 

 

7. Upgrade 헤더 필드의 구문이 변경되고, Upgrade 헤더 사용에 대한 명세가 더 구체화되었습니다. ([RFC7230] Section 6.7)

 

426(Upgrade Required) 응답을 전송하는 서버는 내림차순 기본 설정 순서로 허용 가능한 프로토콜을 나타내기 위해 Upgrade 헤더 필드를 전송해야 한다.(MUST)

 

Upgrade가 실수로 전달되는 것을 방지하기 위해 “upgrade” 커넥션 옵션이 포함된 Connection 헤더 필드(Section 6.1)도 전송해야 한다.(MUST) 서버는 HTTP/1.0 요청으로 수신된 Upgrade 헤더 필드를 무시해야 한다.

 

 

8. 헤더 필드 요소에서 “ ” 빈 목록 헤더 필드는 더 이상 사용되지 않는다.([RFC7230] Section 7)

 

 

9. Proxy-Connection 헤더 필드의 사용이 중단되었습니다.  ([RFC7230] Appendix.A 1.2)

 

HTTP/1.0 호환성을 위해 Connection: keep-alive 헤더를 여러 계층으로 전송하는 문제를 해결하려고 했으나 

잘못된 사용으로 인해, 방법을 간구한 것이 Proxy-Connection 헤더를 도입하는 걸 통해 문제를 해결하려고 했으나, 이 또한 비슷한 문제를 야기시키기 때문에 Proxy-Connection 헤더 자체를 사용하면 안 된다.

 

 

10. Content-Length와 Transfer-Encoding 헤더에 대한 구체적인 내용이 추가되었습니다. ([RFC7230] Section 3.3.1, Section 3.3.2)

 

(1) (서버인 경우) 서버는 상태 코드가 1xx or 204 응답에서 Transfer-Encoding를 전송하면 안 된다.

(2) (서버인 경우) 서버는 CONNECT 요청에 2xx 응답에서 Transfer-Encoding 를 전송하면 안 된다.

(3) (서버인 경우) 클라이언트 전송 HTTP 프로토콜이 1.1 이상이 아닌 경우 Transfer-Encoding 를 전송하면 안 된다.

(4) (클라이언트인 경우) 서버가 HTTP 프로토콜 1.1 이상을 처리할 수 있을 것이라고 알지 못한다면 Transfer-Encoding 를 전송하면 안 된다.

(5) (서버인 경우) 이해하지 못하는 전송 코딩과 메시지를 받은 서버는 501 Not Implement로 응답해야 한다.

(6) 발신자는 Transfer-Encoding 헤더 필드를 포함하는 메시지에서 Content-Length 헤더 필드를 보내면 안 된다.

(7) (서버인 경우) 서버는 HEAD 요청에 대한 응답으로 Content-Length 헤더 필드를 전송할 수 있다.

(8) (서버인 경우) 서버는 상태 코드가 1xx 또는 204인 응답에 Content-Length 헤더 필드를 보내면 안 된다.

(9) (서버인 경우) 서버는 CONNECT 요청에 대한 2xx (Successful) 응답에서 Content-Length 헤더 필드를 보내서는 안 된다.

 

 

11. Message Length에 관련된 부분이 더 구체적으로 작성되었습니다.

 

1) RFC 2616 Section 4.4 (이전)

 

(1) 본문을 갖는 것이 허용되지 않는 HTTP 메시지는 Content-Length가 무시되어야 한다.

(2) Transfer-Encoding 헤더 포함 시, 0바이트 청크로 불리는 패턴으로 끝나야 한다.

(3) Transfer-Encoding 헤더 포함 시(identity가 아닌) Content-Length는 무시되어야 한다.

(4) multipart/byteranges 미디어 타입을 사용하고 Content-Length로 결정되지 않는다면 본문이 각각 메시지를 가지고 있다는 뜻이다.

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

(6) 오직 서버만이 메시지가 끝났음을 알리기 위해서 커넥션을 닫을 수 있다.(중요)

(7) 메시지의 길이를 판별할 수 없다면 400 Bad Request 응답을 보내고 유효한 Content-Length를 요구하려면 411 Length Required를 전송한다.

(8) Transfer-Encoding을 HTTP/1.0은 이해하지 못한다.

 

 

2) RFC 7230 Section 3.3.3 (이후)

 

(1) HEAD 요청에 대한 응답과 1xx, 204 또는 304 상태 코드 응답은 메시지 본문을 포함할 수 없다.

(2) CONNECT 요청에 대한 2xx 응답인 경우 클라이언트는 이러한 메시지에 수신된 Content-Length 또는 Transfer-Encoding 헤더 필드를 반드시 무시해야 한다.

(3) Transfer-Encoding 헤더 필드가 있고 청크 전송 코딩(Section 4.1)이 최종 인코딩인 경우, 전송 코딩이 데이터가 완료되었음을 나타낼 때까지 청크 데이터를 읽고 디코딩하여 메시지 본문 길이를 결정한다.

 

* 응답에 Transfer-Encoding 헤더 필드가 있고 청크 분할 전송 코딩이 최종 인코딩이 아닌 경우, 서버가 커넥션을 닫을 때까지 커넥션을 읽어 메시지 본문 길이를 결정한다.

* 요청에 Transfer-Encoding 헤더 필드가 있고 청크 전송 코딩이 최종 인코딩이 아닌 경우 메시지 본문 길이를 신뢰할 수 없다; 서버는 400(Bad Request) 상태 코드로 응답한 다음 연결을 반드시 닫아야 한다.

* 메시지가 Transfer-Encoding 및 Content-Length 헤더 필드와 함께 수신되면 Transfer-Encoding이 Content-Length를 재정의한다. 그러한 메시지는 오류로 취급되어야 한다. 발신자는 이러한 메시지를 다운 스트림으로 전달하기 전에 수신된 Content-Length 필드를 반드시 제거해야 한다.

 

(4) Transfer-Encoding이 없는 메시지를 수신하거나 여러 Content-Length 헤더 필드들의 field-value가 다르거나 단일 Content-length 헤더 필드가 잘못된 경우

 

* 서버가 수신한 요청 메시지인 경우, 서버는 400 (Bad Request) 상태 코드로 응답한 다음 커넥션을 닫아야 한다.

* 프락시에서 수신한 응답 메시지인 경우, 프락시는 서버에 대한 커넥션을 닫고 수신된 응답을 무시하고, 502 (Bad Gateway)을 클라이언트에게 전송해야 한다.

* 사용자 에이전트가 수신한 응답 메시지인 경우, 사용자 에이전트는 서버에 대한 커넥션을 닫고 수신된 응답을 삭제해야 한다.

 

(5) Transfer-Encoding이 없는 유효한 Content-Length 헤더 필드가 있는 경우, 발신자가 커넥션을 닫거나 표시된 Content-Length octet 수를 수신하기 전에 시간이 초과되면, 수신자는 메시지가 불완전한 것으로 간주하고 연결을 반드시 닫아야 한다.

(6) 이 메시지가 요청 메시지이고 위의 메시지 중 하나가 참이 아니면 메시지 본문 길이가 0이다.

(7) 그렇지 않으면, 이것은 선언된 메시지 본문 길이가 없는 응답 메시지이므로, 메시지 본문 길이는 서버가 커넥션을 닫기 전에 수신한 octet 수로 결정된다.

 

 

 

12. 페이로드가 특정 식별자와 연관되어 있는지 여부를 결정하기 위한 알고리즘이 추가되었습니다. ([RFC7231] Section 3.1.4.1)

 

 

 

13. 텍스트 미디어 타입에 대한 ISO-8859-1의 기본 문자 집합이 제거되었으며,

미디어 타입 정의가 말하는 기본 문자 집합은 이제 모두 삭제되었고,

마찬가지로 ISO-8859-1의 특별 처리는 Accept-Charset 헤더 필드에서 제거되었습니다. ([RFC7231] Section 3.1.1.3 및 Section 5.3.3)

 

 

(1) RFC2616 Section 3.7.1, 14.2

 

"charset" 파라미터는 몇몇 미디어 형식에서 데이터의 문자 집합(3.4 절)을 규정하는 데 사용한다. 송신자가 명백한 charset 파라미터를 제공하지 않았다면 "text" 유형의 미디어 subtype 형식은 HTTP를 통하여 수신했을 때 "ISO-8859-1"의 charset 기본값을 갖도록 규정되어 있다. "ISO-8859-1" 이외 문자 집합의 데이터나 그 하부 세트는 적절한 charset 값으로 명명되어야 한다. ([RFC2616] Section 3.7.1)

 

Accept-Charset 요청 헤더 필드는 응답에 사용할 수 있는 문자 조합을 표시하는 데 사용한다. 이 필드는 광범위하고 전문적인 목적의 문자 조합을 이해할 수 있는 클라이언트가 이러한 문자 조합으로 문서를 표시할 수 있는 서버에게 자신의 능력을 알려 줄 수 있도록 한다. 모든 클라이언트는 ISO-8859-1 문자 조합을 사용할 수 있는 것으로 가정한다. ([RFC2616] Section 14.2)

 

(2) RFC7231 Section 3.1.1.3, 5.3.3

 

ISO-8859-1에 대한 처리 처리 내용이 제거됨 ([RFC7231] Section 3.1.1.3)

 

Accept-Charset 필드에 있는 경우 특수 값 “*”은 Accept-Charset 필드의 다른 곳에서 언급되지 않은 모든 문자 집합과 일치한다. Accept-Charet 필드에 “*”가 없는 경우, 필드에 명시적으로 언급되지 않은 모든 문자 집합은 클라이언트에 “not acceptable”것으로 간주된다.

Accept-Charset 헤더 필드가 없는 요청은 사용자 에이전트가 응답에 대한 모든 문자 집합을 수용함을 의미한다.([RFC7231] Section 5.3.3)

 

 

14. [RFC7230]의 method-neutral 파싱 알고리즘과 일치하기 위해,

GET 정의를 완화하여 본문은 GET을 의미하지 않지만 요청은 본문을 가질 수 있다.([RFC7231] Section 4.3.1)

 

 

15. 서버는 더 이상 모든 Content-* 헤더 필드를 처리할 필요가 없으며,

PUT 요청에서 Content-Range의 사용이 명시적으로 금지되었다. ([RFC7231] Section 4.3.4)

 

 

16. OPTION과 TRACE 요청 메서드는 안전하다고 정의되었다. (RFC7231 Section 4.3.7 및 Section 4.3.8)

 

안전, 멱등성 메서드 표 - [RFC7231] Section 8.1.3 참조

 

 

 

17. 널리 배포된 잘못된 구현으로 인해 Expect 헤더 필드의 확장 메커니즘이 제거되었다. ([RFC7231] Section 5.1.1)

 

1) RFC2616 Section 14.20

 

Expect       =  "Expect" ":" 1#expectation

 

 

이 헤더 필드는 미래의 확장성을 위해 확장 가능한 구문으로 정의된다.

서버가 지원하지 않는 expectation-extension을 포함하는 Expect 필드를 포함하는 요청을 수신하는 경우,

서버는 반드시 417 (Expectation Failed) 상태로 응답해야 한다.

 

 

2) [RFC7231] Section 5.1.1

 

Expect  = "100-continue"

 

100-continue 이외의 Expect field-value를 수신하는 서버는 417 (Expectation Failed) 상태 코드로 응답하여 예상하지 못한 expectation을 충족할 수 없음을 나타낼 수 있다.(MAY)

 

Expect 헤더 필드는 중간 100 (Continue) 응답을 요청하는 수단 및 반드시 이해해야 하는 확장을 표시하는 일반적인 메커니즘으로 HTTP/1.1 [RFC2068]의 최초 발행 후 추가되었다. 그러나, 확장 메커니즘은 클라이언트에 의해 사용되지 않았고, 반드시 이해되어야 하는 요구사항은 많은 서버에 의해 구현되지 않아 확장 메커니즘이 무용지물이 되었다. 이 명세는 100-continue 정의와 처리를 단순화하기 위해 확장 메커니즘을 제거하였다.

 

 

19. Max-Forwards 헤더 필드는 OPTIONS와 TRACE 메서드로 제한되었다. 이전에는 구체적으로 어느 메서드에서만 사용해야 한다는 제한이 없었다. ([RFC7231] Section 5.1.2)

 

 

20. 다음 상태 코드는 이제 캐시 가능(즉, 명시적인 신선도 정보가 없는 상태에서 캐시에 저장 및 재사용 가능): 204, 404, 405, 414, 501. ([RFC7231] Section 6)

 

1) RFC 2616 Section 13.4

 

상태 코드 200, 203, 206, 300, 301 또는 410으로 수신된 응답은 Cache-Control 지시어가 캐시를 금지하지 않는 한 만료 메커니즘에 따라 캐시에 저장되고 후속 요청에 대한 응답에 사용될 수 있다.

 

2) RFC7231 Section 6.1

 

기본적으로 캐시 가능으로 정의된 상태 코드(e.g., 이 명세의 200, 203, 206, 300, 301, 404, 405, 410, 414 및 501)의 응답은 메서드 정의나 명시적 캐시 제어 [RFC7234]에 달리 명시되지 않는 한 휴리스틱 한 만료를 가진 캐시에 의해 재사용할 수 있으며, 다른 모든 상태 코드는 기본적으로 캐시 가능하지 않다.

 

 

21. 명시적인 신선도 정보가 제공될 경우 캐시 할 수 있도록 303 (See Other) 상태 코드에 대한 설명이 변경되었으며, GET에 대한 303 응답에 대한 구체적인 정의가 추가되었다. ([RFC7231] Section 6.4.4)

 

 

22. 305 (Use Proxy) 상태 코드는 프락시의 인-밴드 구성과 관련된 보안상의 문제로 인해 더 이상 사용되지 않았다. (Section 6.4.5)

 

 

23. 400 (Bad Request) 상태 코드가 구문 오류에 국한되지 않도록 완화되었다. ([RFC7231] Section 6.5.1)

 

1) RFC2616 Section 10.4.1

 

잘못된 형식의 구문으로 인해 서버에서 요청을 이해할 수 없었다. 고객은 수정 없이 요청을 반복해서는 안 된다.(SHOULD NOT)

 

2) RFC7231 Section 6.5.1

 

400 (Bad Request) 상태 코드는 클라이언트의 오류로 인식되는 것(e.g., 잘못된 요청 구문, 잘못된 요청 메시지 프레임 또는 기만적인 요청 라우팅)으로 인해 서버가 요청을 처리할 수 없거나 처리할 수 없음을 나타낸다.

 

 

24. [RFC2817]에서 426 (Upgrade Required) 상태 코드가 통합되었다. ([RFC7231] Section 6.5.15)

 

 

25. HTTP-date와 Date 헤더 필드의 요구사항의 대상은 날짜를 보내는 모든 시스템이 아닌 날짜를 생성하는 시스템으로 축소되었다. ([RFC7231] Section 7.1.1)

 

 

26. Location 헤더 필드의 구문은 단편 사용이 적절하지 않은 시기에 대한 일부 명확성과 함께 상대적 참조와 단편을 포함한 모든 URI 참조를 허용하도록 변경되었다. ([RFC7231] Section 7.1.2)

 

3xx (Redirection) 응답에 제공된 Location 값에 단편 구성 요소가 없는 경우, 사용자 에이전트는 그 값이 요청 대상을 생성하는 데 사용된 URI 참조의 단편 구성 요소(즉, 리디렉션은 원래 참조의 파편을 상속하는 경우)를 상속하는 것처럼 리디렉션을 처리해야 한다.([RFC7231] Section 7.1.2)

 

 

27. Allow가 응답 헤더 필드로 재분류되어, PUT 요청에서 Allow를 지정하는 옵션이 제거되었다. Allow의 내용과 관련된 요구사항은 완화되었다. 따라서 클라이언트는 항상 그 값을 신뢰해야 하는 것은 아니다. ([RFC7231] Section 7.4.1)

 

1) RFC2616 Section 14.7

 

Allow 헤더 필드에는 새 리소스 또는 수정된 리소스가 지원하는 메서드를 권장하기 위한 PUT 요청이 제공될 수 있다. 서버는 이러한 메서드를 지원할 필요가 없으며 실제 지원되는 메서드를 제공하는 응답에 Allow 헤더를 포함해야 한다.(SHOULD)

 

2) RFC 7231 Section 7.4.1 

 

(내용 삭제됨)

 

 

28. [RFC6266]에 의해 정의된 이후 Content-Disposition 헤더 필드가 제거되었다.

 

 

29. 이제 범위 요청을 제외한 모든 요청에서 약한 entity-tag가 허용된다.  ([RFC7232] Section 2.1 및 Section 3.2)

 

강한 검증자는 캐시 검증, 부분 콘텐츠 범위, "갱신 손실" 방지 등 모든 조건부 요청에 사용할 수 있다.  약한 검증자는 클라이언트가 캐시 입력을 검증하거나 웹 트래버설을 최근 변경사항으로 제한할 때와 같이 이전에 획득한 표현 데이터와의 정확한 동일성을 요구하지 않는 경우에만 사용할 수 있다.(RFC7232 Section 2.1)

 

 

30. ETag 헤더 필드 ABNF가 quoted-string을 사용하지 않도록 변경되어 이스케이핑 문제가 발생하지 않도록 했다.  ([RFC7232] Section 2.3)

 

1) RFC2616 Section 14.19, 3.11

 

ETag = "ETag" ":" entity-tag

entity-tag = [ weak ] opaque-tag

weak       = "W/"

opaque-tag = quoted-string

 

2) RFC7232 Section 2.3

 

ETag       = entity-tag

entity-tag = [ weak ] opaque-tag

weak       = %x57.2F ; "W/", case-sensitive

opaque-tag = DQUOTE *etagc DQUOTE

etagc      = %x21 / %x23-7E / obs-text
                ; VCHAR except double quotes, plus obs-text

 

이전에는 불투명 태그가 따옴표 문자열([RFC2616], Section 3.11)로 정의되었기 때문에 일부 수신자는 백슬래시 언 이스케이핑을 수행할 수 있다.  따라서 서버는 엔티티 태그의 문자를 역슬래시하지 않아야 한다.

 

 

31. ETag는 선택된 표현에 대한 엔티티 태그를 제공하도록 정의되어 있어, 다양한 상황(PUT 응답 같은)에 적용되는 내용을 명확히 한다. ([RFC7232] Section 2.3)

 

응답의 "ETag" 헤더 필드는 요청 처리 완료 시 결정된 대로 선택된 표현에 대한 현재 entity-tag를 제공한다.  entity-tag는 복수의 표현이 시간에 따른 리소스 상태 변화, 복수의 표현을 동시에 유효하게 만드는 콘텐츠 협상, 또는 둘 다에 관계없이 동일한 리소스의 복수의 표현을 구별하기 위한 불투명한 검증자다.  entity-tag는 불투명한 따옴표 문자열로 구성되며, 약한 표시기에 의해 접두사가 될 수 있다.

 

 

32. 조건부 요청의 평가 우선순위가 정의되었다.([RFC7232] Section 6)

 

요청에 둘 이상의 조건부 요청 헤더 필드가 있을 때 필드가 평가되는 순서가 중요해진다.  실제로 이 문서에서 정의한 필드는 캐시 유효성 검사보다 "갱신 손실" 전제조건이 더 엄격하고, 검증된 캐시가 부분 응답보다 효율적이며, 엔티티 태그가 날짜 검증자보다 더 정확한 것으로 추정되기 때문에 하나의 논리적 순서로 일관되게 구현된다.

 

수신자 캐시 또는 원서버는 이 명세에 의해 정의된 요청 전제조건을 다음 순서로 평가해야 한다.(MUST)

 

1) 수신자가 원서버이고 If-Match가 있을 때 If-Match 전제조건을 평가한다.

* 참일 경우 3단계로 계속 진행

* 거짓일 경우, 상태 변경 요청이 이미 성공했다고 판단할 수 없는 한 412 (Precondition  Failed) 응답한다([RFC7232] Section 3.1 참조).

 

2) 수신자가 원서버이며, If-Match가 존재하지 않고, If-Unmodified-Since가 있을 경우, If-Unmodified-Since 전제조건:

* 참일 경우 3단계로 계속 진행

* 거짓일 경우, 상태 변경 요청이 이미 성공했다고 판단할 수 없는 한 412 (Precondition Failed) 응답한다([RFC7232] Section 3.4 참조).

 

3) If-None-Match가 있을 때 If-None-Match 전제조건을 평가한다.

* 참일 경우 5단계로 계속 진행

* GET/HEAD에 대해 거짓일 경우 304 응답(Not Modified)

* 기타 메서드에 대해 거짓일 경우 412 응답(Precondition Failed)

 

4) 메서드가 GET 또는 HEAD일 때, If-None-Match가 존재하지 않고, If-Modified-Since가 있을 때, If-Modified-Since:

* 참일 경우 5단계로 계속 진행

* 거짓일 경우 304 응답(Not Modified)

 

5) 메서드가 GET이고 Range와 If-Range가 모두 있을 때 If-Range 전제조건을 평가한다.

* 검증자가 일치하고 Range 명세가 선택된 표현에 적용 가능한 경우, 응답 206(Partial Content) [RFC7233]

 

6) 그렇지 않으면

* 모든 조건이 충족되므로 요청된 조치를 수행하고 성공 또는 실패에 따라 대응한다.

 

 

33. 206 응답에는 약한 검증자를 사용할 수 없다. ([RFC7233] Section 4.1, Section 3.2)

 

서버는 대상 리소스에 대한 Range 헤더 필드를 지원하며, 지정된 범위가 유효하고 충족 가능한 경우(Section 2.1에서 정의) 서버는 Section 4에 정의된 바와 같이 요청된 충족가능한 범위에 해당하는 하나 이상의 부분적 표현을 포함하는 페이로드와 함께 206 (Partial Content) 응답을 보내야 한다.(SHOULD) ([RFC7233] Section 3.1)

 

클라이언트는 약한 entity-tag가 포함된 If-Range 헤더 필드를 생성해서는 안 된다.(MUST NOT) ([RFC7233] Section 3.2)

 

 

34. 인증된 응답을 캐시 할 수 있는 조건이 명확해졌다.  ([RFC7234] Section 3.2)

 

공유 캐시는 해당 응답을 저장할 수 있는 캐시 지시어가 응답에 없는 한, 후속 요청을 충족하기 위해 Authorization 헤더 필드가 있는 요청에 대해 캐시 된 응답을 사용해서는 안 된다.(MUST NOT) ([RFC7235] Section 4.2).

 

 

35. 새로운 상태 코드는 이제 캐시가 휴리스틱 한 신선도를 함께 사용할 수 있도록 허용된다는 것을 정의할 수 있다.  캐시는 이제 쿼리 구성요소가 있는 URI의 휴리스틱한 신선도를 계산할 수 있다.  ([RFC7234] Section 4.2.2)

 

[RFC2616] Section 13.9에서는 캐시가 쿼리 구성요소가 있는 URI(즉, '?'가 포함된)에 대해 휴리스틱 신선도를 계산하는 것을 금지했다. 실제로 이는 널리 구현되지 않았다.  따라서 캐싱을 배제하고자 하는 경우 원서버는 명시적 지시어(예: Cache-Control: no-cache)를 전송하도록 권장된다.([RFC7234] Section 4.2.2)

 

 

36. Content-Locaion 응답 헤더 필드는 더 이상 유효성 검사 시 사용할 적절한 응답을 결정하는 데 사용되지 않는다. ([RFC7234] Section 4.3)

 

(Content-Location 관련 내용 제거됨)

 

 

37. 사용할 캐시 된 협상 응답 선택 알고리즘은 여러 가지 방법으로 명확히 하였다.  특히 이제는 헤더 필드 선택 처리 시 헤더 별 표준화를 명시적으로 허용하고 있다.  ([RFC7234] Section 4.1)

 

 

38. 캐시 무효화는 성공적인 응답이 수신된 경우에만 발생한다.  (Section 4.4)

 

안전하지 않은 요청 메서드에 대한 응답으로 비-오류 상태 코드가 수신될 때, 캐시는 유효한 요청 URI([RFC7230]의 Section 5.5)와 Location 및 Content-Location 헤더 필드(있는 경우)의 URI를 무효화해야 한다.(MUST)

 

캐시는 안전한지 알 수 없는 메서드로 요청에 대한 비-오류 응답을 수신했을 때 유효한 요청 URI([RFC7230]의 Section 5.5)를 무효화해야 한다.(MUST)

 

 

39. 캐시 지시어는 대소문자를 구분하지 않도록 명시적으로 정의되어 있다. 한 개만 예상될 때 캐시 지시어의 여러 인스턴스를 처리하는 것이 이제는 정의된다.  ([RFC7234] Section 5.2)

 

 

40. ”no-store" 요청 지시어는 응답에 적용되지 않는다. 즉, 캐시는 no-store 요청을 충족할 수 있고 무효화하지 않는다. ([RFC7234] Section 5.2.1.5)

 

이 지시어를 포함하는 요청이 캐시에서 충족되는 경우, 이미 저장된 응답에는 no-store 요청 지시어가 적용되지 않는다는 점에 참고한다.

 

 

41. private 캐시 및 no-cache 캐시 지시어 적격 형태는 널리 구현되지 않는 것으로 알려져 있다. 예를 들어, "private=foo"는 단순한 "private"로 해석되는 많은 캐시가 있다.  또한, no-cache의 자격 있는 형태의 의미가 명확해졌다. ([RFC7234] Section 5.2.2)

 

 

42. Expires 헤더 필드 값에 대한 1년 제한은 제거되었다. 대신, 합리적인 값을 사용하기 위한 추론이 제시된다. ([RFC7234] Section 5.3)

 

역사적으로, HTTP는 Expires field-value가 향후 1년 이하가 되도록 요구하였다.  더 긴 신선도 수명은 더 이상 금지되지 않지만, 극도로 큰 값은 문제를 일으키는 것으로 입증되었고(e.g., 시간 값에 32비트 정수 사용으로 인한 시계 오버플로), 대부분의 캐시가 그보다 훨씬 빠르게 응답을 제거할 것이다.

 

 

43. Pragma 헤더 필드는 이제 역호환성만을 위해 정의되며, 미래에 pragma는 더 이상 사용되지 않는다.  ([RFC7234] Section 5.4)

 

"Pragma" 헤더 필드는 HTTP/1.0 캐시와의 역호환성을 허용하므로 클라이언트가 이해할 "no-cache" 요청을 지정할 수 있다(HTTP/1.1까지 Cache-Control이 정의되지 않았기 때문에).  Cache-Control 헤더 필드도 존재하며 요청으로 이해되면, Pragma는 무시된다.

 

 

 


 

 

마지막으로 하고 싶은 말

 

RFC 2616에서 RFC 7230, 7231, 7232, 7233, 7234, 7235로 개정되었습니다.(오래전..)

사실, RFC 문서 자체는 강제성이 있는 부분은 아닙니다. 국제법이나 국내법 같은 ‘어기면 큰일 난다’의 문서가 아닙니다. 

 

다만, “커뮤니케이션하는데 이렇게 하는 것은 어떻겠느냐”라는 것에 대한 작성된 문서로 볼 수 있습니다. 

이런 문서들의 특성 중 하나는 ‘규칙부터 먼저 만들고 이렇게 합시다’가 아닌 ‘사람들이 대부분 이렇게 사용하더라’라는 것을 정리하는 ‘뒤 따르는’ 특성을 가진 문서로 볼 수 있습니다.

그러다 보니 이런 문서는 뒤늦게 ‘표준’ 문서로 지정됩니다. 

 

또 하나의 특성은, 각 큰 기업이나, 협회 또는 특정 프로토콜 설계자들이 기술과 프로토콜을 만들면, 많은 사람들이 사용하게 되면서 ‘표준’으로 채택할 가능성이 높습니다. 그러한 것들을 정리하면 표준 문서가 됩니다. 

예시로, HLS 같은 프로토콜이 그렇게 표준화되었습니다. HTTP/3.0 같은 경우도 마찬가지로, 기업에서 먼저 선도한 프로토콜이며 그 결과물을 좀 더 다듬어서 표준화시키려는 노력을 할 뿐이지요.

 

고로, '커뮤니케이션 표준'을 꼭 지켜야 한다, 지키지 않아도 돼야 한다 이런 부분은 얘기할 필요는 없을 것 같습니다. 

'옳다', '그르다', '왜 모르냐’'이런 것보단. 알면 좋은. 그런 느낌으로 보면 좋을 것 같습니다.

 

ps. 다만, 웹서버를 직접 만들 경우는 명세에 따라 만드는 것이 좋습니다. 이유는 명세가 알고리즘과 규칙의 근거와 기준이 될 수 있기 때문입니다.

 

 

Comments