티스토리 뷰

dev

UTF8과 UTF16의 차이

IT's me 2019. 5. 7. 12:41

 

 

최근엔 개발하면서 UTF8로 통일해서 쓰지만 십년 전 정도에는 euc-kr로 구성된 시스템이 많아서 이기종 간 데이터 통신 시에 문자 인코딩 방식이 달라서 애를 먹은 적이 많다. 실제 개발할 때 이기종 간 맞춰보지 않다가 개발이 완료된 후 테스트 단계에서 발견되는 경우가 많았는데 그러다 보니 남은 일정 내에 이슈를 대응하기가 어려운 경우가 많았던 거다. 심지어 영문으로만 테스트된 경우엔 운영 상태에서 문제가 발생할 수도 있다.

( 테스트 시에 'abcd' 이런 식으로 구겨 넣다가... )

 

서론이 길었다. UTF8과 UTF16에 대해서 알아보자.

 

UTF (Universal Coded Character Set + Transformation Format – N-bit, Unicode Transformation Format)로 뒤에 숫자는 해당 비트를 이용하는 전 세계 문자 표현 방법이라고 생각하면 좋을 것 같다.

 

UTF8은 1(8비트)~4바이트를 이용하는 가변 길이 표현 방법인데 1바이트를 이용하는 건 아스키 방식과 완전히 동일하며 추가적으로 필요한 경우 앞에 1의 개수만큼 바이트를 사용하고 있다. UTF8은 1을 최대 네 개를 사용할 수 있으니 1바이트부터 4바이트까지 사용할 수 있는 거다.

 

이 내용은 위키에 아주 잘 표현되어있다.

 

UTF8과 UTF16의 차이

 

코드 범위(십육진법)

UTF-16BE 표현(이진법)

UTF-8 표현(이진법)

설명

000000-00007F

00000000 0xxxxxxx

0xxxxxxx

ASCII와 동일한 범위

000080-0007FF

00000xxx xxxxxxxx

110xxxxx 10xxxxxx

첫 바이트는 110 또는 1110으로 시작하고,

나머지 바이트들은 10으로 시작함

000800-00FFFF

xxxxxxxx xxxxxxxx

1110xxxx 10xxxxxx 10xxxxxx

010000-10FFFF

110110yy yyxxxxxx 110111xx xxxxxxxx

11110zzz 10zzxxxx 10xxxxxx 10xxxxxx

UTF-16 서러게이트 쌍 영역 (yyyy = zzzzz - 1).

UTF-8로 표시된 비트 패턴은 실제 코드 포인트와 동일하다.

 

UTF16도 표현방식이 표에 나타나 있는데 UTF16은 아스키와 동일한 범위를 표현할 때도 앞에 0으로 채워서 16 비트가 최소로 이용되며 3바이트 이용 없이 2 or 4 바이트 사용만 있다. utf8에서 3바이트가 필요한 표현을 2바이트로 표현해낸다.

 

쉽게 얘기해보면 영문만 사용하는 경우 UTF8은 1바이트만 사용되고, UTF16은 기본 2바이트, 그리고 UTF8은 표현범위에 따라 각기 2,3,4바이트 를 사용하는 데 UTF16은 2바이트 혹은 4바이트를 사용한다. UTF8에서 3바이트로 표현되는 문자들은 모두 UTF16에서는 2바이트로 표현되므로 문서가 3바이트에 해당하는 경우 UTF16을 선택하면 더 효율적일 수 있다.

 

UTF8의 장점과 단점 ( 위키 내용을 그대로 복붙 내지 정리했다. 어차피 내 공부를 위한 정리이므로 ... )

 

장점

비고

하위 호환성 보장

ASCII 인코딩은 UTF-8의 부분 집합이다. 일반적인 ASCII 문자열은 올바른 UTF-8 문자열이며, 따라서 하위 호환성이 보장된다.

간단한 인코딩 변환

-

바이트 검색 알고리즘 사용

바이트 단위 문자열 검색 알고리즘들을 그대로 사용할 수 있다.

