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은 따로 선택할 수 있다.


```

U+0000  to U+FFFF  : BMP, Basic Multilingual Plane

U+10000 to U+1FFFF : SMP, Supplementary

... 이 외에 U+10FFFF까지 있으나 생략.

```


UTF-8

한 문자를 나타내는데 1-4 bytes를 사용하는 가변 길이 인코딩 방식(Variable-width encoding).

따라서 효율적이며 많이 쓰인다.

ASCII range인 ``c U+007F``(127)까지는 1 byte만 사용해서 표현한다.

``c U+0080`` 부터는 2 bytes를 사용해서 표현하는데, 상위 1 byte는 `` 0xc2``부터 사용하고 `` 0x80~0xbf``를 하위 1 byte로 사용해서 원래 1 byte인 `` 0x00~0x7f``와 구분할 수 있도록 했다.

따라서 `` 0x80~0xbf``는 단독으로 쓰이지 않는다.

```c

U+007F 7f    <control>

U+0080 c2 80 <control>

```

```c

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가 넘어가는 경우(``c U+10000`` 이상), 값에서 ``c U+10000``을 뺀 후 문자값을 10비트씩 쪼갠 후 각각 surrogate halves인 ``c U+D800, U+DC00``의 하위 10비트에 끼워 넣는 식으로 총 4 bytes로 표현한다.

```js

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

ASCII range는 1byte, 한글은 2 bytes로 표현하는 가변 길이 인코딩 방식.

UTF-8 처럼 ``c 0x7f``까지는 1 byte로 표현하지만, EUC-KR의 2 bytes 표현 방식은 ``c [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) 이며, 한 문자를 표기하는데 고정된 크기를 사용하는 것을 의미하고, 윈도우에서는 ``c wchar_t`` 타입이 WCS이며 모든 문자는 한 문자당 2 byte다. 

```c

// 문자열 앞에 L을 붙이면 WCS가 되어 한 문자당 2바이트가 들어간다.

wchar_t *wstr = L"Wide Char String"

```