문자 코드는 우리가 표현하고자 하는 문자들의 집합을 코드화시킨 것이고, 문자열 인코딩은 그러한 문자 코드의 배열을 메모리상에 표현하는 방법입니다.
문자 코드 | 인코딩 |
---|---|
아스키 코드 | iso 8859 |
유니코드 | UTF-8, 16, 32... |
아스키 코드:
0
~ 127
유니코드:
U+0000
~ U+10FFFF
(문자 집합별로 구간이 나눠져있는데 여기서 그건 생략...
참고로 유니코드는 U+0000
~ U+007F
에 아스키 코드를 담고 있죠)
아스키 코드까지는 문자열 인코딩에 대해서 큰 문제는 딱히 없었는데, 왜 유니코드는 인코딩이 우리를 헷갈리게 만들까요(...)
아마 그건 한 바이트 안에 문자 코드가 전부 매핑되지 않기 때문일 것입니다.
a
라는 글자는 아스키 코드로 97
이라 한 바이트로 표현이 가능하지만,
가
는 유니코드로 U+AC00
이고, UTF-8
인코딩으로 표현하면 EA B0 80
이 됩니다
(띄어쓰기로 바이트를 구분하였습니다.).
게다가 UTF-16
으로 표현하면 AC 00
, UTF-32
로 표현하면 00 00 AC 00
이 되죠.
(UTF-16, 32는 빅엔디안이라고 가정했습니다.)
이렇게 같은 문자 코드를 표현하는데에 있어서 여러가지 방법이 있는데다,
심지어 UTF-8
이나 UTF-16
같은 경우는 글자를 표현하는 바이트 수가 가변적이라,
디코딩없이 일정한 바이트 단위로만 하나의 문자를 가려내는 것이 불가능하기 때문에,
이러한 고려가 없이 설계된 레거시를 다룰 때 골치가 아픈게 아닌가 싶습니다.
utf-16, utf-32 에서 엔디안 식별 등을 위해서 값 (0xFEFF) 를 첫 문자로 넣어서 인코딩을 인식할 수 있게 합니다.
추가적으로 utf-8은 바이트 단위로 읽기 때문에 endianless 한데... 윈도우 등에서 0xFEFF 를 utf-8 값으로 표현한 BOM을 또 저장해서 다른 시스템에서 읽는데 방해를 하기도 합니다