요약
- RFC 2068은 HTTP 버전 번호를, 실제 사용된 기능 목록이 아니라 메시지 형식과 발신자가 이후 통신을 이해할 수 있는 최대 능력에 대한 선언으로 정의했다.
- 프록시가 메시지를 해석한 뒤 다음 홉으로 보낼 메시지를 새로 만들 때, 프록시 자체가 발신자가 되며 이전 클라이언트의 능력이 아니라 자신의 능력에 맞는 버전을 선언해야 한다.
- 단일 주 버전 내의 발전은 새 권한을 허용했지만, 최신 발신자가 만든 메시지는 수신자가 모르는 필드를 제거했을 때에도 구버전 수신자에게 유효해야 한다는 조건이 붙었다.
모든 것을 설명하지 않는 숫자
버전 정책 문구는 HTTP/1.1 이전에 등장했다. RFC 1945는 1996년 5월 HTTP/1.0의 널리 퍼진 사용을 문서화하면서, 일관되게 구현된 특성과 드물거나 일관되지 않은 특성을 구분했다. 하나의 이름이 균질하지 않은 구현 현실을 뒤덮고 있었기 때문에, 그 숫자가 모든 프로그램의 모든 기능을 정밀하게 목록화하는 역할을 할 수는 없었다.
문서는 메시지의 버전이 그 형식과 발신자가 더 많은 HTTP 통신을 이해할 수 있는 능력을 가리키며, 해당 교환에서 실제 활용된 특성을 가리키는 것이 아니라고 밝혔다. 두 숫자의 역할은 서로 다르다. 주 버전은 메시지 형식이 바뀔 때 바뀌고, 부 버전은 일반적인 파싱 알고리즘을 바꾸지 않고 의미론이나 능력이 추가될 때 올라갈 수 있다. 확장 가능한 필드에 새 값을 추가하는 것만으로는 새 버전이 필요하지 않다.
1997년 1월에 발행된 RFC 2068은 이 구분을 유지하면서 더 명확한 의무로 만들었다. 그 사양에 따라 정의된 요청이나 응답은 시작 줄에HTTP/1.1을 쓴다. 이 선언은 발신 애플리케이션이 적어도 조건부로는 그 사양과 호환됨을 의미한다. 애플리케이션의 버전은 그 수준의 호환성을 달성할 수 있는 최고 버전이다.
따라서 하나의 증표에 합쳐서는 안 되는 세 가지가 있다. 지금 도착한 메시지의 구성, 그 작성자가 선언한 능력의 상한, 그리고 바로 그 메시지에서 활성화한 기능이다. 단순한 요청이 분할 전송 본문이나 콘텐츠 협상, 눈에 띄는 캐시 지시어 없이HTTP/1.1을 담을 수 있다. 숫자가 여전히 유용한 이유는, 나중에 오는 응답이나 요청에서 발신자가 무엇을 이해할 수 있는지 상대에게 알려주기 때문이다. 하지만 그것이 지속 연결이나 청크 전송, 혹은 다른 어떤 기능이 실제로 사용되었음을 증명하지는 않는다.
이 정의가 첫 줄을 인증 메커니즘으로 바꾸지도 않는다. 불완전한 프로그램은 선언에서 과장할 수 있다. 사양은 호환 선언의 의미를 정할 뿐, 코드에 서명하거나 구현을 검사하지 않는다. 마찬가지로 그 숫자는 메시지가 최종 목적지에 도달했음, 모든 중간 노드가 필드를 보존했음, 콘텐츠가 수락되었음, 애플리케이션 작업이 완료되었음을 증명하지 않는다.
프록시는 클라이언트의 목소리가 아니라 자기 목소리로 말한다
증거의 한계는 메시지가 중간 노드를 지날 때 드러난다. 프록시나 게이트웨이는 필드를 해석하고, 일부를 삭제하고, 다른 것을 추가한 뒤 새 메시지를 만들 수 있다. 그래서 RFC 2068은 중간 노드가 자신의 실제 버전보다 높은 번호를 보내는 것을 금지했다.
중간 노드가 자신이 이해하는 수준보다 새로운 요청을 받으면 선택지는 정해져 있었다. 버전을 낮추거나, 오류를 반환하거나, 메시지를 해석하지 않는 터널로 전환하는 것 중 하나였다. 더 오래된 요청을 받으면 적절한 조건에서 전달 시 버전을 올릴 수도 있다. 이 변환 과정에서 필드를 추가하거나 삭제해야 할 수 있다. 이것은 클라이언트 카드의 사본이 아니라, 다음 메시지를 만드는 자가 떠안는 새로운 책임이다.
RFC 2145가 1997년 5월에 나온 것은 버전 번호의 의도를 둘러싼 혼란과 논쟁, 상호운용성 문제 때문이었다. 문서는 규칙을 명확히 요약했다. HTTP 버전 번호는 홉마다의 구성 요소이며, 종단 간 속성이 아니다. 프록시가 요청이나 응답의 번호를 마치 원본 메시지의 소유물인 것처럼 '전달'하는 일은 없다.
Via필드는 이전 구간들이 선언한 프로토콜을 별도로 기록할 수 있다. 그러나 그것은 다른 종류의 증거이며, 현재 버전 번호를 경로 전체의 완전한 역사나 조작 불가능한 증명으로 만들지 않는다. 원본 서버가 보는 것은 직접 이웃이 낸 선언을 설명한다. 브라우저가 이전 중간 노드에게 무엇을 말했는지 알려면 그 구간 자체를 관찰하거나 신뢰할 수 있는 기록이 필요하다.
새로움을 잃어도 유효한 메시지라는 조건이 붙은 갱신 권리
부 버전을 올리는 것이 알려진 모든 의미를 바꾸겠다는 선언은 아니었다. RFC 2145는 같은 주 버전 안의 부 버전은 기존 필드의 해석을 바꾸어서는 안 된다고 명확히 했다. 수신자는 보통 모르는 필드를 무시할 수 있으며, 그 덕분에 공유된 파싱 알고리즘이 발전의 기준으로 남는다.
그러나 이 관용은 결정적인 제약 안에 있다. 최신 당사자가 HTTP/1.1 메시지를 HTTP/1.0 수신자, 혹은 버전을 알 수 없는 당사자에게 보낸다면, 더 오래된 버전이 정의하지 않는 필드를 제거한 뒤에도 메시지가 HTTP/1.0 메시지로서 유효해야 했다. 발신자는 새 필드를 넣을 수 있지만, 옛 당사자가 그 필드를 이해해야 메시지가 해석 가능해진다는 식으로 의존할 수는 없다.
이 삭제 테스트는 혁신의 비용을 새 기능을 선택한 쪽에게 둔다. 옛 애플리케이션은 미래를 예측할 필요가 없다. 요구되는 것은 새 애플리케이션이 자신의 추가가 사라진 뒤에도 완결된 옛 핵심을 남기는 것이다. 그래서 예컨대 HTTP/1.1 서버가Transfer-Encoding: chunked에 의존하는 응답을 HTTP/1.0 요청에 보내면서 클라이언트에게 필드 이름만 무시하라고 기대해서는 안 된다. 그 경우 정보를 지우면 메시지 본문의 프레이밍 자체가 깨진다.
또한 모르는 필드와 홉 전용 필드를 구분해야 한다. 원칙적으로 프록시는 모르는 필드를 보존해야 한다. 이후 방향의 애플리케이션이 그 확장을 이해할 수 있기 때문이다. 반면Connection에 언급된 필드는 현재 연결에 속하며 다음 홉 전에 제거해야 한다. 확장 가능성은 지역 지시어를 통과시키거나, 메시지 경계를 이해하는 데 필수적인 의존을 숨기는 허가가 아니다.
해설 문서는 통계가 아니라 역사의 일부
RFC 2145는 HTTP/1.0과 HTTP/1.1에서 의도된 의미를 바꾸지 않고, 모호함이 있을 때 그 읽기를 확정한다고 밝혔다. 그 문서가 필요해졌다는 사실 자체가 텍스트와 구현 사이의 마찰을 보여준다. 그러나 그것은 피해를 입은 제품 수나 그 이름, 규칙을 어긴 트래픽의 비율을 알려주지 않는다. 그런 수치를 그 문서에서 추출해서는 안 된다.
문서는 또한 버전 선택 방식을 규율했다. 클라이언트는 보통 조건부 호환을 달성할 수 있는 최고 버전을 보내되, 서버가 알고 있는 주 버전을 넘지 말아야 한다. 서버는 그 호환을 달성할 수 있는 최고 버전으로 응답하되, 주 버전이 받은 것을 넘지 않도록 한다. 어느 쪽도 자신이 구현하지 않는 버전을 선언할 권리가 없다.
문서는 결함이 확인된 상대를 다루기 위해 문제를 관찰한 뒤 번호를 낮추는 것을 허용했지만, 이를 기본 정책으로 삼지는 말라고 했다. 영구적인 하향은 올바른 애플리케이션에서 새 능력을 빼앗고 결함 있는 구현을 보상한다. 반대로 과장된 번호는 상대가 존재하지 않는 능력에 의존하도록 부추긴다.
1999년 RFC 2616은 이 구분을 유지하며 RFC 2145를 명시적으로 참조했다. 2014년 RFC 7230은 부 버전이 현재 메시지가 하위 호환 가능한 기능 집합만 사용하더라도 미래의 통신 능력을 선언한다는 점을 더 명확히 정식화했다. 또한 RFC 2068에서 RFC 2616으로의 전환이 부 버전을 올리지 않았음을 기록했다. 문서의 개정, 의무의 변경, 전선 위 표시의 변경은 서로 다른 사건이다.
이어서 2022년의 RFC 9110은 공통 HTTP 의미론을 HTTP/1.1, HTTP/2, HTTP/3 각각의 메시지 형식과 분리했다. 이 주 버전들은 공존하며, HTTP/1.1의 부 버전 메커니즘을 그 협상과 서로 다른 형식에 기계적으로 투영해서는 안 된다. 중간 노드가 메시지를 다시 전달할 때 버전은 그 중간 노드가 그 홉에서 사용한 프로토콜이며,Via는 현재 선언과는 다른 역할의 기록을 수행한다.
사양 발표와 능력 운용 사이에서
Lu Heng의 후속 정식화 — '최소 초기 사양, 지역화된 미래 결정, 자발적 채택' — 은 유용한 편집적 렌즈를 제공한다. 독립적인 당사자들은 파싱에 충분히 엄격한 공유 계층을 필요로 하며, 그다음 각 구현자는 어떤 호환 가능한 능력을 운용할지 지역적으로 결정한다. 기능은 그 문서가 발표되거나 그 번호가 나타난다고 운영 현실이 되는 것이 아니라, 구현과 검증, 사용을 통해 그렇게 된다.
이것은 회고적 비교이며, HTTP의 저자들이 Lu Heng의 조직론이나 분산 원장 관련 아이디어를 예견했거나 지지했다는 증거가 아니다. 여기서의 유용성은 더 좁다. 발행된 RFC, 선언된 버전 번호, 설치된 프로그램, 사용된 기능, 완료된 작업을 서로 분리된 증거 계층으로 유지하는 것이다.
RFC 2068은 그 숫자에 세계적인 증명 권한을 부여하지 않았다. 약속의 주인을 지정했다. 메시지를 만드는 각 당사자는 다음 홉에 놓는 선언에 대해 책임지고, 새것을 선택한 당사자는 아직 채택하지 않은 이들을 위한 유효한 경로를 유지할 책임이 있다.
출처
- RFC 1945 — Hypertext Transfer Protocol — HTTP/1.0
- RFC 2068 — Hypertext Transfer Protocol — HTTP/1.1
- RFC Editor의 RFC 2068 페이지
- RFC 2145 — Use and Interpretation of HTTP Version Numbers
- RFC 2616 — Hypertext Transfer Protocol — HTTP/1.1
- RFC 7230 — HTTP/1.1 Message Syntax and Routing
- RFC 9110 — HTTP Semantics
- Lu Heng — Minimum Initial Specification, Localized Future Decision, and Voluntary Adoption
회원 브리핑
프로필 심층 컨텍스트
올바른 멤버십 등급으로 로그인하면 전체 브리핑과 출처 노트를 볼 수 있습니다.
Strategic Circle 전용
Strategic Circle
모든 독자에게 공개됩니다. 가입 후 로그인하면 프로필 브리핑를 열람할 수 있습니다.
Strategic Circle 가입하기Leadership Alliance 전용
Leadership Alliance
자격을 갖춘 IP 자산 소유자 및 운영진을 위한 콘텐츠입니다. 로그인하면 Leadership Alliance 브리핑을 열람할 수 있습니다.
Leadership Alliance 가입하기





