티스토리 뷰
유니코드란 무엇일까? (UTF8과 EUC-KR 비교)
유니코드는 다국어를 지원하는 프로그래밍을 하다보면 가장 먼저 접하는 어려움이다. 일단 유니코드라는 용어의 개념부터 정리해보도록 하자. 조금 공부한 사람들은 ASCII, EUC-KR, CP949, UTF8, UTF16 같은 것들을 알고 있을 것이다.
그럼 문제, 이 중에 뭐가 유니코드(Unicode)일까?
이 중에 유니코드 그 자체인 것은 없다. 그나마 UTF-8, UTF-16에는 50점 줄 수 있을 것 같다. 이들은 유니코드를 '사용'하는 인코딩 방식이기 때문이다. EUC-KR도, CP949가 유니코드가 아닌가? 라고 생각하는 사람도 있을것이고, 유니코드란 2바이트로 표현하는 문자셋이 아닌가? 라고 알고있는 사람들도 있을 것이다.
이제는 잊어야한다. 만약 지금 헷갈리고 있다면 당신은 "유니코드"와 "인코딩 방식"을 헷갈리고 있는 것이다.
그럼 유니코드란 무엇일까?
유니코드란, 숫자와 글자, 즉 키와 값이 1:1로 매핑된 형태의 코드 인것이다.
다시말해 아스키코드로 0x41 = A 로 매핑된 것 처럼, 아스키코드로 표현할 수 없는 문자들을 유니코드라는 이름 아래 전 세계의 모든 문자를 특정 숫자(키)와 1:1로 매핑한 것이다.
전세계의 모든 문자가 너무 많을 것 같다. 하지만 유니코드는 현재 220 + 216 개수 만큼의 공간을 사용하고 있어서 웬만큼은 다 담겨있다. 특히 한자의 총 갯수가 10만여자가 될 것이라고 추정하는데, 모든 한자를 담고 있지 못하다는 것을 빼면 전세계 대부분의 문자가 전부 유니코드에 담겨있다고 봐도 될 것이다. 우리가 사용하는 한글의 경우에는 조합형을 위한 자모와, 완성형 한글이 모두 포함되어 있다.
유니코드는 너무~ 많아서 아스키코드표 처럼 한 눈에 들어오는 테이블은 만들기 어렵다. 그래서 블록으로만 나누어놓은 테이블도 상당하다.
U+ 라는 접두어가 붙어있으면 유니코드 라는 의미이다. 아스키코드의 0x41은 대문자 A이고, 이를 유니코드표에서 찾으면 U+0041이 된다.
위에 언급한 UTF-8, UTF-16같은 인코딩 방식은 이 유니코드표의 숫자 키들을 어떻게 표현하느냐에 따라 달린 것이다. 예를 들어 UTF-8은 가변바이트를 사용하기 때문에, 1바이트로 표현이 충분한 A같은 경우는 0x41로 표현한다. 반면 UTF-16은 16비트 즉, 2바이트로 표현하기 때문에, 0x0041로 표현한다. UTF-32도 있는데, 4바이트로 표현하기 때문에 0x00000041이 된다. (이렇게 될 것 같지만, UTF16과 UTF32의 인코딩 방식의 표현 방법에 따라 조금 다르다.)
- 추가내용1: UTF16은 Little-Endian이냐, Big-Endian이냐에 따라 0x4100이 될수도, 0x0041이 될 수도 있다.
- 추가내용2: UTF32 역시 LE냐 BE냐에 따라 0x4100 0000 이거나, 0x0000 0041이 된다.
따라서 UTF-8의 표현 방식이 대체로 더욱 효율적이다. 세계적으로도 UTF-8표준으로 많이 쓰이는 추세이다.
그럼 EUC-KR, CP949는 무엇인가?
이 두가지 인코딩 방식은, 2바이트로 한글을 표현할 수 있게 만든 방식이다. 일부 한자 등도 포함된다. 아스키값은 그대로 1바이트로 표현된다.
오래전부터 쓰이던게 EUC-KR이고, 이 인코딩에서 표현할 수 없는 한글이 있어 마이크로소프트에서 코드페이지 949를 사용하기 시작한다. CP949는 EUC-KR보다 더 많은 한글을 표현할 수 있으며, 윈도우에서 주로 쓰이는 인코딩 기법이다. CP949를 EUC-KR의 확장이라고 보면 될 것이다.
UTF-8, EUC-KR의 비교
한번 예제를 통하여 UTF-8과 EUC-KR을 간단하게 비교하는 실습을 해보도록 하자. 우분투 14.04에서 실습)
안abcd녕?
리눅스에서 vi를 통해 위 글자를 입력한 후 저장하자. 시스템의 기본 설정이나, vi의 fileencoding 설정에 따라서 저장되는 인코딩 방식이 다를 것이다.
파일의 인코딩을 확인하는 방법은 아래와 같다.
$ file -i test
test: text/plain; charset=utf-8
utf-8로 저장된 test 파일을 xxd라는 16진수 뷰어로 열어보자.
$ xxd test
00000000: ec95 8861 6263 64eb 8595 3f0a ...abcd...?.
utf-8은 유니코드를 사용하는 인코딩방식이라 하였다. 그럼 유니코드표를 보고 비교하면 된다.
유니코드표에서 '안'을 찾아보면 U+C548 에 위치하고 있다.
이 U+C548이라는 키를 2진법으로 표현하는 방법이 인코딩방식 인 것이고, 이 중에 하나가 UTF-8인 것이다. UTF-8인코딩에 대해서는 차후 포스팅에서 다룰 예정이지만, 예제 진행을 위해 간단히 표현 해 보겠다.
먼저 C548을 2진수로 풀면 아래와 같다.
16진수: C 5 4 8
2진수: 1100 0101 0100 1000
그리고 이 한글 유니코드 블록은 UTF-8에서 3바이트로 표현된다. 이 코드를 UTF-8식으로 표현하면 위에 C548의 이진수 값이 아래 빨간색의 영역에 차곡차곡 들어가서 아래와 같이 된다.
2진수: 1110 1100 1001 0101 1000 1000
16진수: E C 9 5 8 8
EC9588, 다시 위의 헥사값과 비교해보면 정확히 앞의 3바이트와 일치하는 것을 알 수 있다. 뒤에 61 62 63 64 는 a, b, c, d의 1바이트 아스키코드의 헥사값과 일치한다. 그리고 eb 85 95는 '녕'을 의미함을 알 수 있을 것이다.
- 참조
- 3f: ?의 아스키
- 0a: LF (Line Feed)
그럼 이제부터는 EUC-KR식의 표현방법을 보도록 하자. 먼저 utf-8로 저장된 test파일을 euckr로 변환해야 한다. iconv명령어를 이용해 변환하도록 하겠다. 아래와 같이 입력한다.
$ iconv -f utf8 -t euckr test > test-euckr
그리고 아까와 같이, euckr로 변환된 텍스트의 헥사값을 본다.
$ xxd test-euckr
00000000: bec8 6162 6364 b3e7 3f0a ..abcd..?.
EUCKR의 인코딩에는 UTF인코딩처럼 유별난 규칙은 없다. 아스키코드와 같이 그냥 EUCKR코드표에서 매칭되는 값을 찾으면 된다.
EUC-KR코드표에서 '안'을 찾으면 bec8 로 나온다. '녕'은 b3e7에 매핑되어 있다.
정리하기
자, 이쯤에서 정리를 다시 해보자.
- 아스키코드의 경우, 128개의 코드가 정리되어 있는 코드표가 있다.
- EUC-KR/CP949의 경우, 2바이트로 표현할 수 있는 코드표가 있는 것이다.
UTF-8/UTF-16등의 인코딩은 U+로 시작되는 코드표가 존재하고, 이를 유니코드라고 말한다. UTF같은 인코딩은 같은 유니코드표를 가지고 다르게 표현하는 방법인 것이다.
(참조: 위의 '안'을 UTF16LE로 표현하면 ff fe 48 c5 가 된다. 물론 유니코드표에서 찾으면 U+C548으로 같다. 어? 아까 UTF-16은 2바이트라고 했는데 왜 4바이트이지? 이것은 추후 다룰 UTF-16 인코딩 방식의 특성 때문이다.)
추가내용: UTF-16과 UTF-32 인코딩은 LE(Little-Endian) 또는 BE(Big-Endian)과 같은 엔디안 속성을 가진다. ff fe 라는 문자열을 통해 이 인코딩이 LE인지 BE인지 구별하게 된다.
Big-Endian의 경우에는 FE FF 로 표현하고 Little-Endian의 경우에는 FF FE로 표현한다.
참고로 UTF-32는 4바이트로 표현해야하기 때문에, 이 마저도 4바이트 (FFFE 0000)로 표현된다.
이제는 유니코드가 무엇인지 헷갈려하지 말자. 유니코드는 그냥 코드표이다. 추후 그동안 우리를 헷갈리게 해왔던 주범인 인코딩 방식에 대해 다루도록 하겠다.
참고
- 위키피디아: http://ko.wikipedia.org/wiki/유니코드
- 한글인코딩의 이해1: http://helloworld.naver.com/helloworld/textyle/19187
- 유니코드 문자 변환기: http://www.nl.go.kr/kolisnet/convert/convert.php
- Total
- Today
- Yesterday
- lua table
- 안시 색상
- ansi color
- angular2
- 폰트 조정
- C언어
- observable
- terminal 색
- NgZone
- 리눅스 터미널 색상
- 우분투 16.04
- 타입스크립트
- typeScript
- Zone.js
- 챗봇
- itoa
- Rx.js
- vim
- 스위프트
- ECMA2015
- QT
- ZONES
- JavaScript
- 안시 컬러
- Swift
- git proxy
- zone
- git 설정
- Angular
- qemu linux arm
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |