Copyright © 2004-2021 W3C® (MIT, ERCIM, Keio, Beihang). W3C liability, trademark and permissive document license rules apply.
이 문서는 월드 와이드 웹을 위한 문자 모델 1.0: 기본 사항 [CHARMOD]를 바탕으로, 명세 작성자, 소프트웨어 개발자 및 콘텐츠 개발자에게 월드 와이드 웹에서 문자열 동일성 매칭에 대한 공통 참조를 제공하고 이를 통해 상호운용성을 높인다.
이 절은 이 문서가 공개된 시점의 상태를 설명한다. 다른 문서가 이 문서를 대체할 수 있다. 현재 W3C 공개 문서 목록과 이 기술 보고서의 최신 개정본은 https://www.w3.org/TR/의 W3C 기술 보고서 색인에서 찾을 수 있다.
의견 추적을 더 쉽게 하기 위해, 각 의견마다 별도의 이슈나 이메일을 제기하고 URL을 사용하여 의견을 다는 절을 가리켜 주기 바란다.
이 문서는 국제화 워킹 그룹이 워킹 그룹 노트로 공개했다.
이 명세에 대한 논의에는 GitHub Issues 사용을 권장한다.
워킹 그룹 노트로 공개되었다고 해서 W3C 회원의 지지를 의미하는 것은 아니다.
이 문서는 초안 문서이며 언제든지 다른 문서로 갱신, 대체 또는 폐기될 수 있다. 이 문서를 진행 중인 작업 이외의 것으로 인용하는 것은 적절하지 않다.
이 문서는 2017년 8월 1일 W3C 특허 정책에 따라 운영되는 그룹이 제작했다. 이 그룹은 이 문서가 W3C 권고안이 될 것으로 예상하지 않는다.
이 문서는 2020년 9월 15일 W3C 프로세스 문서의 적용을 받는다.
월드 와이드 웹을 위한 문자 모델의 목표는 W3C의 보편적 접근 목표에 따라 언어, 문자, 문자 체계 또는 문화적 관습과 관계없이 모든 사람이 웹을 쉽게 사용할 수 있도록 하는 것이다. 이 목표를 달성하기 위한 기본 전제 조건 중 하나는 전 세계에서 사용되는 문자를 잘 정의되고 잘 이해된 방식으로 전송하고 처리할 수 있어야 한다는 것이다.
이 문서는 월드 와이드 웹을 위한 문자 모델: 기본 사항 [CHARMOD]를 기반으로 한다. 이 문서의 개념을 이해하는 것은 이 문서를 성공적으로 이해하고 적용하는 데 중요하다.
월드 와이드 웹을 위한 문자 모델의 이 부분은 문자열 매칭, 즉 명세나 구현이 두 문자열 값이 서로 같은지 다른지를 정의하는 과정을 다룬다. 이 문서는 의미적으로 동등한 텍스트가 서로 다르게 인코딩될 수 있는 방식과, 이것이 형식 언어 (예: 웹을 구성하는 형식과 프로토콜에서 사용되는 언어)에 중요한 매칭 작업에 미치는 영향을 설명한다.
이 명세의 주요 대상 독자는 W3C 명세 개발자이다. 이 명세와 그 일부는 다른 W3C 명세에서 참조할 수 있으며, 이 명세는 W3C 명세뿐 아니라 다른 명세에 대한 적합성 기준을 정의한다.
이 명세의 다른 대상 독자에는 소프트웨어 개발자, 콘텐츠 개발자 및 W3C 외부의 명세 작성자가 포함된다. 소프트웨어 개발자와 콘텐츠 개발자는 W3C 명세를 구현하고 사용한다. 이 명세는 W3C 명세를 구현하고 사용하는 구현(소프트웨어)과 콘텐츠에 대한 일부 적합성 기준을 정의한다. 또한 소프트웨어 개발자와 콘텐츠 개발자가 W3C 명세의 문자 관련 조항을 이해하는 데 도움을 준다.
이 명세에서 설명하는 문자 모델은 명세 작성자, 소프트웨어 개발자 및 콘텐츠 개발자에게 월드 와이드 웹에서 일관되고 상호운용 가능한 텍스트 조작을 위한 공통 참조를 제공한다. 이 세 그룹이 함께 협력하면 전 세계적으로 접근 가능한 웹을 구축할 수 있다.
이 문서는 문서 형식에서 문자열 동일성 매칭을 위한 규칙과 절차를 정의함으로써, 이 문제와 관련된 웹의 기본 구성 요소 중 하나를 정의한다. 이러한 규칙은 문서 형식에서 사용되는 식별자와 구조적 마크업(구문 콘텐츠)을 대상으로 하며, 각각의 일관된 처리를 보장하도록 설계되었고 명세 작성자를 대상으로 한다. 이 절은 구현자를 대상으로 한다.
이 문서는 두 개의 주요 절로 나뉜다.
첫 번째 절은 문자열 매칭과 관련된 문제, 유니코드와 대소문자 접기가 이러한 문제에 미치는 영향, 그리고 이러한 문제를 해결하는 데 사용할 수 있는 다양한 쟁점과 정규화 메커니즘을 제시한다.
두 번째 절은 W3C 명세에서 정의되는 많은 문서 형식과 같은 형식 언어에서 사용할 문자열 동일성 매칭에 대한 요구사항과 권장사항을 제공한다. 이는 주로 웹을 기능적으로 만들고 문서 작성자에게 일관된 결과를 제공하는 데 관련된다.
이 절은 이 명세에서 다루는 주제에 대한 역사적 배경을 제공한다.
문자 모델의 핵심에는 유니코드 표준 [Unicode]과 ISO/IEC 10646 [ISO10646]이 공동으로 정의한 범용 문자 집합(UCS)이 있다. 이 문서에서 Unicode는 범용 문자 집합의 동의어로 사용된다. 성공적인 문자 모델은 전 세계의 문자 체계, 문자 및 언어로 작성된 웹 문서가 (그리고 서로 다른 플랫폼에서) 전 세계 웹 사용자에 의해 교환되고, 읽히고, 검색될 수 있게 한다.
유니코드 표준 [Unicode]의 첫 몇 장은 유용한 배경 읽을거리를 제공한다.
이 명세의 중요한 부분 개발에 영향을 준 요구사항에 대한 정보는 문자열 동일성 매칭 및 문자열 인덱싱 요구사항 [CHARREQ]을 참조하라.
이 절에는 이 문서에 특화된 용어와 표기법이 포함되어 있다.
웹은 텍스트 기반 형식과 프로토콜 위에 구축되어 있다. 문자열 매칭이나 검색을 효과적으로 설명하려면, 요구사항과 세부사항이 크게 달라지므로 주어진 형식이나 프로토콜 내의 다양한 종류의 텍스트에 대해 말할 수 있게 해 주는 용어를 확립할 필요가 있다.
유니코드 코드 포인트(또는 "코드 포인트")는
각 유니코드 문자에 할당된 숫자 값을 가리킨다. 유니코드 코드 포인트의 범위는
0부터
0x10FFFF까지이다. (문자 인코딩 용어에 대한
더 자세한 논의는 [CHARMOD]의
4.1절을 참조하라.)
유니코드 코드 포인트는 U+hhhh로 표기되며, 여기서 hhhh는 최소 네 자리, 최대 여섯 자리의
16진수 숫자 시퀀스이다. 예를 들어 문자 € [U+20AC
EURO SIGN]의 코드 포인트는 U+20AC이고, 문자 😺 [U+1F63A SMILING CAT FACE WITH OPEN MOUTH]의
코드 포인트는 U+1F63A이다.
이 문서의 예에서 사용되는 일부 문자는 특정 장치나 표시 장치에서 의도한 대로 나타나지 않을 수 있다. 일반적으로 이는 로컬에 설치된 문자별 글꼴이 없거나 특정 렌더링 시스템의 다른 제한 때문이다. 이 문서는 여러 비라틴 문자에 대한 대체 글리프를 제공하기 위해 Webfont를 사용하지만, 장치가 해당 글꼴 표시를 지원하지 않을 수도 있다. 가능한 범위에서 편집자는 예가 그럼에도 이해 가능하게 유지되도록 노력했다.
레거시 문자 인코딩은 유니코드 문자 집합의 전체 문자 레퍼토리를 인코딩하지 않는 문자 인코딩 형식이다.
트랜스코더는 두 문자 인코딩 사이에서 텍스트를 변환하는 과정이다. 이 문서에서는 가장 일반적으로 레거시 문자 인코딩에서 UTF-8과 같은 유니코드 인코딩 형식으로 변환하는 과정을 가리킨다.
자연어는 인간이 사용하는 말, 글 또는 수어 의사소통을 말한다(여기도 참조 [LTLI])
구문 콘텐츠는 문서 형식이나 프로토콜의 구조에 속하는 모든 텍스트이다. 이 정의에는 일반적으로 "마크업"으로 여겨지는 값도 포함되지만, HTTP 헤더의 필드 이름과 같은 다른 값도 포함될 수 있다. 구문 콘텐츠는 형식이나 프로토콜의 구조를 형성하는 모든 문자로 구성된다. 예를 들어, <와 >(그리고 이들이 둘러싸는 요소 이름과 다양한 속성)는 HTML 문서의 구문 콘텐츠 일부이다.
구문 콘텐츠는 일반적으로 명세 또는 여러 명세에 의해 정의되며, 주어진 프로토콜이나 형식에 대해 정의되고 예약된 키워드뿐 아니라 문서 작성자가 문서의 ("콘텐츠"가 아니라) 구조를 형성하기 위해 정의하는 문자열 토큰과 식별자를 모두 포함한다.
어휘는 형식이나 프로토콜에서 예약 키워드 및/또는 사용자 제공 값(예: 식별자)을 할당하기 위한 규칙의 목록이다. 여기에는 서로 다른 위치에 나타날 수 있는 문자의 범위, 순서 또는 유형에 대한 제한이 포함될 수 있다.
예를 들어, HTML은 요소와 속성의 이름뿐 아니라 열거형 속성 값도 정의하며, 이는 HTML 구문 콘텐츠의 "어휘"를 정의한다. 또 다른 예는 ECMAScript로, 식별자나 변수 이름의 시작 또는 본문에 나타날 수 있는 문자의 범위를 제한한다. 문자열 리터럴의 값과 같은 다른 경우에는 서로 다른 규칙을 적용한다.
어휘 내의 값은 크게 두 부류로 나뉜다. 하나는 사람이 보고, 읽고, 상호작용하도록 의도된 값(따라서 자연어 텍스트를 포함할 것으로 기대될 수 있음)이고, 다른 하나는 애플리케이션 또는 프로토콜 내부용이며 사람과의 상호작용을 의도하지 않은 값이다.
사용자 대면 식별자는 어휘에서 사용자가 정의하거나 할당한 식별자로, 최종 사용자에게 적어도 잠재적으로 보이도록 의도된 것이다(따라서 지역화 가능 콘텐츠이다).
애플리케이션 내부 식별자는 어휘에서 사용자가 정의하거나 할당한 식별자로, 문서 형식이나 프로토콜 내부용이며 사람과의 상호작용을 의도하지 않은 것이다. 이러한 값은 일반적으로 지역화 가능 콘텐츠가 아니다.
사용자 제공 값은 구문 콘텐츠 중
어휘에서
예약되지 않은 것으로, 주어진 형식이나 프로토콜의 예약 키워드와 구별되며 사용자가 할당한다.
사용자는 일반적으로 자신의 사용자 제공 값이 자신이 선호하는
자연어의 단어나 구문일 수 있기를 기대한다. 이것이 바로
[CHARMOD]가
"명세는 U+0000부터 U+10FFFF까지의 유니코드 코드 포인트 전체 범위에서
임의로 코드 포인트를 제외해서는 안 된다(SHOULD NOT)"라고 권장하는 이유이다.
지역화 가능
콘텐츠는 사람이 읽을 수 있는 텍스트로 의도된 문서 콘텐츠를 가리키며, 문서 구조의 일부를 이루는
주변 또는 삽입된 구문 콘텐츠는 아니다. 구문 콘텐츠에는 지역화 가능 콘텐츠가 포함될 수 있다는 점에 유의하라.
예를 들어 [HTML] img 요소가 이미지 설명을 담은 alt 속성을
갖는 경우가 그렇다.
리소스는 이 문서의 맥락에서
지역화 가능 콘텐츠와,
이를 둘러싸거나 포함하는 식별자 같은
구문 콘텐츠를 모두
포함하는 주어진 문서, 파일 또는
프로토콜 "메시지"이다. 예를 들어 일부 CSS와 몇 개의
script 태그 안에 포함된 JavaScript도 포함하는 HTML 문서에서,
파일로서 고려한 전체 HTML 문서가 리소스이다. 이 용어는 [RFC3986]에서 사용되는
'resource'라는 용어와 의도적으로 유사하지만, 여기서는 느슨하게 적용된다.
자소는 어떤 텍스트의 시각적 표현에서
일반적인 사용자가 하나의 단위(문자
)로 인식할
하나 이상의 문자 시퀀스이다. 자소는 정렬이나 텍스트 선택과 같은
여러 텍스트 작업에서 중요하므로, 사용자가 인식하는 각 문자 사이의
경계를 계산할 수 있어야 한다. 유니코드는
Unicode Standard Annex #29: Text Segmentation [UAX29]에서
자소를 계산하기 위한 기본 메커니즘을 정의하고, 이 근사치를
자소 클러스터라고
부른다. 정의된 기본 자소 클러스터에는
두 가지 유형이 있다. 달리 명시하지 않는 한, 이 문서에서 자소
클러스터는 확장 기본 자소 클러스터를 가리킨다. (자소 클러스터에 대한 논의는
유니코드 표준 [Unicode]의 2절에도 제시되어 있다. 또한
The Unicode Standard 버전 8.0의 2.11절
끝부분 근처를 비교하라.)
서로 다른 자연어는 서로 다른 요구를 가지므로, 자소 클러스터에도 때때로 맞춤 조정이 필요할 수 있다. 예를 들어 슬로바키아어 사용자는 기본적으로 두 개의 자소 클러스터인 "ch"를 하나의 자소 클러스터로 다루고자 할 수 있다. 문자열 콘텐츠의 언어와 최종 사용자의 선호 사이의 상호작용은 복잡할 수 있음에 유의하라.
이 절은 위에서 정의한 용어 중 일부를 예시한다. 설명을 위해 다음의 작은 HTML 파일을 예로 사용한다(참조를 위해 줄 번호를 추가함).
1 <html lang="en" dir="ltr">
2 <head>
3 <meta charset="UTF-8">
4 <title>Shakespeare</title>
5 </head>
6 <body>
7 <img src="shakespeare.jpg" alt="William Shakespeare" id="shakespeare_image">
8 <p>What’s in a name? That which we call a rose by any other name would smell as sweet.</p>
9 </body>
10 </html>
’는 구문 콘텐츠의 일부이다.)
William Shakespeare)도 지역화 가능 콘텐츠이다.
위의 모든 텍스트(텍스트 파일의 모든 텍스트)는 리소스를 구성한다. 어떤
리소스에는 지역화 가능 콘텐츠가
전혀 없을 수도 있다(주황색 사각형으로 보이도록 스타일링된 네 개의 빈
div 요소로 구성된 HTML 문서를 생각해 보라). 또한 리소스가 구문 콘텐츠를
전혀 포함하지 않고 오직 지역화 가능 콘텐츠만으로
구성될 수도 있다. 예를 들어 Hamlet의 독백을 담은 일반 텍스트 파일이 그렇다.
또한 HTML 엔터티 ’가 지역화 가능 콘텐츠 안에 나타나며 이 리소스에서
지역화 가능 콘텐츠와 구문 콘텐츠 양쪽 모두에 속한다는 점에도 주목하라.
비규범으로 표시된 절뿐 아니라, 이 명세의 모든 작성 지침, 도표, 예 및 참고는 비규범이다. 이 명세의 그 밖의 모든 내용은 규범적이다.
이 문서의 핵심어 MAY, MUST, MUST NOT, OPTIONAL, RECOMMENDED, SHOULD, 및 SHOULD NOT은 여기에 표시된 것처럼 모두 대문자로 나타날 때에만 BCP 14 [RFC2119] [RFC8174]에 설명된 대로 해석해야 한다.
이 문서는 다른 명세의 작성자를 위한 모범 사례뿐 아니라 구현 및 콘텐츠 작성자를 위한 권장사항도 설명한다. 이러한 모범 사례는 Internationalization Working Group의 문서 Internationalization Best Practices for Spec Developers [INTERNATIONAL-SPECS]에서도 찾을 수 있으며, 이 문서는 W3C 명세의 모든 국제화 모범 사례에 대한 일반 참조로 제공되도록 의도되었다.
이 문서의 모범 사례는 특정 권장사항에 관한 Internationalization Working Group의 의도를 명확히 하기 위해 [RFC2119] 키워드를 사용한다. 이 문서의 권장사항을 따르면 W3C의 "광범위 검토" 과정, 구현 중, 또는 작성자가 생산하는 콘텐츠에서 문제가 발생하는 것을 피하는 데 도움이 될 수 있다. 이 문서 자체는 규범적이지 않으며 때때로 개정될 수 있다.
명세는 다음을 만족하는 경우 이 문서에 대한 적합성을 주장할 수 있다.
명세에 부과된 요구사항은 그 명세에 적합하다고 주장하는 구현이나 콘텐츠에 요구사항이 간접적으로 부과되도록 할 수 있다.
이 명세에 절차적 설명이 포함되어 있는 경우, 이는 원하는 외부 동작을 지정하는 한 방법으로 이해해야 한다. 구현은 관찰 가능한 동작에 영향을 주지 않는 한 동일한 결과를 달성하기 위해 다른 수단을 MAY 사용할 수 있다.
웹은 주로 문자 데이터에 기반한 문서 형식과 프로토콜로 구성된다. 이러한 형식이나 프로토콜은 주로 어떤 형태의 구조적 마크업 또는 리소스로 이루어진 텍스트 파일들의 집합으로 볼 수 있다. 이러한 구문 콘텐츠나 문서 데이터를 처리하려면 매칭(정규 표현식 포함), 인덱싱, 검색, 정렬 등과 같은 문자열 기반 작업이 필요하다.
사용자, 특히 구현자는 때때로 유사한 문자열이 매칭되거나 매칭되지 않는 방식, 또는 텍스트, 특히 구문 콘텐츠에 적용할 수 있는 여러 변환의 효과에 대해 순진한 기대를 갖는다. 이는 웹에서 이루어지는 여러 유형의 텍스트 처리에도 해당된다.
근본적으로 웹은 문서에서 텍스트가 표현될 수 있는 다양한 방식에 민감하므로, 동일한 텍스트가 서로 다른 방식으로 표현될 수 있다는 점을 고려하지 않으면 사용자를 혼란스럽게 하거나 예기치 못한, 또는 답답한 결과를 초래할 수 있다. 아래 절에서 이 문서는 웹에서 텍스트에 대한 사용자의 인식과 웹이 의존하는 문자열 처리 양쪽에 영향을 미치는 다양한 유형의 텍스트 변이를 검토한다.
일부 문자와 문자 체계는 대문자, 소문자, 제목형 대소문자를 구분한다. 인도의 브라흐미계 문자, 아랍 문자, 중국어, 일본어 또는 한국어를 표기하는 데 사용되는 문자 등 대부분의 문자는 대소문자 구분을 갖지 않지만, 일부 중요한 문자 체계는 이를 갖는다. 이러한 문자 체계의 예로는 이 문서 대부분에서 사용되는 라틴 문자뿐 아니라 그리스 문자, 아르메니아 문자, 키릴 문자 등이 있다.
대소문자 매핑은 문자를 대문자, 소문자 또는 제목형 대소문자와 같은 특정 대소문자 형태로 변환하는 과정이다. 대소문자 구분이 있는 문자 체계에 대해, 유니코드는 각 유니코드 코드 포인트마다 기본 대문자, 소문자 및 제목형 대소문자 문자 매핑을 정의한다. 대소문자 매핑은 처음에는 단순해 보인다. 그러나 다양한 언어에서 유니코드 전체 범위를 다룰 때 고려해야 할 변이가 있다.
대소문자 접기는 대소문자만 다른 두 텍스트를 비교 목적으로 동일하게 만드는 과정, 즉 문자열 매칭을 위한 과정이다. 이는 주로 표시 목적을 위한 대소문자 매핑과는 구별된다. 기본 대소문자 매핑과 마찬가지로, 유니코드는 각 유니코드 코드 포인트마다 기본 대소문자 접기 매핑("case folding")을 정의한다. 유니코드는 두 가지 형태의 대소문자 접기를 정의하며, 아래에서 이를 살펴본다.
대부분의 문자 체계는 대소문자 구분이 없으므로, 대소문자 매핑과 마찬가지로 대부분의 유니코드 코드
포인트는 대소문자 접기를 필요로 하지 않는다. 대소문자 접기가 있는 코드 포인트의 경우,
대부분은 다른 하나의 일치하는(일반적으로 소문자) 코드 포인트로 단순하고 직접적으로 매핑된다.
유니코드는 이 접기 집합을 common이라고 부르는데, 유니코드가 정의한
두 유형의 대소문자 접기가 모두 이를 포함하기 때문이다.
몇몇 문자는 하나의 유니코드 코드 포인트를 두 개 이상의 코드 포인트로 매핑하는 대소문자 접기를 가진다.
이러한 대소문자 접기 집합을 full 대소문자 접기라고 한다. full 및 common 대소문자 접기는 함께 사용되어
유니코드 전체에 대한 기본 대소문자 접기를 제공한다. 이 문서에서는 이러한 형태의 대소문자 접기를
전체
대소문자 접기 또는 Unicode full이라고 부른다.
일부 애플리케이션은 대소문자 접기 작업을 수행할 때 추가 저장 공간을 할당할 수 없기 때문에,
유니코드는 일반적으로 더 많거나 더 적은 코드 포인트로 접힐 코드 포인트를 비교 목적으로 대신
하나의 코드 포인트로 매핑하는 simple 대소문자 접기를 제공한다.
전체 접기와 달리, 이 접기는 항상 텍스트의 내용(그리고 잠재적으로 의미)을 변경한다.
전체 대소문자 접기와 마찬가지로,
단순 대소문자
접기 또는 Unicode simple
대소문자 접기는 유니코드 전체 범위를 포괄하기 위해 simple 매핑과
common 매핑을 결합한 것이다. Unicode simple은 웹에서 사용하기에
적절하지 않다.
대소문자 접기는 문자열에서 정보를 제거하며, 이 정보는 나중에 복구할 수 없다는 점에 유의하라. 예를 들어 독일어에서 두 개의 s 글자가 접기 전 텍스트의 ß를 반드시 나타내는 것은 아니다.
대소문자 매핑과 대소문자 접기의 또 다른 측면은 그것이 언어에 민감할 수 있다는 점이다. 유니코드는 각 인코딩된 문자에 대해 기본 대소문자 매핑과 대소문자 접기를 정의하지만, 이것들은 기본값일 뿐 모든 경우에 적절하지는 않다. 일부 언어는 특정 언어적 요구를 충족하기 위해 대소문자 매핑을 맞춤 조정해야 한다. 그 한 예는 라틴 문자로 쓰이는 튀르크계 언어이다.
위의 예(및 이 문서 전반)는 매칭 목적의 대소문자 접기에 초점을 맞추지만,
대소문자 매핑 역시 언어별로 다르다는 점에 유의하라. 터키에서 두 번째로 큰 도시의 이름은
"Diyarbakır"이며,
점 있는 글자와 점 없는 글자 i를 모두 포함한다.
일부 문서 형식이나 프로토콜은 자신들이 정의하는 어휘나 해당 형식 또는 프로토콜에서 허용되는 사용자 제공 값에서 대소문자 변이를 무시함으로써 상호운용성을 돕거나 콘텐츠 작성자를 지원하려고 한다.
때때로 대소문자는 의미적으로 중요하지 않거나 사용자가 완전히 제어할 수 없는 방식으로 달라질 수 있다. 이는 문서를 검색할 때 특히 그렇지만, 식별자와 같이 사용자 또는 콘텐츠가 생성한 값을 매칭하기 위한 규칙을 정의할 때에도 때때로 적용될 수 있다. 이러한 상황에서는 대신 대소문자를 구분하지 않는 매칭이 바람직할 수 있다.
어휘를 정의할 때 중요한 고려사항 중 하나는 값이 유니코드의 ASCII [ASCII] 하위 집합으로 제한되는지, 아니면 어휘가 라틴 문자 위의 악센트나 비라틴 문자를 포함한 광범위한 유니코드처럼 잠재적으로 더 복잡한 대소문자 접기 요구사항을 가지는 문자의 사용을 허용하는지이다. 이러한 서로 다른 요구사항을 다루기 위해, 이 문서는 문서 형식이나 프로토콜에서 문자열 동일성 매칭을 목적으로 네 가지 유형의 대소문자 접기 매칭을 정의한다.
대소문자 구분 매칭: 코드 포인트를 대소문자 접기 없이 직접 비교한다.
ASCII 대소문자 비구분 매칭은 [INFRA]에 정의되어 있다. 이 정의는 0x41부터 0x5A(A부터 Z) 범위의 모든 ASCII 코드 포인트가 0x61부터 0x7A(a부터 z) 범위의 대응하는 코드 포인트로 매핑된 것처럼 두 코드 포인트 시퀀스를 비교한다. 어휘 자체가 ASCII로 제한되는 경우 ASCII 대소문자 비구분 매칭이 요구될 수 있다.
유니코드 대소문자 비구분 매칭은 두 입력 시퀀스 모두에 Unicode full 대소문자 접기(위 참조)가 적용된 것처럼 두 코드 포인트 시퀀스를 비교한다.
언어 민감 대소문자 구분 매칭은 문서 형식이나 프로토콜이 구문 콘텐츠의 언어에 관한 정보를 포함하고, 언어 민감 대소문자 접기를 합리적으로 적용할 수 있는 드문 경우에 유용하다. 이러한 대소문자 접기는 유니코드 컨소시엄의 Common Locale Data Repository [UAX35] 프로젝트에 정의되어 있다.
대소문자 접기를 처리하는 방법에 대한 조언은 § 3.2.6 대소문자 접기에 대한 추가 고려사항을 참조하라.
유니코드 텍스트에서는 다른 종류의 변이가 발생할 수 있다. 때로는 서로 다른 여러 유니코드 코드 포인트 시퀀스를 사용하여 같은 추상 문자를 나타낼 수 있다. 코드 포인트를 비교하여 텍스트를 검색하거나 매칭할 때, 이러한 인코딩상의 변이는 사용자가 같을 것으로 기대하는 텍스트 값이 매칭되지 않게 만든다.
애플리케이션은 서로 다른 코드 포인트 시퀀스를 사용하는 텍스트들 사이에서 의미적 동등성을 찾아야 하므로, 유니코드는 의미적으로 동등한 두 텍스트를 동일하게 만드는 수단인 유니코드 정규화 형식 [UAX15]을 정의한다.
리소스는 이러한 변이의 영향을 받기 쉽다. 웹에서 그 명세와 구현은 텍스트의 유니코드 정규화를 요구하지 않는 경우가 많고, 나중에 구문 콘텐츠(사용자 제공 값 포함)와 지역화 가능 콘텐츠를 처리할 때 사용되는 문자열 매칭 알고리즘을 고려하지도 않기 때문이다. 이러한 이유로 콘텐츠 개발자는 이후 문제를 피하기 위해 일관된 표현을 제공했는지 확인해야 한다.
그러나 사용자는 주어진 리소스 또는 리소스 집합이 일관된 텍스트 표현을 사용하는지 확인하기 어려울 수 있다. 그 차이는 보통 텍스트로 볼 때 보이지 않기 때문이다. 따라서 도구와 구현은 시각적으로 또는 논리적으로 동등한 문자열이 (사용자의 생각에는) "당연히" 매칭되어야 하는데도 서로 다른 값으로 간주될 때 사용자가 겪는 어려움을 고려해야 한다. 사용자가 이러한 차이를 보고 및/또는 적절히 정규화할 수 있는 수단을 제공하면, 최종 사용자가 원본 문서의 보이지 않는 차이에서 비롯되는 실패를 피할 수 있다. 예를 들어, W3C Validator는 HTML 문서가 유니코드 정규화 형식 C에 완전히 속하지 않을 때 경고한다.
유니코드는 문자 사이의 두 가지 동등성 유형인 정준 동등성과 호환 동등성을 정의한다.
정준 동등성은 같은 추상 문자를 나타내는 유니코드 코드 포인트 또는 유니코드 코드 포인트 시퀀스 사이의 근본적인 동등성이다. 정준적으로 동등한 시퀀스는 이상적으로 같은 시각적 모양을 가져야 하며(다소 다르게 보이게 만드는 많은 요인이 있을 수는 있지만), 동일한 것처럼 다루고 처리해야 한다. 유니코드는 이렇게 다르게 인코딩되었지만 정준적으로 동등한 두 텍스트 사이의 주요 차이를 제거하는 정준 분해라는 과정을 정의한다.
유니코드가 정의한 정준 동등성의 예는 다음과 같다.
호환 동등성은 같은 추상 문자를 나타내지만 서로 다른 시각적 모양이나 동작을 가질 수 있는 유니코드 문자 또는 유니코드 문자 시퀀스 사이의 더 약한 동등성이다. 일반적으로 호환 분해라고 하는 과정은 위 첨자, 아래 첨자, 회전, 원 문자 등과 같은 서식상의 변이를 제거하지만, 다른 변이도 발생한다. 많은 경우 호환 분해를 가진 문자는 의미적 성격의 구별을 나타내므로, 구별되는 문자를 그 호환 분해로 대체하면 텍스트의 의미가 바뀔 수 있다. 호환 분해 이후에 동등한 텍스트는 그 전에는 동일한 것으로 인식되지 않은 경우가 많으며, 형식 언어에서는 동등한 것으로 다루어서는 안 된다(SHOULD NOT).
위 표에서, 예시된 문자가 단지 문맥이나 스타일로 인한 표시상의 변이가 아니라 실제 유니코드 코드 포인트라는 점에 유의하는 것이 중요하다. 각 문자는 여러 레거시 문자 인코딩과의 호환성을 위해 유니코드에 인코딩되었다. 이들은 호환 문자가 아닌 대응 문자에 사용되는 일반적인 표시 처리와 혼동해서는 안 된다.
예를 들어, 대부분의 아랍 문자 텍스트는 유니코드의 아랍 문자 블록에 있는 문자 (U+0600부터 시작)를 사용한다. 텍스트를 표시하는 데 사용되는 실제 글리프는 단어 안의 위치(처음, 중간, 끝 또는 독립)에 기반한 글꼴과 텍스트 처리 논리를 사용하여 선택되며, 이 과정을 "셰이핑"이라고 한다. 위 표에는 아랍어 글자 ه [U+0647 ARABIC LETTER HEH]의 네 가지 표시 형태가 나와 있다. 표시된 문자는 U+FE00 블록의 호환 문자로, 각각 특정한 "위치별" 형태를 나타내며, 표시된 네 코드 포인트 각각은 일반 아랍어 글자 ه [U+0647 ARABIC LETTER HEH]로 호환 분해된다. 이러한 표시 형태는 동등한 표시 형태를 포함하는 레거시 문자 인코딩과의 왕복 인코딩 변환을 지원하기 위한 용도로만 의도되었다. 그 외의 경우, 글자 'heh'의 시퀀스를 포함하는 문자열은 단순히 일련의 U+0647 코드 포인트로 인코딩되며, 렌더링 시스템과 글꼴이 적절한 형태를 제공한다.
마찬가지로, 반각과 전각 형태 및 회전된 문자(세로쓰기 텍스트에 사용)의 변이는 주로 레거시 문자 인코딩과의 호환성을 위해 별도의 코드 포인트로 인코딩된다. 많은 경우 이러한 변이는 East Asian Width [UAX11]에 설명된 유니코드 속성과 관련된다. 세로쓰기 텍스트 표시 형태에 대한 논의는 Unicode Vertical Text Layout [UTR50]도 참조하라.
위에 표시된 것과 같이 호환 분해를 가진 문자의 경우, K 유니코드 정규화 형식은 텍스트를 "일반" 또는 "예상되는" 유니코드 코드 포인트로 변환한다. 그러나 이러한 호환 문자가 존재한다고 해서 일반적인 텍스트 레이아웃과 표시 과정에서 생성되는 유사한 모양의 변이가 유니코드 정규화의 영향을 받는다고 볼 수는 없다. 영향을 받지 않는다.
유니코드가 정의한 이 두 가지 동등성 유형은 다시 또 다른 한 쌍의 변이인 "분해"와 "조합"으로 묶인다. "분해"에서는 시각적 문자의 분리 가능한 논리적 부분이 기본 문자와 결합 마크의 시퀀스로 나뉘고, 결과 코드 포인트가 고정된 정준 순서로 놓인다. "조합"에서는 분해가 수행된 다음, 특정 규칙에 따라 결합 마크가 그 기본 문자와 다시 조합된다.
대략적으로 말해, NFC는 각 결합 문자 시퀀스 (기본 문자 뒤에 하나 이상의 결합 문자가 오는 시퀀스)를 가능한 한 정준적으로 동등한 조합 완료 문자로 대체하도록 정의되어 있다.
이것이 무엇을 의미하지 않는지 알아차리는 것이 매우 중요하다. 모든 문자 시퀀스에 조합 완료된 동등 문자가 있는 것은 아니므로, 결과 문자 시퀀스는 여전히 결합 마크를 포함할 수 있다. 실제로 앞에서 본 것처럼, 이 예의 데바나가리 모음과 같이 많은 문자 체계는 결합 마크 사용 외의 대안을 제공하지 않는다. 다른 경우에는 주어진 기본 문자와 결합 마크가 정규화 규칙에 의해 조합이 차단되기 때문에 조합 완료 문자로 대체되지 않는다. 예를 들어, 일부 인도계 문자는 대응하는 조합 완료 문자가 존재하더라도 조합 제외 규칙 때문에 특정 기본 문자와 발음 구별 기호의 시퀀스를 조합하지 않는다. 또한 두 문자가 원래라면 조합될 수 있더라도 그 사이의 다른 결합 마크에 의해 조합이 차단될 수 있다.
네 가지 유니코드 정규화 형식이 있다. 각 형식은 문자 코드로 이름이 붙는다.
유니코드 정규화는 이러한 시퀀스(및 같은 문자를 나타내는 그 밖의 잠재적 이스케이프 시퀀스)를 단 세 가지 가능한 변이로 줄인다. 그러나 유니코드 정규화가 모든 텍스트상의 구별을 제거하지는 않으며, 때로는 유니코드 정규화를 적용하면 주어진 맥락에서 구별되거나 의미 있는 의미가 제거될 수 있다. 예를 들면 다음과 같다.
NFKD 또는 NFKC)를
사용해 정규화하면 ASCII 문자 시퀀스
81/2가 된다.
많은 사용자는 특정 유니코드 정규화 형식이 적용된 문자열을 포함하여
동일하게 보이는 두 문자열이 실제로는 같은 기본 유니코드 코드 포인트를
사용하지 않을 수 있다는 사실에 놀란다. 여기에는 더 파괴적인 NFKC 및
NFKD 호환 정규화 형식이 적용된 문자열도 포함된다. 문자열, 토큰 또는 식별자가
시각적으로 같아 보이더라도 서로 다르게 인코딩될 수 있다.
유니코드 정준 정규화 형식은 주어진 추상 문자나 자소 클러스터에 사용할 수 있는 여러 서로 다른
코드 포인트 시퀀스를 같은 코드 포인트 시퀀스로 접는 데 관련된다. 그러나 논리적으로 구별되는
문자나 자소 클러스터도 여전히 같거나 매우 비슷하게 보일 수 있다. 한 쌍의 자소가 동일하게(또는 매우 비슷하게)
보일 때, 이를 동형문자라고 한다. 한 쌍의 자소가 비슷하게 보이거나
동형문자이지만 실제로는 논리적으로 다른 문자 또는 문자
시퀀스를 나타낼 때, 이들은 혼동
가능
하다고 한다.
동일하거나 동일해 보이는 모양의 예는 단일 문자 체계 안에서도 나타날 수 있다. 이는 "0"과 "O" 또는 "l"과 "1"처럼 모양이 비슷한 문자의 형태를 취할 수 있다. 그러나 다른 문자 체계나 서로 다른 호환 문자의 사용은 훨씬 덜 쉽게 구별되는 변이를 나타낼 수 있다. 어떤 경우에는 유니코드 정규화가 이들을 하나로 모으지만, 다른 많은 경우에는 그렇지 않다.
모양이 동일하거나 혼동 가능
한 문자는 스푸핑 및 기타 보안 위험을 초래할 수 있다.
이는 단일 문자 체계 안에서도, 별개의 문자 체계에 있는 유사한 문자에서도 참일 수 있다.
동형 글리프와 혼동 가능성에 대한 추가 논의와 예는 [UTS39]가
유용한 참고문헌 중 하나이다.
동일하거나 비슷하게 보이는 문자 외에도 반대 문제도 존재한다.
유니코드 정규화는 NFKC 및 NFKD 호환 형식조차도
같은 본질적 의미나 기능을 갖지만 모양이나 사용 방식이 다른 문자를 하나로 모으지 않는다.
예를 들어 U+002E(.)와 U+3002(。)는 모두 문장 끝 문장부호로
기능하지만, 두 문자는 구별되는 정체성을 가지므로 그 차이는 정규화로 제거되지 않는다.
대소문자를 구분하지 않는 방식으로 문자열을 매칭할 때 한 가지 복잡한 점은, 원래 문자열이 정규화되어 있었더라도 대소문자 접기 과정이 정규화되지 않은 문자열을 생성할 수 있다는 점이다. 문자열 비교는 코드 포인트 시퀀스의 매칭에 의존하므로, 매칭 과정이 신뢰할 수 있으려면 대소문자 접기가 적용된 각 문자열을 정규화해야 한다.
유니코드 정준 정규화 형식(NFC 또는 NFD)과 대소문자 접기는 함께 사용될 때 닫혀 있다. 즉, 한 문자열에 대소문자 접기를 적용한 뒤 NFD 또는 NFC를 적용하면, 같은 대소문자 접기나 유니코드 정규화 형식을 추가로 적용해도 다른 문자열이 나오지 않는다.
문자 사이의 호환 동등성 (다시 말해 NFKC/NFKD 형식)을 비교할 때는, 대소문자 접기 후 정규화 작업을 두 번 수행해야 한다. 호환 분해 단계가 대소문자 접기가 필요한 문자를 생성할 수 있고, 이어지는 대소문자 접기가 다시 정규화해야 하는 시퀀스를 생성할 수 있기 때문이다.
유니코드의 정준 대소문자 접기 매칭(규칙 [D145])과
호환 대소문자 접기 매칭(규칙 [D146]) 정의에는 여러
정규화 단계가 포함되어 있다. 이는 대소문자 없는 매칭을 수행하는 복잡성과 비용을 증가시킨다.
대소문자 접기를 수행하기 전의 초기 대소문자 접기 단계는 특정한 예외적 사례를 다루며,
이 절에서 자세히 설명한다.
유니코드의 대소문자 접기 매칭 과정에서 마지막 정규화 단계는 결과 문자열이 특정 유니코드 정규화 형식에 속하도록 보장하기 위해 존재한다. 결과로 생성된 대소문자 접기 문자열을 저장하거나 사용자에게 표시하려면, 대소문자 접기 작업으로 생성된 비정규화 시퀀스를 표시용으로 다시 정규화하는 것이 좋은 관행이다. 그러나 이 단계는 유니코드 정준 대소문자 접기 정규화 단계와 유니코드 호환 대소문자 접기 정규화 단계에서 OPTIONAL이다. 추가 정규화를 수행해도 문자열 비교 결과가 달라지지 않기 때문이다.
63개의 그리스어 조합 완료 문자는 문자 ͅ
[U+0345 COMBINING GREEK YPOGEGRAMMENI]를
포함하는 분해 매핑(즉, NFD 형식으로 정규화)을 가진다. 이 문자는 아래첨자 이오타를 나타내는
발음 구별 기호로, prosgegrammei 또는 ypogegrammeni라고 한다.
이 기호는 고대 또는 고전 그리스어에서 발견되는 정서법적 형태를 나타내며, 더 현대적인 언어 형태에는
존재하지 않는 소리를 나타낸다. 이러한 문자의 대문자 및 제목형 매핑은 이 결합 마크를 별도의
기본 글자인 iota로 분리한다. 제목형/대문자 매핑과의 일관성을 위해, 따라서 이러한
문자의 대소문자 접기 매핑에는 ι [U+03B9 GREEK SMALL LETTER IOTA]가 포함된다(앞서 설명했듯이, 유니코드 대소문자 접기는 일반적으로 소문자로 접는다).
이 63개 문자 중 하나가 결합 마크 뒤에 오는 경우에만, 대소문자 접기 전에 정준 분해를 적용하지 않으면 잠재적인 비교 불일치가 발생할 수 있다. 이러한 문자 시퀀스는 정규화된 형식이 아니며, 키보드와 기타 입력 과정을 통해 "자연스럽게" 만들기 어렵다.
예를 들어, 기본 문자와 발음 구별 기호의 이 조합을 나타내는 가장 일반적인 방법인 조합 완료 (NFC) 문자 ᾌ [U+1F8C GREEK CAPITAL LETTER ALPHA WITH PSILI AND OXIA AND PROSGEGRAMMENI]에서 시작하여 단지 대소문자 접기 변환만 수행하면 다음과 같은 결과를 얻게 된다. ἄι [U+1F04 GREEK SMALL LETTER ALPHA WITH PSILI AND OXIA + U+03B9 GREEK SMALL LETTER IOTA].
대신 같은 글자를 나타내는 완전히 분해된(NFD) 시퀀스인 ᾌ [U+0391 GREEK CAPITAL LETTER ALPHA + U+0313 COMBINING COMMA ABOVE + U+0301 COMBINING ACUTE ACCENT + U+0345 COMBINING GREEK YPOGEGRAMMENI]에서 시작하면, 결과는 ἄι [U+03B1 GREEK SMALL LETTER ALPHA + U+0313 COMBINING COMMA ABOVE + U+0301 COMBINING ACUTE ACCENT + U+03B9 GREEK SMALL LETTER IOTA]가 된다. 이 문자열을 NFC로 정규화하면 위 첫 번째 예와 같은 문자 시퀀스가 생성된다.
이 두 경우 모두, 급성 악센트는 뒤따르는 이오타가 아니라 알파 기본 문자와 연결된다.
그러나 반조합 완료 시퀀스 ᾌ [U+1F88 GREEK CAPITAL LETTER ALPHA WITH PSILI AND PROSGEGRAMMENI + U+0301 COMBINING ACUTE ACCENT]에서 시작하면, 결과는 ἀί [U+1F00 GREEK SMALL LETTER ALPHA WITH PSILI + U+03B9 GREEK SMALL LETTER IOTA + U+0301 COMBINING ACUTE ACCENT]가 되며, 여기서는 급성 악센트가 이오타와 연결된다. 이는 다른 것들과 매칭되도록 정규화할 수 없는 시퀀스를 생성한다(그리고 실제로는 원래 사용자가 인식한 문자와 다른 의미를 가지므로 올바르지 않다).
위에서 언급했듯이, 유니코드는 대소문자 접기 작업을 수행하기 전에 텍스트를 NFD로 정규화함으로써 이 매칭 문제를 해결한다. 그러면 ᾌ [U+1F8C GREEK CAPITAL LETTER ALPHA WITH PSILI AND OXIA AND PROSGEGRAMMENI]와 ᾌ [U+1F88 GREEK CAPITAL LETTER ALPHA WITH PSILI AND PROSGEGRAMMENI + U+0301 COMBINING ACUTE ACCENT]는 둘 다 분해된 버전, 즉 ᾌ [U+0391 GREEK CAPITAL LETTER ALPHA + U+0313 COMBINING COMMA ABOVE + U+0301 COMBINING ACUTE ACCENT + U+0345 COMBINING GREEK YPOGEGRAMMENI]와 같아진다. 이제 이 시퀀스를 대소문자 접기하고 정규화하면, 모든 경우에 대해 매칭되는 결과가 생성된다.
대부분의 문서 형식이나 프로토콜은 입력, 처리 또는 인코딩하기 어려운 문자를 포함할 수 있도록 이스케이프 메커니즘을 제공한다. 이러한 이스케이프 메커니즘은 주어진 리소스 안에서 문자를 표현하는 추가적인 동등 수단을 제공한다. 또한 문서에서 사용되는 문자 인코딩 체계로 표현되지 않는 유니코드 문자를 인코딩할 수 있게 한다.
문자 이스케이프와 포함의 확장은 문맥, 즉 문자열 매칭 작업을 수행할 때 어떤 구문 콘텐츠나 프로그래밍 언어가
적용되는 것으로 간주되는지에 따라 달라진다. XML 문서에
suçon은 없고 suçon이 있을 때,
문자열 suçon을 검색하는 경우를 생각해 보자. 검색이 일반
텍스트 편집기에서 수행되면 문맥은 일반 텍스트이다
(구문
콘텐츠나 프로그래밍 언어가
적용되지 않음). 따라서 ç 문자 이스케이프는 인식되지 않고,
확장되지 않으며 검색은 실패한다. 검색이 XML 브라우저에서 수행되면 문맥은
XML이고, XML이 정의한 문자 이스케이프가 확장되어 검색이 성공한다.
중간적인 경우로, 엔터티 참조를 확장하지 않은 채 XML 문서의 보기를 의도적으로 제공하는 XML 편집기를 들 수 있다. 이 경우 그 유사 XML 보기에서의 검색은 의도적으로 엔터티를 확장하지 않는다. 그 특정 문맥에서는 엔터티 참조가 포함으로 간주되지 않으며 확장될 필요가 없다.
예를 들어, € U+20AC
EURO SIGN은 HTML에서 16진수 엔터티
€ 또는 10진수 엔터티 €로도 인코딩될 수 있다.
JavaScript나 JSON 파일에서는 \u20ac 또는 \u{20AC}로 나타날 수 있고,
CSS 스타일시트에서는 \20ac로 나타날 수 있다. 이러한 모든 표현은
동일한 리터럴 문자 값인 €를 인코딩한다.
문자 이스케이프는 일반적으로 문서가 처리되고 형식이나 프로토콜 안의 문자열이 매칭되기 전에 해석된다. 위에서 사용한 예로 돌아가면 다음과 같다.
이 텍스트는 다음과 같이 표시될 것으로 기대할 수 있다. Hello world!
이것이 작동하려면 사용자 에이전트(브라우저)가 클래스 이름
héllo를 나타내는 두 문자열을 매칭해야 했다. CSS와 HTML이 각각 서로 다른
이스케이프 메커니즘을 사용했음에도 그렇다. 위 단편은 텍스트가 달라질 수 있으면서도
명세에 따라 여전히 "같은 것"으로 간주될 수 있는 한 가지 방식을 보여준다. 클래스 이름
h\e9llo는 HTML 마크업의 클래스 이름
héllo와 매칭되었다(또한 코드 포인트
é [U+00E9 LATIN SMALL LETTER E
WITH ACUTE]를 사용하는 리터럴 값 héllo와도 매칭될 것이다).
형식 언어와 문서 형식은 한 리소스의 텍스트 일부를 다른 리소스 안에 포함하기 위한 기능을 제공하는 경우가 많다. 포함은 리소스의 본문에 콘텐츠를 삽입하는 메커니즘이다. 포함 메커니즘은 처리 시점에 콘텐츠를 리소스로 가져온다. 이는 문서의 구조와 잠재적으로 문서의 어휘에 대한 매칭에 영향을 준다. 포함의 예로는 XML의 엔터티 참조, XInclude [XInclude] 명세, 그리고 CSS의 @import 규칙이 있다.
포함은 결합 마크로 시작하지 않는 경우(문자 이스케이프 형태이든 포함된 리소스의 문자 리터럴이든) 포함 정규화됨이라고 한다.
유니코드는 문서 작성자가 텍스트의 모양이나 동작을 제어하는 데 도움이 되는 여러 특수 목적 문자를 제공한다. 이러한 문자 중 다수는 보이지 않거나 키보드에 대응 항목이 없기 때문에 사용자는 그 존재나 부재를 항상 인식하지 못한다. 그 결과, 이러한 문자가 인코딩된 문자 시퀀스의 일부이지만 예상되는 매칭 텍스트에는 포함되어 있지 않은 경우 문자열 매칭을 방해할 수 있다. 이러한 문자의 몇 가지 예는 다음과 같다.
유니코드 제어 문자 U+200D Zero Width Joiner (ZWJ라고도 함)와 U+200C Zero Width Non-Joiner (ZWNJ라고도 함). 이러한 문자는 원치 않는 합자의 형성을 방지하거나 원하는 합자의 형성을 유도하는 등 합자 형성을 제어하는 데 사용할 수 있지만, 주된 용도는 아랍 문자나 여러 인도계 문자와 같은 복합 문자에서 결합 및 형태 선택을 제어하는 것이다. 일부 인도계 문자는 작성자가 특정 결합자가 취하는 형태를 제어할 수 있도록 ZWJ 및 ZWNJ 문자를 사용한다. [Unicode] 12장의 논의를 참조하라.
Zero Width Non-Joiner는 페르시아어에서 특정 "일반" 아랍 문자 결합을 방지하는 데 사용된다. 이러한 경우에는 해당 문자의 존재 여부가 의미에 영향을 준다. 예를 들어 단어 تنها("alone")와 단어 تنها ("bodies" 또는 "corpuses")는 각각 "U+062A U+0646 U+0647 U+0627"와 "U+062A U+0646 U+200C U+0647 U+0627"로 인코딩되며, 유일한 차이는 뒤 단어의 ZWNJ이다.
ZWJ 문자는 특정 이모지 시퀀스를 형성하는 데도 사용되며, 이에 대해서는 아래에서 더 자세히 논의한다.
변형 선택자(U+FE00부터 U+FE0F까지)는 대체 모양이나 글리프를 선택하는 데 사용되는 문자이다 (Character Model: Fundamentals [CHARMOD] 참조). 예를 들어 흑백 이모지와 컬러 이모지 중 하나를 선택하는 데 사용된다. 이들은 미리 정의된 표의문자 변형 시퀀스(IVS)에도 사용된다. Unicode Character Database(UCD)의 "Standardized Variants" 부분에는 많은 예가 제시되어 있다.
몇몇 문자 체계도 시각적 변형 선택을 인코딩하는 방법을 제공한다. 대표적인 예는 몽골 문자의 자유 변형 선택자(U+180B부터 U+180D까지)이다.
이름이 오해를 부르는 U+034F Combining Grapheme Joiner (실제로 자소를 결합하지 않음)는 정렬 목적상 그렇지 않으면 하나의 자소로 간주될 수 있는 문자를 분리하거나, 텍스트에 유니코드 정규화를 적용할 때 특정 텍스트상의 구별을 유지하는 수단을 제공하는 데 사용된다.
공백 변이도 텍스트의 해석과 매칭에 영향을 줄 수 있다. 예를 들어 NBSP, NNBSP 등과 같은 다양한 줄바꿈 없는 공백 문자가 있다.
U+200B Zero Width Space는 공백이 원래 나타나지 않는 텍스트에서 단어 경계를 나타내는 데 사용되는 문자이다. 예를 들어 태국어 문서에서 단어 분리를 돕기 위해 사용될 수 있다.
U+00AD Soft Hyphen은 텍스트에서 가능한 또는 선호되는 하이픈 위치를 나타내는 데 사용할 수 있다. 텍스트가 해당 위치에서 줄바꿈되도록 재배치될 때만 보이게 된다.
U+2060 WORD JOINER는 때때로 WJ라고 불리며, 폭이 없는 줄바꿈 없는 공백 문자이다. 그 목적은 두 문자 사이의 줄바꿈을 방지하는 것이다. 줄바꿈 목적을 제외하고는 무시되어야 한다. 이는 U+FEFF ZERO WIDTH NO-BREAK SPACE 문자를 대체하는 역할을 한다. U+FEFF는 "Byte Order Mark"(BOM)로 더 널리 알려져 있기 때문이다. 바이트 순서 표시는 일부 일반 텍스트 파일의 시작 부분에서 해당 파일이 유니코드 문자 인코딩으로 되어 있음을 알리는 데 사용된다.
마지막으로, 대부분의 문자 체계는 가로로 쓰일 때 왼쪽에서 오른쪽으로 진행된다. 그러나 아랍 문자와
히브리 문자 같은 일부 문자 체계는 주로 오른쪽에서 왼쪽으로 쓰인다. 텍스트는 이러한 문자 체계가
혼합되어 쓰이거나, 숫자나 다른 문자 체계의 따옴표처럼 텍스트의 다른 부분과 반대 방향으로 진행되는
문자 시퀀스를 포함할 수 있다. 이러한 텍스트 방향의 혼합을 양방향 텍스트 또는 줄여서
bidi
라고 한다. Unicode Bidirectional Algorithm [UAX9]은
이러한 혼합 방향 텍스트가 표시를 위해 처리되는 방식을 설명한다. 대부분의 텍스트에서는 방향 처리를
텍스트 자체에서 도출할 수 있다. 그러나 알고리즘이 텍스트를 올바르게 표시하기 위해 추가 정보를
필요로 하는 경우도 많다. 더 많은 예는 [html-bidi]를 참조하라.
유니코드가 텍스트 방향의 모호성을 해결하기 위해 정의한 방법 중 하나는 방향 진행의 시작과 끝을 표시하는 보이지 않는 제어 문자 집합이다. 양방향 제어 문자는 텍스트의 표시 방식에 영향을 줄 수 있지만 (유니코드 양방향 알고리즘이 텍스트 표시를 처리하는 데 도움을 주기 때문에), 제어 문자가 없더라도 텍스트가 자연스럽게 양방향 진행으로 나뉘었을 경우에는 텍스트에 아무 영향이 없을 수도 있다. 이러한 제어 문자는 위에서 언급한 문자들과 마찬가지로 보이지 않기 때문에, 매칭에 의도치 않은 영향을 줄 수 있다.
이러한 거의 모든 경우에, 사용자는 주어진 문서나 텍스트 문자열이 이러한 문자 중 하나를 포함했는지 또는 생략했는지 알지 못하거나 확신하지 못할 수 있다. 텍스트 매칭은 기본 코드 포인트의 매칭에 의존하므로, 이러한 표식으로 인한 텍스트 인코딩의 변이는 성공해야 할 매칭이 (사용자의 관점에서는) 알 수 없는 이유로 실패하게 만들 수 있다.
유니코드의 비교적 새로운 기능은 이모지 문자이다. [UTR51]에서 유니코드는 이를 다음과 같이 설명한다.
이모지는 일반적으로 다채로운 만화 형태로 표시되고 텍스트 안에 인라인으로 사용되는 그림문자(그림 기호)이다. 얼굴, 날씨, 차량과 건물, 음식과 음료, 동식물, 또는 감정, 느낌, 활동을 나타내는 아이콘과 같은 것들을 표현한다.
이모지는 U+200D ZERO WIDTH JOINER 또는 ZWJ를 포함한 다양한 이모지 수정자와 함께 사용되어 더 복잡한 이모지를 형성할 수 있다.
예를 들어 이모지(👪 [U+1F46A FAMILY])는 이모지 문자 사이에 ZWJ를 사용하는 시퀀스 U+1F468 U+200D U+1F469 U+200D U+1F466로도 형성될 수 있다. 다른 이모지 문자를 변경하거나 추가하면 가족의 구성이 달라질 수 있다. 예를 들어 시퀀스 👨👩👧👧 U+1F468 U+200D U+1F469 U+200D U+1F467 U+200D U+1F467는 이러한 종류의 조합을 지원하는 시스템에서 "family: man, woman, girl, girl"에 대한 조합 이모지 문자를 생성한다. 많은 일반적인 이모지는 ZWJ 시퀀스를 사용해야만 형성될 수 있다. 자세한 내용은 [UTR51]를 참조하라.
이모지 문자 뒤에는 이모지 수정자 문자가 올 수 있다. 이러한 수정자는 사람을 나타내는 이모지의 피부색을 선택할 수 있게 한다. 이 문자들은 일반적으로 수정 대상인 기본 이모지 뒤에 오는 보이지 않는 수정자이다. 예를 들면 다음과 같다. 👨 👨🏻 👨🏼 👨🏽 👨🏾 👨🏿
이모지 문자 뒤에는 기본 이모지의 텍스트(흑백, U+FE0E Variation Selector 15로 표시) 또는 컬러 (U+FE0F Variation Selector 16로 표시) 표시를 나타내기 위해 변형 선택자가 올 수도 있다.
이모지 사용의 또 다른 복잡한 점은 깃발이다. 국가 깃발은 국가 Zambia의 국가 코드(ZM)인 🇿🇲처럼, [BCP47] 레지스트리에서 파생된 국가 코드, 예컨대 시퀀스 🇿 [U+1F1FF REGIONAL INDICATOR SYMBOL LETTER Z] 🇲 [U+1F1F2 REGIONAL INDICATOR SYMBOL LETTER M]를 사용하여 구성할 수 있다. 다른 지역 깃발이나 특수 목적 깃발은 다양한 기호와 함께 깃발 이모지를 사용하거나, 취소 태그로 끝나는 지역 표시자 코드를 사용하여 구성할 수 있다. 예를 들어 스코틀랜드의 깃발(🏴)은 다음과 같이 구성할 수 있다.
이러한 메커니즘은 각각 함께 사용될 수 있으므로, 매우 복잡한 문자 시퀀스가 하나의 이모지 자소나 이미지 형성에 사용될 수 있다. 매우 비슷한 이모지 시퀀스라도 정확히 같은 인코딩 시퀀스를 사용하지 않을 수 있다. 대부분의 경우 위에서 언급한 수정자와 조합은 최종 사용자의 키보드에서 생성된다 (여기서는 하나의 이모지 "문자"로 표시된다). 이러한 인코딩 옵션의 다양성은 서로 다른 벤더가 유니코드가 "교환용으로 권장"하는 시퀀스만을(그리고 정확히 그 시퀀스를) 사용하는 범위에서 부분적으로 해결된다. 이는 벤더가 글꼴과 키보드가 사용자가 기대하는 옵션을 제공할 준비가 되도록 보장하는 데 도움이 된다. 그래도 사용자는 일반적으로 기본 인코딩의 복잡성과 생성 메커니즘을 인식하지 못하며, 생성 메커니즘은 권장된 것에만 제한되지 않는다. 이모지 시퀀스는 빠르게 발전하고 있으므로 가까운 미래에 이모지 매칭을 돕거나 방해하는 추가 발전이 있을 수 있다. 유니코드 정규화는 이러한 시퀀스를 재정렬하거나 수정자를 삽입 또는 제거하지 않는다. 따라서 사용자와 구현자는 네임스페이스 및 기타 매칭 문맥에서 이모지 문자를 사용하는 사용자가 인코딩 변이 때문에 예상치 못한 "문자" 불일치를 쉽게 겪을 수 있음을 주의해야 한다.
리소스는 웹에서 문서 형식을 직렬화하기 위해 레거시 문자 인코딩을 포함한 서로 다른 문자 인코딩 체계를 사용할 수 있다. 각 문자 인코딩 체계는 범용 문자 집합의 주어진 하위 집합을 표현하기 위해 서로 다른 바이트 값과 시퀀스를 사용한다.
모든 문서, 형식 및 프로토콜에 대해 UTF-8과 같은 유니코드 문자 인코딩을 선택하는 것은 강력히 권장되는 권장사항이다. 레거시 문자 인코딩을 사용해 얻을 추가적인 효용이 없고, 이 절의 나머지 고려사항을 완전히 피할 수 있기 때문이다.
예를 들어 € [U+20AC EURO
SIGN]은 UTF-8 문자 인코딩에서 바이트 시퀀스
0xE2.82.AC로 인코딩된다. 같은 문자는 레거시 문자 인코딩
windows-1252에서 바이트 시퀀스 0x80으로
인코딩된다. (다른 레거시 문자 인코딩은 이 문자를 인코딩할 바이트 시퀀스를 전혀 제공하지
않을 수도 있다.)
명세는 주로 문서를 문서의 문자 인코딩(레거시 문자 인코딩이든 UTF-8과 같은 유니코드 인코딩이든)에서 변환하고 문자 이스케이프를 모두 해제한 뒤, 문서 처리를 계속하기 전에 각 문서를 유니코드 문자 시퀀스로 간주함으로써 이러한 결과적 변이를 다룬다.
단일 레거시 문자 인코딩 안에서도 구현상의 변이가 있을 수 있다.
유명한 예로 레거시 일본어 인코딩 Shift_JIS가 있다.
서로 다른 트랜스코더 구현은 특정 바이트 시퀀스를 유니코드에 매핑하는 방법을 선택해야 했다.
따라서 바이트 시퀀스 0x80.60(JIS X 0208 문자 집합의 0x2141)은
일부 구현에서 U+301C
WAVE DASH로 매핑된 반면, 다른 구현은 U+FF5E
FULL WIDTH TILDE를 선택했다. 이는 합리적이고 자체적으로 일관된 두 트랜스코더가
같은 입력에서 서로 다른 유니코드 문자 시퀀스를 생성할 수 있음을 의미한다.
Encoding [Encoding]
명세는 부분적으로 웹 구현이 상호운용 가능하고 동일한 매핑을 사용하도록 보장하기 위해
존재한다. 그러나 Encoding 명세와 일치하는 트랜스코더가 웹에서 발견되는 문서나
특정 문서 형식 또는 프로토콜에 나타나는 데이터를 처리하는 데 적용된다는 보장은 없다.
유니코드로 변환할 때 추가로 고려할 사항 하나는 시각적 저장 순서를 사용하는 양방향 문자 체계(예: 히브리어 및 아랍어)의 레거시 문자 인코딩이 존재한다는 점이다. 즉, 유니코드 및 기타 현대적 인코딩과 달리, 문자는 (라인 프린터에서처럼) 화면에 왼쪽에서 오른쪽으로 인쇄되는 순서대로 메모리에 저장된다. 이러한 인코딩을 유니코드로 변환하거나 이러한 인코딩의 텍스트를 비교할 때는 원본 텍스트와 대상 텍스트 모두를 논리적 순서로 배치하도록 주의해야 한다. 자세한 내용은 [CHARMOD]의 3.3.1절을 참조하라.
자연어 검색 또는 "찾기" 기능을 수행할 때 적절한 추가적인 종류의 동등성이나 처리가 있다. 이는 Character Model 문서 시리즈의 다른 부분([STRING-SEARCH])에서 설명된다. 어휘를 위한 명세나 형식 구문에서 사용할 매칭 알고리즘을 정의하는 명세는, 일관되고 예측 가능한 결과를 생성하는 것을 방해하므로 그 문서에서 설명하는 것과 같은 추가적인 사용자 지정 접기, 매핑 또는 처리를 적용하려고 해서는 안 된다(SHOULD).
웹 환경에서는 문자열이 서로 다른 문자 인코딩을 사용할 수 있고, 그러한 인코딩 안에서 서로 다른 문자 시퀀스를 사용할 수 있으며, 이 문서에서 설명한 대소문자와 같은 다른 변이를 가질 수 있으므로, 문자열 동일성을 평가하기 위한 일관된 절차를 확립하는 것이 중요하다.
이 장은 구문 콘텐츠에서 문자열 매칭을 지정하고 구현하기 위한 요구사항을 정의한다.
문자열 매칭을 더 효과적이고 일관되게 만들 수 있는 방법 중 하나는 매칭 대상 콘텐츠에 제한을 적용하는 것이다. 어휘의 정의, 특히 그 어휘 안에서 사용자 제공 값을 허용하는 정의에는 필연적으로 "유효한 식별자"를 만드는 규칙이 포함된다. 여기에는 보통 길이와 콘텐츠 제한이 포함된다. 이러한 제한을 정의하기 위한 몇 가지 모범 사례는 다음과 같다.
명세는 식별자에서 서로게이트 코드 포인트 (U+D800부터 U+DFFF까지) 또는 비문자 코드 포인트를 허용해서는 안 된다.
명세는 식별자에서 C0
(U+0000부터 U+001F까지) 및 C1 (U+0080부터 U+009F까지) 제어 문자를
허용해서는 안 된다.
식별자에는 크게 두 가지 부류가 있다. 사용자 대면 식별자와 애플리케이션 내부 식별자이다.
애플리케이션 내부 식별자는 기계가 읽을 수 있고 표시를 의도하지 않는 문서 형식 또는 프로토콜의 어휘 부분이다. 이러한 식별자에는 문서 형식이나 프로토콜의 내용을 다루거나 디버그해야 하는 개발자 또는 콘텐츠 작성자를 돕기 위해 (일반적으로 영어로) 의미 있는 이름이 부여되는 경우가 많다.
애플리케이션 내부 식별자(사용자에게 표시되지 않으며 애플리케이션이나 프로토콜 안에서 매칭 또는 처리에 항상 사용되는 것)를 정의하는 명세는 콘텐츠를 인쇄 가능한 ASCII 하위 집합으로 제한해야 한다. ASCII 대소문자 비구분 매칭이 권장된다.
애플리케이션 내부 식별자 필드나 값은 최종 사용자에게 표시될 때 지역화 가능한 표시 값으로 감싸야 한다.
사용자 대면 식별자는 사용자가 할당하거나 편집하거나, 사용자가 선택할 수 있도록 제시되는 문서 형식 또는 프로토콜의 어휘 부분이다. 사용자 대면 식별자의 예로는 네트워크 이름(예: SSID), 장치 이름, class, style 또는 attribute 이름, 사용자 정의 설정이나 값 등이 있다. 이러한 종류의 식별자는 이 문서에서 설명하는 문제 때문에 매칭이 더 복잡하지만, 특히 영어를 하지 않거나 라틴 문자에 덜 익숙한 사용자에게 최상의 경험을 제공한다.
많은 사용자 대면 식별자는 또한 사용자 제공 값이며, 문서 형식이나 프로토콜의 사용자가 할당할 수 있다. 사용자가 선호하거나 사용자의 공동체 또는 문화에서 선호하는 자연어를 사용할 수 있는 능력은 더 나은 사용자 경험을 제공하고, 특히 영어에서 언어 능력이 제한될 수 있는 대상에게 기능을 더 접근 가능하게 만든다.
식별자가 사용자에게 보이거나 잠재적으로 보일 수 있는 경우, 명세는 모든 언어의 사용자가 결과 문서 형식이나 프로토콜을 동등하게 접근하여 사용할 수 있도록 비ASCII 유니코드 문자의 사용을 허용해야 한다. 대소문자 구분(즉, 대소문자 접기를 하지 않음)이 권장된다.
넓은 범위의 유니코드 문자가 허용되어야 하지만, 명세는 여전히 사용자 대면 식별자의 콘텐츠에 특정한 실용적 제한을 부과할 수 있다. 이러한 유형의 콘텐츠 규칙을 정의하는 명세의 한 예는 Unicode Identifier and Pattern Syntax [UAX31]에서 찾을 수 있다.
주어진 명세에 사용할 매칭 알고리즘을 선택할 때의 기본 결정은 매칭되는 문자열에 적용할 텍스트 정규화 수준(대소문자 민감성과 유니코드 정규화를 모두 포함)이다. 역사적으로 웹의 대부분의 명세는 유니코드 정규화 없이 대소문자 구분 매칭을 선택해 왔으며, 이는 모든 새 명세에 대해 권장되는 매칭 형식이다. 그러나 대소문자 비구분과 정규화가 유용한 경우도 있다.
명세는 해당 형식이나 프로토콜 사용자에게 주는 이점이 구현 비용과 복잡성을 능가한다면 대소문자 비구분을 선택할 수 있다. 대소문자 접기와 정규화는 모두 비교되는 값에 영향을 줄 수 있고, 텍스트의 표시 및 경우에 따라 의미에도 영향을 줄 수 있으며, 이러한 작업은 상대적으로 비용이 많이 들기 때문에, 대소문자 비구분을 선택하는 것은 일반적으로 권장되지 않는다.
대소문자 비구분의 특수한 경우는 ASCII/Basic Latin 범위(즉,
코드 포인트 U+0000부터 U+007F까지)로
제한된 어휘이다. 이러한 명세는 해당 문자 범위에 대해서만 대소문자 비구분을 선택할 수 있다.
이는 매칭 구현을 크게 단순화한다. 그러나 이 매칭 형식은 식별자나 구문에서 더 넓은 범위의
유니코드를 허용하는 명세에는 적절하지 않다. 사용자가 매칭 동작을 이해하기 어렵고,
비ASCII 문자 체계와 언어의 사용자에게 불리하기 때문이다. 즉 사용자는
green은 GREEN과 매칭되지만 grüß는 GRÜẞ 또는 어쩌면 GRÜSS와 매칭되지 않고(대신 GRüß와 매칭되는) 상황을 이상하고 예측 불가능하다고 느낀다.
매칭 알고리즘은 두 문자열을 비교하는 데 필요한 일련의 단계를 설명한다.
주어진 명세에 적합한 텍스트 정규화는 형식 또는 프로토콜의 어휘 요구사항에 따라 달라진다. 텍스트 정규화에는 네 가지 선택지가 있다.
식별자와 구문 콘텐츠에서 문자열을 매칭할 때 콘텐츠에 대해 대소문자 접기나 유니코드 정규화를 수행하지 않는 것이 권장된다.
이 정규화 단계는 텍스트에 아무 영향도 주지 않으며, 그 결과 비교는 비교되는 원본 문자열의 대소문자 차이와 유니코드 정규화 형식 차이 모두에 민감하다. 콘텐츠 작성자는 토큰이 매칭되기를 기대한다면 영향을 받는 텍스트를 인코딩하기 위해 일관된 대소문자와 일관된 문자 시퀀스를 사용해야 함을 인식하고 보장해야 한다.
'ASCII 대소문자 접기' 접근 방식은 어휘 자체가 ASCII 범위로 제한되는(또는 매칭이 ASCII 토큰에서만 발생하는) 예외적인 경우에만 사용해야 한다.
ASCII 대소문자 접기 정규화 단계는 ASCII 범위에 대해서만 대소문자 접기를 수행한다. 유니코드 정규화 형식은 적용되지 않는다. 이 단계는 어휘 자체가 ASCII 범위로 제한되는 경우(또는 매칭이 ASCII 토큰에서만 발생하는 경우)에만 적절하다.
각 문자열에 대해 다음 단계를 수행한다.
대부분의 명세에는 대소문자 비구분이 권장되지 않지만, 어휘가 비ASCII 문자를 허용하고 대소문자 구별에 민감하지 않기를 원하는 예외적인 경우에는 '유니코드 정준 대소문자 접기' 접근 방식을 사용해야 한다.
비ASCII 문자를 허용하는 어휘를 가진 명세는 대부분의 새 어휘를 포함해야 한다.
유니코드 대소문자 접기는 비정규화된 문자 시퀀스를 생성할 수 있으므로, 매칭이 사용자 기대와 일치하도록 하려면 모든 유니코드 대소문자 접기 뒤에 유니코드 정규화가 따라야 한다. 예는 § 2.4 정규화와 대소문자 접기의 상호작용을 참조하라.
[Unicode] 요구사항 D145는 결과 문자열이 정규화된 형식에 있도록 보장하기 위해 대소문자 접기 작업 뒤에 정규화 단계를 요구한다. 대소문자 접기 이후 정규화의 포함은 선택 사항이다. 결과 문자열이 비교에만 사용되고 저장되거나 사용자에게 표시되지 않는다면, 코드 포인트 시퀀스는 대소문자 접기 뒤에 동등하다. 다만 특정 정규화 형식에 있다고 보장되지 않을 뿐이다. 이는 D145에 대한 의도적 위반이다. 유니코드는 이것이 유효한 권장사항임을 확인했다.
각 문자열에 대해 다음 단계를 수행한다.
'유니코드 호환 대소문자 접기' 접근 방식은 사용해서는 안 된다.
비ASCII 문자를 허용하고 유니코드 호환 동등물을 매칭해야 하는 어휘를 가진 명세는 이 정규화 단계를 사용할 수도 있다. 호환 정규화 형식(NFKC 및 NFKD)은 텍스트의 의미, 모양 및 처리를 변경하므로, 이 단계는 웹의 대부분의 애플리케이션에서 사용해서는 안 된다.
대소문자 접기는 입력 코드 포인트 시퀀스의 영향을 받는다. 또한 비정규화된 코드 포인트 시퀀스를 생성할 수도 있다. 호환 분해와 대소문자 접기의 상호작용은 일관된 매칭을 생성하기 위해 여러 번의 패스를 필요로 한다. 그 결과 이 정규화 단계에는 유니코드 정규화가 여러 번 사용된다. 예는 § 2.4 정규화와 대소문자 접기의 상호작용을 참조하라.
각 문자열에 대해 다음 단계를 수행한다.
콘텐츠 작성자는 리소스를 유니코드 문자 인코딩(웹에서는 일반적으로 UTF-8)으로 입력하고 저장해야 한다.
텍스트를 비교하는 첫 번째 단계는 둘 다 같은 디지털 표현을 사용하는지 보장하는 것이다. 이는 구현이 레거시 문자 인코딩의 모든 텍스트를 유니코드 코드 포인트 시퀀스로 변환해야 함을 의미한다. 일반적으로 이는 데이터를 일관된 유니코드 인코딩 형식(예: UTF-8 또는 UTF-16)으로 변환하기 위해 트랜스코더를 적용하여 수행한다. 이를 통해 문자열의 비트 단위 비교로 문자열 동등성을 판단할 수 있다.
정규화 트랜스코더는 트랜스코더로, 레거시 문자 인코딩에서 유니코드로 변환을 수행하고 또한 그 결과가 유니코드 정규화 형식 C(NFC)에 있도록 보장한다. 대부분의 레거시 문자 인코딩에서는 정규화 트랜스코더를 구성할 수 있다(임의의 트랜스코더 뒤에 정규화기를 사용하여). 하지만 레거시 문자 인코딩의 레퍼토리에 유니코드로 표현되지 않는 문자가 포함된 경우에는 그렇게 할 수 없다. 정규화 트랜스코더는 NFC에 있는 문자 시퀀스만 생성하지만, 변환된 문자 시퀀스는 포함 정규화되어 있지 않을 수 있다 (예: 결합 마크로 시작하는 경우).
웹의 문서 형식은 종종 추가적인 외부 리소스(예: HTML 문서에 적용되는 CSS 스타일시트)와 상호작용하거나 이를 사용해 처리되므로, 서로 다른 문자 인코딩을 사용하는 문서 사이에서 값을 매칭할 때 텍스트의 일관된 표현이 중요해진다. 정규화 트랜스코더를 사용하면 레거시 인코딩된 문서가 대부분의 언어에서 일반적으로 기대되는 유니코드 문자 시퀀스와 매칭되도록 하여 상호운용성을 보장하는 데 도움이 된다.
웹에서 사용되는 대부분의 트랜스코더는 출력으로 NFC를 생성하지만, 일부는 그렇지 않다. 이는 보통 트랜스코더가 원본 레거시 문자 인코딩과 왕복 호환되도록 하거나, 다른 문자 구별을 보존하거나, 사용자 에이전트에서 사용 중인 다른 트랜스코더와 일관되도록 하기 위한 것이다. 이는 Encoding 명세 [Encoding]와 여러 다른 중요한 트랜스코딩 구현이 다수의 비정규화 트랜스코더를 포함한다는 뜻이다. 실제로 유니코드의 대부분의 호환 문자는 레거시 인코딩에서의 왕복 변환만을 위해 존재하며, 이들 중 다수는 NFC에서 싱글턴 정준 매핑을 가진다. 앞서 이 문서의 앞부분에서 Å [U+212B ANGSTROM SIGN]를 통해 그 예를 보았다.
대부분의 트랜스코더가 NFC 출력을 생성하며, 모든 문자에 대해 NFC를 생성하지 않는 트랜스코더도 압도적으로 많은 문자에 대해서는 NFC를 생성한다는 점을 기억하라. 특히 조합 완료 형식이 존재하는 곳에서 분해 형식을 생성하거나, 정규화된 시퀀스와 다른 결합 문자 시퀀스를 생성하는 일반적으로 사용되는 트랜스코더는 없다(그리고 이는 [Encoding]의 모든 트랜스코더에 대해 참이다).
명세는 유니코드 문자 인코딩을 허용해야 한다.
명세는 기본 문자 인코딩을 지정해야 하며, 기본 인코딩으로 UTF-8을 지정해야 한다.
명세는 UTF-8 이외의 인코딩을 허용하지 않아야 한다.
레거시 문자 인코딩은 웹에서 대체로 그 효용을 다했다. 새 명세는 처음부터 유니코드 인코딩을 지원하고, 유니코드 인코딩(일반적으로 UTF-8)을 기본값으로 사용하며, 가능하다면 그 밖의 인코딩 사용을 허용하지 않아야 한다. 이는 상호운용성을 촉진할 뿐 아니라 문자 및 데이터 표현에서 무의미한 변이의 범위를 줄인다.
대부분의 문서 형식과 프로토콜은 문자를 이스케이프 시퀀스로 인코딩하거나 텍스트를 포함한 외부 데이터를 리소스 안에 포함하는 수단을 제공한다. 이는 [CHARMOD]의 4.6절과 위에서 자세히 논의된다.
매칭을 수행할 때는 매칭이 적절히 성공(또는 실패)하도록 문자 이스케이프를 언제 해석해야 하는지 아는 것이 중요하다. 일반적으로 이스케이프, 참조 및 포함은 매칭(또는 매칭에 민감한 처리)을 수행하기 전에 처리되거나 확장된다. 이러한 구문은 인코딩하기 어려운 시퀀스를 문서에 편리하게 넣을 수 있도록 하면서, 해당 문자가 문제의 문서에 코드 포인트 시퀀스로 직접 인코딩된 것처럼 동작하도록 하기 위해 존재하기 때문이다.
이것이 복잡해질 수 있는 한 영역은 구문 콘텐츠와 지역화 가능 콘텐츠가 어떻게 상호작용하는지 결정하는 것이다. 예를 들어 다음 HTML 조각을 고려하라.
기술적으로 결합 마크 ̀ [U+0300 COMBINING GRAVE ACCENT]가 앞선 따옴표와 결합하더라도, HTML은 그 문자(엔터티로 인코딩되었는지 여부와 무관하게)를 HTML 구문의 일부를 형성하는 것으로 간주하지 않는다.
리소스에서 매칭 작업을 수행할 때의 일반 규칙은 사용자가 상호작용하는 것과 같은 "수준"에서
이스케이프를 확장하는 것이다. 예를 들어 위 예를 고려할 때, HTML 소스를 보는 도구는
이스케이프 시퀀스 ̀를 앰퍼샌드로 시작하는 문자 문자열로 표시할 것이다.
반면 JavaScript 프로그램은 브라우저의 문서 해석 위에서 동작하며, U+0300 문자를
id 속성의 값으로 매칭할 것이다.
문서 형식의 구문을 처리할 때, 이스케이프는 형식의 처리 규칙에서 명시적으로 금지된 경우를 제외하고 보통 구문 처리 전에 그것이 나타내는 문자 시퀀스로 변환된다. 이를 통해 리소스는 모든 종류의 문자를 리소스의 구문 구조 안에 포함할 수 있다.
어떤 경우에는 이스케이프를 사전 처리하면 문제가 생긴다. 예를 들어 HTML 문서를 파싱하기 전에
< 시퀀스를 확장하면 문서 오류가 발생할 것이다.
특정 유니코드 정규화 형식이 콘텐츠 작성자에게 항상 적절하거나 사용 가능한 것은 아니며, 사용자의 텍스트 인코딩 선택이 데이터의 하위 소비자에게 명확하지 않을 수 있다. 이 문서에서 보인 것처럼, 콘텐츠 작성자나 애플리케이션이 텍스트를 입력하거나 교환할 때 같은 의미 값을 표현하기 위해 선택할 수 있는 방식은 매우 많다. 정규화는 사용자가 의도적으로 적용한 구별을 제거할 수 있다. 따라서 매칭 알고리즘은 문자열의 대소문자 접기 매칭을 수행할 때 유니코드 정규화를 사용하도록 지정하며, 그것도 알고리즘 내부에서만 사용하도록 지정한다. 콘텐츠에 정규화를 부과하는 것은 사용자와 구현자에게 장벽이 될 수 있다. 따라서:
명세는 주어진 어휘의 인코딩, 저장 또는 교환을 위해 유니코드 정규화 형식을 지정해서는 안 된다.
구현은 콘텐츠를 유니코드 문자 인코딩으로 트랜스코딩하거나, 대소문자 접기 또는 기타 사용자 주도 변경과 같은 텍스트 변환의 부작용으로 필요한 경우를 제외하고는, 교환, 읽기, 파싱 또는 처리되는 구문 콘텐츠(사용자 제공 값 포함)나 지역화 가능 콘텐츠의 정규화 형식을 변경해서는 안 된다. 소비자나 콘텐츠 자체가 비정규화된 표현에 의존할 수 있기 때문이다.
작성 도구는 리소스를 정규화하는 수단을 제공하고, 주어진 리소스가 유니코드 정규화 형식 C에 있지 않을 때 사용자에게 경고해야 한다.
특정 정규화 형식으로 텍스트를 저장하고 교환하도록 요구하는 명세는 § 3.2.5.1 문서 형식에서 정규화를 지정할 때의 요구사항에 있는 요구사항을 다루어야 한다.
명세는 추가 요구사항이 필요한 구체적이고 명확한 이유가 없는 한, 형식이나 프로토콜이 데이터를 정규화된 형식으로 저장하거나 교환하도록 요구하는 것이 일반적으로 권장되지 않는다. 웹의 많은 문서 형식은 정규화를 요구하지 않으므로, 콘텐츠 작성자가 때때로 비정규화된 문자 시퀀스에 의존할 수 있다. 정규화 단계는 그러한 콘텐츠에 부정적 영향을 줄 수 있다.
정준 정규화 형식(NFC 형식 또는 NFD 형식)은 적용 대상 텍스트의 의미와 표시를 보존하도록 의도되어 있다. 항상 그런 것은 아니며, 이것이 정규화가 권장되지 않는 이유 중 하나이다. NFC는 거의 모든 레거시 데이터(유니코드 인코딩으로 단순히 일대일 트랜스코딩된 경우)뿐 아니라 현재 소프트웨어가 생성하거나 대부분(그러나 전부는 아님)의 키보드에서 사용자가 입력한 데이터가 이미 이 형식에 있다는 장점이 있다. NFC는 또한 약간의 간결성 장점이 있으며, 문자와 자소의 관계와 관련해 대부분의 언어에서 사용자 기대에 더 잘 맞는다.
명세는 호환 정규화 형식(NFKC, NFKD)을 지정해서는 안 된다.
구현은 최종 사용자가 명시적으로 요청하지 않는 한 호환 정규화 형식 (NFKC, NFKD)을 적용해서는 안 된다.
호환 정규화 형식(NFKC 형식 및 NFKD 형식)은 중요한 방식으로 텍스트의 구조를 바꾸고 의미를 잃게 한다. 사용자는 때때로 의도적으로 유니코드에서 호환 매핑이 있는 문자를 사용하거나, 유니코드로 변환될 때 호환 매핑을 가지는 레거시 문자 인코딩의 문자를 사용한다. 이는 콘텐츠 작성자의 의도적인 선택으로 간주해야 한다. NFKC/NFKD는 때때로 "찾기" 작업이나 지역화 가능 콘텐츠의 문자열 검색에서 유용할 수 있지만, 호환성 차이를 지우는 것은 해롭다.
NFC를 요구하려면 명세 개발자가 추가로 주의해야 한다. 웹의 콘텐츠는 일반적으로 알려진 정규화 상태에 있지 않기 때문이다. 비정규화된 콘텐츠에 대한 경계 및 오류 조건은 이러한 경우 신중하게 고려되고 잘 지정되어야 한다.
정준적으로 동등하지만 분리된 유니코드 문자 시퀀스가 보안 문제를 나타내는 경우, 명세는 이를 문서화하거나 위험 경고를 제공해야 한다.
콘텐츠 작성자는 가능한 경우 콘텐츠에 대해 유니코드 정규화 형식 C(NFC)를 사용해야 한다.
NFC가 일부 언어의 콘텐츠에 항상 적절하거나 콘텐츠 작성자에게 사용 가능한 것은 아님에 유의하라.
콘텐츠 작성자는 형식이나 구현이 수행하는 매칭에 유니코드 정규화 형식이 포함되어 있더라도, 매칭을 용이하게 하기 위해 일관된 유니코드 문자 시퀀스를 사용해 텍스트를 항상 인코딩해야 한다.
콘텐츠가 일관되게 처리되도록 하기 위해, 콘텐츠 작성자는 같은 텍스트를 나타내는 데 일관된 코드 포인트 시퀀스를 사용하려고 해야 한다. 콘텐츠는 어떤 정규화 형식이든 될 수 있고, 비정규화된(그러나 유효한) 유니코드 문자 시퀀스를 사용할 수도 있지만, 표현이 일관되지 않으면 구현은 서로 다른 시퀀스를 서로 다른 것으로 처리하게 된다. 일관된 선택, 접근, 추출, 처리 또는 표시를 보장하는 가장 좋은 방법은 항상 NFC를 사용하는 것이다.
콘텐츠 작성자는 리소스에 앞선 기본 문자 없이 결합 마크를 포함해서는 안 된다.
이에 대한 예외가 있을 수 있다. 예를 들어 [Unicode] 문자 목록과 같은 문자 목록을 만들 때,
작성자는 대응하는 기본 문자 없이 결합 마크를 사용하고자 할 수 있다. 그러나 기본 문자 없이 결합 마크를
사용하면, 순진한 구현이 결합 마크를 인접한 구문, 사용자 제공 또는 지역화 가능 콘텐츠와 결합하는 경우처럼,
의도치 않은 표시 또는 처리 문제가 발생할 수 있다. 예를 들어 문자 ́ [U+0301 COMBINING ACUTE
ACCENT]와 같은 결합 마크를 HTML의 class 속성 값 시작 부분에
사용하면, 클래스 이름이 편집기에서 올바르게 표시되지 않고 편집하기 어려울 수 있다.
권장되는 기본 문자에는 기본 문자가 보여야 할 때 사용하는 ◌ [U+25CC DOTTED CIRCLE] 또는 기본 문자가 보이지 않아야 할 때 사용하는 [U+00A0 NO-BREAK SPACE]가 있다.
콘텐츠 작성자가 이러한 지침을 항상 따르지는 않으므로:
어휘의 명세는 구문 콘텐츠와 문자 데이터 사이의 경계뿐 아니라 엔터티 경계(해당 언어에 포함 메커니즘이 있는 경우)를 정의해야 한다. 여기에는 임의의 문자를 표현하도록 설계된 문자 이스케이프를 허용하면서도, 언어의 인스턴스가 처리될 때 콘텐츠를 처리하거나 매칭할 때 충돌을 만들 수 있는 모든 경계가 포함되어야 한다.
명세가 저장, 전송 또는 처리를 위해 유니코드 정규화를 요구하는 경우, 명세 작성자뿐 아니라 해당 명세의 구현자도 몇 가지 추가 고려사항을 다루어야 한다.
작업이 정규화된 텍스트 입력에서 비정규화된 출력을 생성할 수 있는 경우, 명세는 그 결과 출력이 정규화되어야 하는지 여부를 정의해야 한다. 명세는 일부 작업에서 정규화 수행이 선택 사항이라고 명시할 수 있다. 이 경우 기본값은 정규화를 수행하는 것이어야 하며, 정규화를 끄기 위해 명시적 옵션을 사용해야 한다.
정규화를 요구하는 명세는 정규화 구현을 선택 사항으로 만들어서는 안 된다.
어떤 구현은 정규화하고 어떤 구현은 정규화하지 않는다면 상호운용성은 달성될 수 없다.
정규화를 수행해야 하는 구현은 다음 요구사항을 고려해야 한다.
정규화에 민감한 작업은 구현이 먼저 텍스트가 정규화된 형식인지 검사로 확인했거나 텍스트 자체를 다시 정규화하지 않은 한 수행되어서는 안 된다. 이러한 규칙의 적용을 받지 않는 사설 시스템 안에서는 사설 합의를 만들 수 있지만, 외부에서 관찰 가능한 결과는 규칙을 준수했을 때와 같아야 한다.
텍스트를 수정하고 정규화에 민감한 작업을 수행하는 정규화 텍스트 처리 구성 요소는 각 수정 후에 정규화가 이루어진 것처럼 동작해야 한다. 따라서 이후의 모든 정규화에 민감한 작업은 항상 정규화된 텍스트를 다루는 것처럼 동작한다.
작성 도구 구현은 처리, 표시 또는 교환을 방해할 수 있는 결합 마크로 시작하는 구문 콘텐츠의 입력 또는 생성을 사용자에게 경고하거나 방지해야 한다.
문자열 동일성 매칭에서 중요한 고려사항 중 하나는 비교가 대소문자를 구분하는지 구분하지 않는지이다.
콘텐츠 작성자는 형식이나 구현이 대소문자 접기 매칭을 지원하더라도, 매칭을 용이하게 하기 위해 식별자를 항상 일관된 대문자, 소문자 및 혼합 대소문자 형식으로 철자해야 한다.
어휘는 보통 콘텐츠 작성자와 사용자에게 예측 가능성을 중시한다. 대소문자 구분 매칭은 구현하기 가장 쉽고, 일반적으로 기본 유니코드 코드 포인트 시퀀스의 비교로 구성되므로 혼동 가능성을 가장 적게 도입한다. 언어별 대소문자 매핑과 같은 고려사항의 영향을 받지 않기 때문에, 위의 터키어 예와 같은 단어를 구문 콘텐츠에 포함한 문서 작성자에게 가장 적은 놀라움을 준다.
대소문자 비구분은 보통 자연어 텍스트 검색을 수행하는 경우처럼 지역화 가능 콘텐츠를 처리하는 데 사용된다. 그러나 때때로 대소문자 비구분이 바람직하다. 이러한 경우 형식 언어가 고려해야 하는 여러 구현 선택지가 있다.
유니코드의 Basic Latin(ASCII) 범위를 넘는 문자를 포함하는 어휘에서 대소문자 비구분 매칭을 정의하는 명세는 Unicode full 대소문자 접기 매칭을 지정해야 한다.
명세는 사용자 정의 값에 대해 유니코드 전체 범위를 허용해야 한다.
어휘는 일반적으로 특히 사용자 제공 값에 대해 넓은 범위의 유니코드 문자를 허용해야 한다. 이는 가장 넓은 범위의 언어와 문화가 불이익 없이 사용할 수 있도록 하기 위해서이다. 그 결과 대소문자 접기와 같은 텍스트 작업은 선택된 일부가 아니라 유니코드 전체 범위를 다루어야 한다. 대소문자 비구분 매칭이 필요한 경우, 이는 유니코드 대소문자 접기를 사용한다는 뜻이다.
Unicode simple 대소문자 접기 형식은 웹에서의 문자열 동일성 매칭에 적절하지 않다.
유니코드의 Basic Latin(ASCII) 하위 집합으로 제한된 어휘에서 대소문자 비구분 매칭을 정의하는 명세는 ASCII 대소문자 비구분 매칭을 지정할 수 있다.
어휘가 ASCII로 제한되고 사용자 정의 이름이나 식별자를 허용하지 않는 형식 언어는 ASCII 대소문자 비구분 매칭을 지정할 수 있다. 그 예는 HTML로, HTML 명세가 정의한 요소 및 속성 이름에 대해 ASCII 대소문자 비구분 비교를 사용하도록 정의한다.
어휘는 모든 토큰과 식별자가 명세에 의해 직접 정의되고, 이러한 식별자나 토큰이 유니코드의 Basic Latin 하위 집합만 사용하는 경우에만 "ASCII-only"로 간주된다. 사용자 정의 식별자가 허용되는 경우에는 유니코드 문자 전체 범위(보안 또는 교환상의 우려에 따라 적절히 제한, [UTR36] 참조)를 허용해야 하며, 동일성 매칭에는 유니코드 대소문자 비구분을 사용해야 한다.
ASCII 전용 어휘는 식별자나 값에서 더 넓은 범위의 유니코드를 허용하는 문서 형식이나 프로토콜 안에 존재할 수 있다. 예를 들어 [CSS-SYNTAX-3]는 CSS 스타일시트의 형식을 식별자와 값에 유니코드 전체 범위를 사용할 수 있도록 정의한다. 그러나 CSS 명세는 항상 ASCII 범위의 하위 집합을 사용하여 CSS 키워드를 정의한다. 따라서 많은 스타일시트가 ASCII가 아닌 식별자나 데이터 값을 포함하더라도 CSS의 어휘는 ASCII 전용이다.
로캘 또는 언어별 맞춤 조정은 자연어 처리 작업의 일부일 때 가장 적절하다 (이는 이 문서의 범위를 벗어난다). 대소문자 매핑이나 대소문자 접기의 언어별 맞춤 조정은 일반 대소문자 접기 규칙과 다른 결과를 생성하므로, 예측 가능성이 중요한 형식 언어에서는 이를 피해야 한다.
어휘에서 대소문자 비구분 매칭을 정의하는 명세는 언어 민감 대소문자 비구분 매칭을 지정해서는 안 된다.
언어 민감 대소문자 구분 매칭이 지정되는 경우, 유니코드 대소문자 매핑은 언어에 따라 맞춤 조정되어야 하며, 각 맞춤 조정에 사용되는 언어의 출처를 지정해야 한다.
매칭되는 두 문자열은 서로 다른 언어일 수 있으며, 또 다른 제3의 언어 문맥에 나타날 수도 있다. 따라서 대소문자 접기에 사용할 언어는 애플리케이션과 사용자 기대에 따라 달라진다.
언어별 맞춤 조정은 형식 언어에 권장되지 않는다. 언어 정보를 얻고, 검증하고, 관리하기 어려울 수 있으며, 그 결과 작업이 사용자에게 좌절감을 주거나, 사용 중인 언어 구성 또는 매칭이 수행되는 시스템 구성에 따라 어떤 사용자에게는 실패하고 다른 사용자에게는 성공하는 결과를 생성할 수 있기 때문이다.
언어별 작업은 적절한 경우 언어별 대소문자 접기를 포함해야 한다.
예를 들어 CSS 작업 text-transform은 문자열을 대소문자 매핑하는 데 사용될 때
언어에 민감하다.
유니코드 대소문자 접기는 문서 형식과 프로토콜을 위한 선호 대소문자 비구분 매칭이지만, 기본값과 다른 매핑을 가진 언어의 콘텐츠 작성자와 사용자는 결과에 여전히 놀랄 수 있다. 그들의 기대는 일반적으로 자신이 사용하는 언어와 일치하기 때문이다.
언어 민감 문자열 비교는 흔히 로캘 민감이라고도 한다.
대부분의 프로그래밍 언어와 운영 환경이 각자의 로캘 기반 API를 사용하여 언어별 맞춤
조정에 접근하기 때문이다. 예를 들어 Java 프로그래밍 언어의 java.text.Collator
클래스나 JavaScript의 Intl.Collator를 참조하라.
명세는 매칭 과정의 일부로 수행되는 모든 추가 맞춤 조정을 명확히 정의해야 한다.
일부 명세는 주어진 어휘에서 매칭을 돕기 위해 추가 맞춤 조정을 포함하고자 할 수 있다. 그 예에는 2절에서 설명한 추가 텍스트 차이를 제거하는 것, 구문의 일부인 문자를 서로 매핑하거나 제거하는 것, 또는 공백 트림을 수행하는 것이 포함될 수 있다.
모든 추가 맞춤 조정은 서로 다른 언어가 유니코드에서 표현되는 방식을 방해하지 않아야 한다. 예를 들어 텍스트를 분해한 다음 모든 결합 문자를 제거하여 글자에서 악센트를 제거하려는 과정은 결합 마크에 의존하는 언어를 망가뜨릴 것이다. 그 예는 예 2의 데바나가리 텍스트이다. (이러한 과정은 잠재적 악센트를 모두 제거하는 데도 실패할 것이며, 텍스트의 의미와 표현에 해를 끼칠 가능성이 크다.)
형식 언어에서 문자열과 토큰을 매칭하는 것이 이 문서의 주요 관심사이지만, 때로는 명세가 순수한 문자열 동일성 너머의 추가적인 매칭 유형을 고려해야 할 필요가 있다.
정규 표현식 구문을 정의하는 명세는 [UTS18]에 따라 최소한 Basic Unicode Level 1 지원을 제공해야 하며, Extended 또는 Tailored(Level 2 및 3) 지원을 제공해야 한다.
정규 표현식 구문은 사용자가 부분적으로만 알려진 값이나 예측 가능한 방식으로 달라질 수 있는 값을 지정할 수 있게 하므로, 형식이나 프로토콜을 정의할 때 때때로 유용하다. 이 문서의 여러 절에서 보았듯이, 유니코드에서 문자가 인코딩될 수 있는 여러 방식에는 변이가 있으며, 이는 표현식에서 문자열이 지정되거나 매칭되는 방식에 잠재적으로 간섭한다. 예를 들어, 문자를 세는 작업은 사용된 유니코드 코드 포인트 수가 아니라 자소 경계에 의존해야 할 수 있고, 대소문자 없는 매칭은 대소문자 접기의 변이를 고려해야 할 수 있으며, 처리되는 표현식이나 텍스트의 유니코드 정규화를 고려해야 할 수도 있다.
Unicode Regular Expressions Level 1 지원에는 정규 표현식에서 이스케이프 사용을 포함해 유니코드 코드 포인트를 지정하는 기능, 그리고 대부분의 정규 표현식 구문에 공통적인 특정 종류의 경계뿐 아니라 유니코드 문자 속성에 접근하는 기능이 포함된다.
Level 2는 이를 확장하여 여러 중요한 기능을 제공하는데, 특히 특정 종류의 자소 클러스터 경계에서 텍스트를 선택하는 기능과 대소문자 변환 지원(위에서 광범위하게 언급한 두 주제)을 포함한다. Level 3은 로캘 [LTLI] 기반 정규 표현식 맞춤 조정을 제공하며, 이는 형식 언어에서는 덜 유용하지만 지역화 가능 콘텐츠를 처리할 때 유용할 수 있다.
이 문서의 변경사항(2018-04-20의 워킹 드래프트부터)은 github 커밋 로그를 통해 확인할 수 있다.
이 버전은 유니코드 정준 대소문자 접기 정규화 단계와 유니코드 호환 대소문자 접기 정규화 단계에서 어떤 정규화 단계가 선택 사항인지 변경한다. 이 버전은 정규화를 첫 번째 단계로 요구하고 출력의 정규화를 선택 사항으로 만든다. 이 변경은 유니코드와의 테스트 및 논의를 기반으로 한다.
W3C 국제화 워킹 그룹과 관심 그룹 및 그 밖의 사람들은 많은 의견과 제안을 제공했다. 워킹 그룹은 다음 사람들에게 감사를 표하고자 한다. Mati Allouche, Ebrahim Byagowi, John Cowan, Martin Dürst, Behdad Esfahbod, Asmus Freitag, Richard Ishida, John Klensin, Peter Saint-Andre, Amir Sarabadani, Najib Tounsi, Richard Wordingham, 그리고 이 문서가 개발된 20(!!)년 동안의 모든 CharMod 기여자들.
이 문서의 이전 버전은 다음 사람들이 편집했다.
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in: