Post

Encoding 정리. Unicode, ANSI, UTF, CP949

Unicode

유니코드 자체는 특정 encoding 방식을 가리키는 말이 아니라, 순서(U+????)와 문자를 1:1로 매핑해놓은 하나의 코드표를 가리킨다.

ANSI와 달리 전세계 글자를 하나의 코드표에 표현하기 위에 만들어졌기 때문에, Unicode 코드표 안에 전세계 글자가 모두 들어있다.

UTF(Unicode Transformation Format) 은 유니코드 표를 보고 문자를 bytes로 변환하는 encoding 방식이다.

ex,

(U+C548, 안) 이라는 문자가 있을 때, 이 문자를 어떤 바이너리 데이터로 변환할 것인가?를 결정하는 것이 UTF-8이니 UTF-16이니 하는 Encoding이라는 것이다. (U+C548, 안)은 UTF-8의 경우 0xec9588으로, UTF-16의 경우 0xc548로 변환된다.

위에서 언급했듯 유니코드 자체는 encoding 방식을 의미하는게 아니지만, 특정 system에서 Unicode encoding 따위로 나타내기 때문에 혼동하는 경우가 많다. 보통 Unicode encoding이라고 하면 Windows와 Java에서는 UTF-16을, 나머지 시스템에서는 UTF-8을 가리킨다. 그래서 메모장에서 저장할 때 선택할 수 있는 인코딩 탭에서 ‘유니코드’를 선택하면, UTF-16으로 인코딩된다. UTF-8은 따로 선택할 수 있다.

1
2
3
4
5
U+0000  to U+FFFF  : BMP, Basic Multilingual Plane
U+10000 to U+1FFFF : SMP, Supplementary
... 이 외에 U+10FFFF까지 있으나 생략.

UTF-8

http://www.utf8-chartable.de/

한 문자를 나타내는데 1-4 bytes를 사용하는 가변 길이 인코딩 방식(Variable-width encoding). 따라서 효율적이며 많이 쓰인다. ASCII range인 U+007F(127)까지는 1 byte만 사용해서 표현한다. U+0080부터는 2 bytes를 사용해서 표현하는데, 상위 1 byte는 ` 0xc2부터 사용하고 0x80~0xbf를 하위 1 byte로 사용해서 원래 1 byte인 0x00~0x7f와 구분할 수 있도록 했다. 따라서 0x80~0xbf`는 단독으로 쓰이지 않는다.

1
2
3
4
5
U+007F
7f    <control>
U+0080
c2 80 <control>

1
2
3
4
5
6
A  == 0x41        %41

§
== 0xc2a7      %c2%a7
 == 0xec9588    %ec%95%88    // 한글은 3 bytes

UTF-16

한 문자를 나타내는데 2 or 4 bytes를 사용하는 가변 길이 인코딩 방식. 2 bytes만 사용하는UCS-2 의 superset이라고 생각하면 된다. (UCS-2는 surrogate가 없고 BMP만 표현한다.) 대부분의 문자가 BMP에 속하기 때문에 대체로 2 bytes만 사용하지만, BMP가 넘어가는 경우(U+10000이상), 값에서 c U+10000을 뺀 후 문자값을 10비트씩 쪼갠 후 각각 surrogate halves인 U+D800, U+DC00의 하위 10비트에 끼워 넣는 식으로 총 4 bytes로 표현한다.

1
2
3
4
5
A  == 0x0041
// Little-Endian 방식이 존재한다. 이 경우 A == 0x4100
 == 0xc548
"".charCodeAt().toString(16) // == "c548"

ANSI

유니코드가 그렇듯이 ANSI encoding도 특정 인코딩 방식 한가지를 가리키는 말이 아니라 “the default local/codepage for my system”을 뜻한다.

그러나 유니코드가 전세계 모든 문자를 집어넣은 단일 코드표인 것과 달리 ANSI는 각 CodePage(≒언어)마다 코드표가 따로 있다. 예를 들면 EUC-KR과 CP949가 바로 한글에 대응되는 CodePage다.

즉, 다시말하자면 ANSI 형식의 인코딩은 Unicode 코드표를 사용하는게 아니라 각 언어에 따른 별도의 코드표(CodePage)를 사용한다. 그래서 메모장에서 ‘ANSI’를 선택하면 CP949로 인코딩된다.

EUC-KR

http://www.fileformat.info/info/charset/EUC-KR/list.htm

ASCII range는 1byte, 한글은 2 bytes로 표현하는 가변 길이 인코딩 방식. UTF-8 처럼 0x7f까지는 1 byte로 표현하지만, EUC-KR의 2 bytes 표현 방식은 [0xa1-0xfe][0xa1-0xfe] 2byte로 구성된다.

CP949 == EUC-KR의 superset

기본적인 부분은 EUC-KR과 같으며 EUC-KR에서 표현할 수 없는 한글도 표현할 수 있는, EUC-KR의 확장이라고 보면 된다. EUC-KR의 superset이기 때문에, CP949로 되어 있는 바이너리를 EUC-KR로 디코드하면 안된다. 반대는 되고. * 메모장에서 ANSI를 선택하면 CP949로 인코딩된다.

multibyte character

원래 의미는 한 문자를 표현하는데 2 bytes 이상 사용하는 것을 의미하나, 실제로는 이것을 의미하는게 아니다. 쉽게 말해 가변 길이 인코딩이 Multi-Byte 라고 생각하면 된다. 즉, EUC-KR이나, UTF-8이나 모두 multibyte encoding이다.

Multi-Byte String (MBS)의 반대는 Wide-Character String (WCS) 이며, 한 문자를 표기하는데 고정된 크기를 사용하는 것을 의미하고, 윈도우에서는 wchar\_t 타입이 WCS이며 모든 문자는 한 문자당 2 byte다.

1
2
3
// 문자열 앞에 L을 붙이면 WCS가 되어 한 문자당 2바이트가 들어간다.
wchar\_t \*wstr = L"Wide Char String"

This post is licensed under CC BY 4.0 by the author.