요약
- RFC 3076은 손대지 않은 파일을 정준화하지 않았다. XML 프로세서가 먼저 옥텟 스트림을 XPath 노드 집합으로 변환하여 정준 직렬화가 시작되기 전에 정보를 정규화하고 전개했다.
- 동일한 정준 바이트는 특정 데이터 모델, 주석 선택 및 알고리즘에 대한 정확한 비교 영수증이었다. 그러나 원본 XML을 재구성하거나 모든 DTD 및 기본 URI 사실을 보존하거나 응용 고유의 의미를 결정하지는 못했다.
안정적인 스트림은 중간에서 시작되었다
2001년 3월, RFC 3076과 W3C 권고안 '정준 XML 버전 1.0'은 실용적인 문제를 다루었다. XML은 많은 응용 프로그램이 동일하다고 여기는 정보를 둘 이상의 물리적 표기로 허용했다. 속성 순서는 달라질 수 있고, 문자 인코딩도 달라질 수 있으며, 빈 요소는 축약형 또는 확장형으로 쓰일 수 있었다. 개체 참조와 리터럴 치환 텍스트는 동일한 파싱 결과로 귀결될 수 있었다. 디지털 서명과 기타 비교 작업에는 하나의 재현 가능한 표현이 필요했다.
이 명세가 그 표현을 제공했다. 출력을 UTF-8로 인코딩하고, XML 선언과 문서 타입 선언을 제거하며, 빈 요소를 시작-종료 쌍으로 변환하고, 속성 값을 큰따옴표로 감싸고, 지정된 문자를 이스케이프하고, 불필요한 네임스페이스 선언을 제거하며, 네임스페이스 선언과 속성을 정렬했다. 주석을 포함할지 여부는 명시적 선택이었다. 잘 구성된 정준 결과가 동일한 방법으로 다시 통과하면 결과는 변하지 않았다.
이는 파일에서 파일로 가는 함수처럼 들린다. 그러나 RFC 3076은 더 정확하고 더 중대한 무언가를 기술했다. 즉, 형식적 입력이 XPath 노드 집합인 함수였다. 구현은 잘 구성된 XML 옥텟 스트림을 받아들여야 했지만, 먼저 그 스트림을 데이터 모델로 변환했다. 정준 변환기는 파싱이 끝난 뒤에야 문서를 만났던 것이다.
이 구분이 출력이 증명할 수 있는 것을 결정한다.
파서는 이미 작업을 수행한 상태였다
XPath 노드를 구성하기 위해 XML 프로세서는 줄바꿈과 속성 값을 정규화했다. CDATA 섹션을 문자 콘텐츠로 치환하고, 문자 참조를 해석하며 개체 참조를 파싱했다. 검증형 또는 적절히 구성된 프로세서는 DTD가 선언한 기본 속성을 공급할 수 있었다. 네임스페이스 처리는 네임스페이스 노드를 공급했다. 연속된 문자들은 UCS 문자 영역에서 텍스트 노드가 되었다.
이것들은 최종 직렬화기가 내린 겉모습 인쇄 선택이 아니었다. 직렬화될 대상을 확립한 더 이른 변환이었다.
두 개의 원본 파일을 상상해 보라. 하나는 문자를 그대로 쓰고, 다른 하나는 문자 참조를 쓴다. 하나는 내부 개체 이름을 담고, 다른 하나는 개체의 치환 텍스트를 담는다. 하나는 빈 요소 태그를 쓰고, 다른 하나는 시작 태그 바로 뒤에 종료 태그를 쓴다. 정준 XML은 파싱된 정보가 자신의 규칙 아래 동일할 때 이 차이들이 의도적으로 수렴하도록 허용한다. 그 수렴이 바로 산출물이다.
동시에 이는 정준 출력이 원본 구문의 가역적 보관함이 아니라는 뜻이기도 하다. XML 선언은 없다. 출력이 UTF-8이므로 원래 문자 인코딩은 사라졌다. DTD도 없다. 개체 경계는 치환 텍스트 속으로 사라졌고, CDATA 경계는 문자 콘텐츠 속으로 사라졌다. 원래의 속성 순서는 정의된 정렬에 굴복했다. 출력이 올바른 정준 형태이면서도 입력이 어떻게 표기되었는지를 답할 수 없는 상태일 수 있다.
따라서 이 영수증은 알고리즘 URI만이 아니라 파서 계약에서 시작된다. 어떤 바이트가 도착했는가? 어떤 기본 URI에서 왔는가? 어느 XML 버전과 선언된 인코딩이 사용되었는가? 검증이 활성화되었는가? 어느 외부 서브셋과 파싱된 개체가 언제 어디서 어떤 바이트로 해석되었는가? 어떤 기본값이 노드 집합에 들어갔는가? 최종 정준 스트림의 해시는 이런 입력들을 재구성하지 못한다.
정보는 사라지는 동시에 동작은 달라질 수 있었다
RFC 3076은 이 경계를 숨기지 않았다. 명세의 한계 절은 XPath 데이터 모델에서 사용할 수 없는 정보를 확인해 주었다. 외부 파싱 개체의 치환 텍스트에 특히 해당되는 기본 URI, 표기법과 외부 파싱되지 않는 개체 참조, 그리고 DTD가 선언한 속성 타입이 그것이다.
기본 URI 사례는 구체적이다. 외부 개체는 상대 URI를 담을 수 있다. 파서가 개체 참조를 콘텐츠로 치환하면 그 콘텐츠는 호스트 문서의 노드 집합으로 옮겨진다. 개체의 원래 기준 위치가 보존되지 않으면 동일한 상대 문자가 다른 곳에서 해석될 수 있다. 정준 바이트는 내부적으로 안정적일 수 있지만, 이후 응용 처리가 도달하는 자원은 달라질 수 있다. RFC 3076은 응용 프로그램이xml:base를 적절히 사용하거나 정준 형태가 필요해지기 전에 상대 URI를 해결하라고 조언했다.
DTD 경계는 두 방향으로 작동한다. 기본 속성은 이미 파싱된 요소에 추가되어 정준 출력에 나타날 수 있는데, 그것을 공급한 문서 타입 선언 자체는 제거된다. 한편ID,IDREF, 열거형,NOTATION등의 타입을 부여했던 선언들은 더 이상 정준 파일과 함께 있지 않다. 이후의 파서는 원래 타입 계약을 복구하지 못한 채 문자만 볼 수 있다. 정준 형태는 그것을 구성한 전체 계보가 아니라 결과 노드 표현을 기록한다.
파싱되지 않는 개체와 표기법도 같은 점을 보여 준다. XPath 모델은 응용이 외부 비-XML 데이터를 해석하는 데 사용할 수 있는 모든 바인딩을 옮겨 다니지 않았다. RFC는 이런 상황을 불가능하다기보다 드물다고 불렀다. '드물다'는 빈도 판단이지, 응용이 실제로 이에 의존할 때 입력 영수증을 지워도 좋다는 허가가 아니다.
노드 집합은 단순한 서브트리가 아니었다
RFC 3076은 문서 부분 집합의 정준화도 지원했다. XPath 노드 집합은 개별 노드들의 수학적 집합이며, '이 요소와 그 아래 전부'의 축약이 아니다. 요소는 선택되어도 그 속성이나 텍스트 자식은 선택되지 않을 수 있다. 제외된 노드는 부모가 존재한다는 이유만으로 렌더링되지 않는다. 생략된 조상이 선택된 자손에게 네임스페이스 맥락이나 상속 속성을 여전히 기여할 수 있다.
그래서 명세는 구성원들의 완전한 의미를 위해 필요한 정보를 보존할 책임을 입력 노드 집합의 생성자에게 두었다. 부분 집합의 정준 출력은 잘 구성된 XML조차 아닐 수 있다. 그것은 선택된 노드에 대해 정의된 옥텟 시퀀스이기는 했지만, 응용은 요소가 보인다는 사실만으로 완전성을 추론할 수 없었다.
이는 RFC 3075의 서명 질문과 구별된다. RFC 3075는 서명이 어떤 참조 데이터와 변환을 다루는지 물었다. RFC 3076은 정준 바이트가 방출되기 전에 어떤 대상이 존재하는지를 묻는다. 완벽한 정준 출력 위의 완벽한 서명도 그 옥텟을 만든 파서와 노드 집합 경계를 여전히 상속한다.
정준적이라고 모든 종류의 동등함을 뜻하지는 않았다
'정준'이라는 단어는 RFC가 주장한 것보다 더 큰 주장을 유혹한다. RFC 3076은 동일한 정준 형태가 정의된 범위 안에서, 그 한계에 따라 동등함을 확립한다고 말했다. 그리고 그 역을 목표로 명시적으로 거부했다. 두 문서는 서로 다른 정준 형태를 만들면서도 응용 입장에서는 여전히 동등할 수 있었다.
응용은 일부 공백을 무시할 수 있고,black과rgb(0,0,0)을 같은 색으로 다룰 수 있다. 다른 XML 관련 명세가 일반 정준 XML이 모르는 동등함을 정의할 수도 있다. 유니코드 문자 모델 정규화는 일반 단계로 수행되지 않았다. 네임스페이스 접두어는 의도적으로 보존되었다. 무분별하게 다시 쓰면 속성 값이나 텍스트에 박혀 있는 XPath나 QName 유사 문자열을 깨뜨릴 수 있기 때문이다.
따라서 정준 비교는 보편적 의미 엔진도 아니고, 임의의 바이트 정리도 아니었다. XPath 표현에 대한 신중하게 경계 지어진 정규화였다. 그 가치는 실행 가능하고 검증 가능하다는 데서 나왔다. 그 권위는 응용 고유의 의미가 시작되는 지점에서 멈췄다.
이후 개정판들은 이 경계를 다시 드러냈다
2001년 이후의 경험은 부분 집합 상속의 문제를 드러냈다. 2006년의 W3C 노트는 정준 XML 1.0이 그것을 올바르게 해석하는 데 필요한 조상 경로를 잃은 채 상대적인xml:base값을 선택된 자손에 복사할 수 있음을 보여 주었다. 이후의xml:id권고안도 정준 XML 1.0의 일반 규칙이 XML 네임스페이스의 속성을 복사한다는 이유만으로 식별자를 상속해서는 안 됨을 분명히 했다.
2008년 W3C 권고안으로 발표된 정준 XML 1.1은 부분 집합 규칙을 개정했다. 즉,xml:id를 상속하지 않고xml:base경로에 대한 특별한 수정 작업을 수행했다. 이 진화가 모든 C14N 1.0 구현이 실패했다는 증거는 아니다. 결정론적 직렬화기조차 자신에게 공급되는 데이터 모델과 맥락 규칙의 충분성에 의존함을 보여 준다.
배타적 XML 정준화는 관련이 있으나 다른 문제를 다루었다. 즉, 부분 집합의 네임스페이스 맥락이 다른 곳으로 옮겨지거나 삽입될 때 어떻게 동작해야 하는가이다. RFC 3275는 XML 서명 환경에서 정준 XML 1.0을 필수 방법으로 만들었다. 어느 발전도 정준 해시를 원본 소스 바이트, 신뢰된 외부 입력 또는 승인된 응용 동작의 증명으로 확대하지 않았다.
역사가 보존해야 할 영수증 사슬
보관용 비교, 서명, 감사 또는 마이그레이션을 위해서는 정준 다이제스트보다 더 많은 것을 보존하라. 수신 옥텟 해시와 검색 URI, 미디어 타입과 선언된 인코딩, 파서 신원과 설정, 검증 및 외부 자원 정책, 실제 소비된 모든 DTD와 외부 서브셋과 파싱된 개체, 유효 기본 URI, 네임스페이스 처리, 기본값 부여된 속성, 선택된 XPath 노드 집합, 주석 포함 여부, 정확한 정준화 방법과 버전, 그리고 정준 출력 해시를 남겨라.
그런 다음 사슬을 이어가라. 비교 또는 서명 결과, 응용 고유의 동등 규칙, 내려진 결정, 관찰된 효과를 기록하라. 정준 바이트 일치는 실제 질문에 답한다. 그것이 오해를 낳는 것은 모든 다른 질문에도 답하게 만들 때뿐이다.
Lu Heng의 이후 실행 코드 및 현실 계층 논의는 여기서 유용하게 드러난 관점을 제공한다. 실행 가능한 출력은 다른 구현이 재현할 수 있기 때문에 슬로건보다 강하다. 그러나 실행 영수증은 그 주위에 있는 원본, 권위, 의미, 결과 계층을 흡수하지 않는다. RFC 3076이 내구성을 지니는 이유는 정확히 하나의 계층을 선명하게 검증 가능하게 만들었기 때문이다.
출처
- RFC Editor의 RFC 3076 기록
- RFC 3076: Canonical XML Version 1.0
- IETF Datatracker의 RFC 3076 기록
- W3C 정준 XML 버전 1.0 권고안
- XPath 버전 1.0
- XML 1.0
- 정준 XML 1.0의 알려진 문제
- 정준 XML 버전 1.1
- 배타적 XML 정준화 버전 1.0
- RFC 3275: XML-Signature Syntax and Processing
- Lu Heng, “Running-Code Primacy”
- Lu Heng, “On Reality Layers, Symbolic Power, and Why Clarity Feels So Hostile”
회원 브리핑
프로필 심층 컨텍스트
올바른 멤버십 등급으로 로그인하면 전체 브리핑과 출처 노트를 볼 수 있습니다.
Strategic Circle 전용
Strategic Circle
모든 독자에게 공개됩니다. 가입 후 로그인하면 프로필 브리핑를 열람할 수 있습니다.
Strategic Circle 가입하기Leadership Alliance 전용
Leadership Alliance
자격을 갖춘 IP 자산 소유자 및 운영진을 위한 콘텐츠입니다. 로그인하면 Leadership Alliance 브리핑을 열람할 수 있습니다.
Leadership Alliance 가입하기