쉬운 바이트 경계 파악

바이트 경계를 순서대로 혹은 역순으로 찾기 쉽다. 만약 여러 바이트로 표시된 문자의 중간에서 찾기 시작한다면, 단지 해당 문자만 손실되고 나머지 문자들은 손상을 입지 않는다. 기존의 많은 다중 바이트 인코딩들은 이러한 재동기화가 훨씬 힘들다.

문자 표현 독립성

한 문자를 표현하는 바이트 표현은 다른 문자를 표현하는 어떤 바이트 표현에도 포함되지 않는다. 따라서 ASCII 문자가 아닌 값들에 투명한 파일 시스템이나 다른 소프트웨어(예를 들어서 C의 printf() 함수)와 호환성을 가진다.

빠른 인코딩

인코딩에 간단한 비트 연산만 사용되므로 효과적이다. UTF-8은 곱셈이나 나눗셈과 같은 느린 연산들을 사용하지 않는다.

 

단점

비고

문자열 표현 용량이 큼

대부분의 UTF-8 문자열은 일반적으로 적당한 기존 인코딩으로 표현한 문자열보다 더 크다. 판독 기호를 사용하는 대부분의 라틴 알파벳 문자는 적어도 2바이트를 사용하며, 한중일 문자들과 표의 문자들은 적어도 3바이트를 사용한다.

 

한중일 문자들과 표의 문자를 제외한 거의 모든 기존 인코딩들은 한 문자에 1바이트를 사용하므로 문자열 처리가 간편한 반면, UTF-8은 그렇지 않다.

 

위키에서 별로 중요하지 않다고 생각되는 장, 단점들은 제거했다. 그러다보니 UTF8의 단점은 표현 용량이 크다는 것뿐. 다른 단점을 찾을수가 없었다.

 

이론 상으로는 이렇고... 실제로 파일이 어떻게 저장되는지 눈으로 봐야 느낌이 팍팍 올것 같다.

 

 

그래서 이런 텍스트 파일 두개를 만들었다. 하나는 utf8.txt, 다른 하나는 utf16.txt.

 

그렇다. 각기 다른 인코딩 방식으로 파일을 만들었고 나는 이놈을 바이너리 형태로 보려고 한다. 바이너리 형태로 보게끔 도와준 고마운 툴은 notepad++의 hex-editor 다. 같은 내용을 적었는데 utf8은 18바이트, utf16은 26바이트가 저장되었다.

 

 

 

먼저 utf8을 보자.

 

UTF8로 'abcdefg 헬로우'를 binary로 읽어보면.

0부터 abcdefg 가 저장되었을거라 유추되는 아스키코드가 보인다. 그 후로 엔터값 이후로 한글 헬로우가 3바이트씩 처리 되었으니 0d-0a가 엔터처리임을 알겠다.

 

다음은 UTF16이다. 처음에 ff, fe는 BOM 표시로 보인다. 위에 UTF8에서 BOM을 사용할수도 있는데 별 의미가 없다 하여 안쓰는 모양이다. 내가 저장한 텍스트 에디터에서는 BOM(Byte Order Mark) 처리를 하지 않는 모양이지.

 

UTF16로 'abcdefg 헬로우'를 binary로 읽어보면.

UTF16에서 파일의 첫번째 문자 혹은 스트림으로 나오며 16비트 코드 엔디언을 나타냅니다. 현재 눈에 보이는 ff-fe 순서가 정상인데 잘못된 엔디언으로 파일을 읽는다면 fe-ff 순서로 제대로 읽혀지지 않으므로 iso-8859-1 문자인 `ÿþ`가 나온다고 한다. 어디서 ÿþ을 본다면 잘못읽었다는 의심을 해봐야 할듯.

 

전에 엔디안에 대해서 정리한 글이 있으니 엔디안을 모른다면 아래 글을 참고해보자.

 

빅 엔디안(Big endian)과 리틀 엔디안(Little endian) 차이점
출처: https://nhj12311.tistory.com/55 [void]

 


댓글
최근에 올라온 글
최근에 달린 댓글