Unicode

유니코드는 봐도봐도 자꾸 까먹어서 한번 정리를 해봐야겠다고 생각했다.

유니코드의 codespace는 0부터 10FFFF까지 1,114,112개의 code point로 이루어져 있다. 그리고 이 codespace는 17개의 plane으로 나뉜다. 우리가 쓰는 글자는 다 BMP에 들어있다. 한글도 마찬가지이다. Plane 1에는 고대 글자나 Emoji 등이 있다. Plane 2에는 한자 같은게 마구 들어있다.

Plane Range
Plane 0 0000–​FFFF Basic Multilingual Plane (BMP)
Plane 1 10000–1​FFFF Supplementary Multilingual Plane
Plane 2 20000–2​FFFF Supplementary Ideographic Plane
Plane 3–13 30000–DFFFF Unassigned
Plane 14 E0000–EFFFF Supplementary Special-purpose Plane
Plane 15–16 E0000–10FFFF Supplementary Private Use Area

UCS-2

UCS-2는 2바이트를 사용해서 BMP만을 표현한다. 인코딩된 값은 유니코드 code point 값과 동일하다.

UTF-16

UTF-16은 UCS-2를 확장한 것으로, 모든 유니코드를 표현할 수 있다.

U+0000–U+D7FF and U+E000–U+FFFF

BMP는 UCS-2와 똑같이 인코딩한다. 그런데 BMP 의 code point 중 U+D800–U+DFFF는 나머지 plane들을 인코딩 할 때 사용하므로 인코딩하지 않는다. 저 범위는 유니코드에서 UTF-16 전용으로 쓰도록 할당한 영역이다.

U+10000–U+10FFFF

BMP 외의 plane은 16bit인 lead surrogate과 trail surrogate의 페어로 표현한다. 먼저 10000–10FFFF에서 10000을 빼면 0–FFFFF가 된다. 이 범위는 20bit로 표현된다. High 10bit를 D800–DBFF로 인코딩하고, 이것을 lead surrogate이라고 한다. Low 10bit는 DC00–DFFF로 인코딩 하고, 이것을 trail surrogate이라고 한다.

BOM

UTF-16은 2바이트를 사용해서 문자를 표현하기 때문에 아키텍쳐의 endianness에 따라 다르게 저장될 것이다. 그래서 UTF-16은 문자열 맨 앞에 FEFF를 붙인다. U+FEFF는 보이지 않는 넓이 0인 문자이다. 만약 디코더의 endianness가 인코더의 endianness가 같다면 U+FEFF로 제대로 디코딩하겠지만, 반대라면 U+FFFE로 인식하게 된다. 이를 통해서 endianness가 다른지 같은지 확인해서 필요하다면 byte 순서를 바꿔서 읽는 것이 가능하다. Endianness를 명시한 UTF-16BE UTF-16LE도 존재한다.

UTF-8

UTF-8는 모든 유니코드를 표현할 수 있고, 1~4바이트를 사용해서 문자를 나타낸다. ASCII와도 호환된다. UTF-8은 문자를 leading byte 한 개와 continuation byte들로 인코딩한다. Leading byte는 연속되는 1 뒤에 0이 한 개 붙는 형태로 시작하는데, 연속된 1의 개수가 byte 수를 나타낸다. 다만, 1 byte일 경우에는 10이 아니라 0으로 시작한다. 10으로 시작하는 것은 continuation byte이다. 예를 들어 3 byte일 경우 leading byte는 1110으로 시작하고 그 뒤에 10으로 시작하는 continuation byte가 2개 온다. 그리고 1110과 10을 뺀 남는 bit에 code point의 bit를 차례대로 넣어서 인코딩한다.

CP의 bit 수 Range Byte 수 Byte 1 Byte 2 Byte 3 Byte 4
7 U+0000–U+007F 1 0xxxxxxx
11 U+0080–U+07FF 2 110xxxxx 10xxxxxx
16 U+0800–U+FFFF 3 1110xxxx 10xxxxxx 10xxxxxx
21 U+10000–U+10FFFF 4 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

‘우’는 U+C6B0이다. 이것은 3 byte로 인코딩되는 범위안에 있다. 그리고 C6B0은 1100 0110 1011 0000 이므로 UTF-8로 인코딩하면 1110 1100 10 011010 10 110000, 즉 EC9AB0이 된다.

ETC

Leave a Reply

Your email address will not be published. Required fields are marked *