UTF-8, UTF-16 차이

IT 2014. 12. 12. 14:16

UTF-8과 UTF-16은 Unicode를 표현하는 Encoding 방식이다.


UTF-8과 UTF-16의 기본 차이는 문자 하나를 표현할 때 사용할 최소 byte를 의미한다고 볼 수 있다. UTF-8로 문자를 표현할 때 1~4bytes만큼 필요하다. UTF-16은 2bytes(16bit), 4bytes 만큼 필요하다. 두 Encoding 방식의 큰 차이는 최소 8bit가 필요하다 16bit가 필요하냐에 따라 다른 것이다. 최적의 상황(저쟝, 통신 용량을 아껴야할 때)이 필요하다면, 어떤 CodePoint를 주로 사용하냐에 따라 UTF-8 또는 UTF-16을 선택하는 기준이 달라질 것이다.


원리를 알면 뭐든지 해결 가능하다고, 인코딩 방식을 알면 도움이 많이 될 것이다. 저장용량을 최대한 아껴야한다면 최적화된 인코딩을 선택하는데 도움을 줄 것이다.



UTF-8

UTF-8의 표현방식

  U+0000~U+007F : UTF-8 Encoding 0xxx xxxx  8bit (총 1byte)

  U+0080~U+07FF : UTF-8 Encoding 110x xxxx 10xx xxxx 16bit( 2bytes)

  U+0800~U+FFFF : UTF-8 Encoding 1110 xxxx 10xx xxxx 10xx xxxx ( 3bytes)

  U+10000~U+10FFFF : UTF-8 Encoding 1111 0xxx 10xx xxxx 10xx xxxx 10xx xxxx ( 4bytes)


  표현방법을 유심히 살펴보면 알겠지만 다음 규칙을 발견할 수 있다. 

   1. U+0000 ~ U+007F( 기존 ASCII의 0~127)은 8byte로 표현한다. 


   2. 가장 첫 바이트의 처음 1이 나오는 갯수만큼 해당 문자의 표현 byte가 결정된다. 

      110 : 2bytes, 1110 : 3bytes, 11110 : 4bytes. 


   3. 뒤에 따라오는 바이트에는 모두 10으로 시작하게 하였다. 




UTF-16


UTF-16의 표현 방법은 조금 다르다. 복잡해보이지만, 조금만 살펴보면 간단하다. 처음에 대충 살펴보았을 땐 모르겠는데, 차분히 살펴보니 간단한 규칙만 알면 된다.


  U+0000~U+FFFF : BMP(Basic Multilingual Plane), 가장 많이 쓰는 문자들이 이 영역에 있다. 

      단, U+D800~U+DFFF 영역은 사용되지 않는다.

  U+10000~U+10FFFF : Supplementary Planes 라 불린다. 계산을 거쳐 4bytes로 저장한다. 

      1. Code Point - 0x10000 = ( 0x0 ~ 0xFFFFF) : 20bit 영역만 남김

      2. 상위 10-bit(0~0x03FF) + 0xD800 을 high surrogate로 할당한다.       

        (0xD800~ 0xDBFF)

      3. 하위 10-bit(0~0x03FF) + 0xDC00 을 low surrogate로 할당한다. 

        (0xDC00~0xDFFF)


high surrogate / low surrogate로 활용하여 U+10000 이상 code points를 표현한다. 


대세는 UTF-8이다. Web Encoding 의 대부분은 UTF-8이 차지하고 있다. 7bit ASCII 영역은 UTF-8에서 동일하게 Encoding되어 있다. 저장, 통신 용량을 고려하지 않는다면 대세인 UTF-8이다. 하지만 용량이 민감하다면 UTF-8, UTF-16중에서 고민해야한다. 


문서에서 많이 사용된 CodePoint들이 몇 Byte로 표현될지 고민 후 결정하면 저장, 통신 용량을 아낄 수 있다. 예를 들어 영문자들로 가득찬 문서의 경우 UTF-8로 표현하면 대부분 1byte로 표현되고 UTF-16으로 표현하면 2byte로 표현되니 UTF-8이 유리하고, 한글의 경우 UTF-8은 3byte, UTF-16은 2byte로 표현되니 UTF-16이 유리하다. 


참고문헌 : 

http://en.wikipedia.org/wiki/UTF-8

http://en.wikipedia.org/wiki/UTF-16


Posted by Picky Kang
,

Python 2.X버전에서 인코딩 시 문제가 생겼던 부분을 해결했다. 


[~]$ python encodingtest.py > std.out

Traceback (most recent call last):

  File "encodingtest.py", line 2, in <module>

    print uni

UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-1: ordinal not in range(128)


문제의 핵심은 Python이 standard output의 encoding을 모르는 것이었다. 해결 방법의 핵심은 standard output의 encoding을 지정하는 것이다. "PYTHONIOENCODING=UTF-8"



다음 예제 파일로 테스트 해보았다. 

encodingtest.py

#!/usr/bin/python

uni = u"\uacf5\uc0ac"

print uni



출력을 터미널로 한 예제

[~]$ python encodingtest.py 

공사




출력을 파일로 리다이렉트(redirect)한 예제, 하지만 unicode 출력에서 문제가 생겼다. 이유는 python이 standard output의 encoding을 알지 못해서이다. 

[~]$ python encodingtest.py > std.out

Traceback (most recent call last):

  File "encodingtest.py", line 2, in <module>

    print uni

UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-1: ordinal not in range(128)



이럴 땐 환경변수를 통해 encoding이 무엇인지 python 에게 알려주어야 한다. PYTHONIOENCODING 환경변수를 이용하여 인코딩을 지정해주면 해결 된다.

[~]$ PYTHONIOENCODING=UTF-8 python encodingtest.py  > std.out

[~]$ cat std.out

공사




Posted by Picky Kang
,

2013년 4월 유럽 여행을 갔다. 총 2주 일정 중 RyanAir 탑승했던 이야기를 하고자 한다.


유럽 여행 일정은 다음과 같았다. 

인천 - 독일 프랑크푸르트(Frankfurt am main) - 프랑스 파리(Paris) - 이탈리아 로마(Rome) - 독일 프랑크푸르트(Frankfurt am main) - 인천


이용했던 교통수단은 루프트한자(Lufthansa), 독일 고속 철도 ICE, 저가항공 EasyJet과 RyanAir.


   Lufthansa : 인천 => 독일 프랑크푸르트( Frankfurt am main)

   ICE(독일고속철도) : 독일 프랑크푸르트 => 프랑스 파리(Paris)

   EasyJet(유럽저가항공) : 프랑스 파리(Paris) => 이탈리아 로마(Rome)

   RyanAir(유럽저가항공) : 이탈리아 로마(Rome) => 독일 (Frankfurt Hahn Airport) 

      * 말이 Frankfurt Hahn Airport 이지 Frankfurt까지 100km가 넘는다.  

         인천 공항은 서울까지 직선 거리로 30~50km정도이다.

   독일 프랑크푸르트 - Lufthansa - 인천


로마에서 독일까지 이동할 때 탔던 RyanAir는 정말 저렴했다. 모든 항공요금이 마찬가지겠지만 미리 예약하고, 사람이 몰리지만 않으면 싸다. RyanAir는 더 저렴했었다. 


가격이 싸다는 것을 확인하기 위해 일단 SkyScanner(Google에서 SkyScanner)를 통해 검색한다. 가격이 너무 비싸다 싶으면 앞뒤 날짜도 함께 보아야한다. 지금도 검색해보면 가격이 튀어 있는 경우가 있는데 그날은 사람이 많이 몰리는 날이니 예산 절감을 위한다면 여행 일정을 바꾸어야 한다. 그리고 RyanAir 는 로마에서 프랑크푸르트까지 매일 운항하지 않는다.


아래는 2013년 3월에 예약한 2013년 4월 직접 이용한 요금이다. CIA (Rome Ciampino Airport) => HHN ( Frankfurt-Hahn Airport ) 2인 요금이고, 20kg까지 허용된 위탁 수화물 포함 가격이다. 저비용항공사 대부분은 위탁 수화물에 대해서 요금을 별도로 받는데. 2명이 타고 갔는데 총액 82.62 EUR 이었다. 한가지 아쉬운 점은 신용카드 수수료를 따로 받는다.


PAYMENT DETAILS

********42.00 EUR Total Fare

*********0.00 EUR Taxes, Fees & Charges

********14.00 EUR Passenger Fee: Administration Fee

********25.00 EUR Passenger Fee: Checked Bag(s)

*********1.62 EUR Passenger Fee: Credit Card Fee

********82.62 EUR Total Paid



요금이 싼만큼 불편한 점은 있다.


1. 싼 공항을 이용하는 경우가 있어 시외에서 멀리 떨어진 곳에 내려진 경우가 있다. 도착지인 Frankfurt-Hahn Airport은 소규모 공항 느낌이다. Frankfurt까지 이동할 교통편도 만만하지 않다.


Frankfurt까지 100km넘는 만만하지 않은 거리와 볼꺼리가 많지 않은 Frankfurt대신 루데스하임(Rudesheim am Rhein : http://www.ruedesheim.de/en/)으로 여행지를 바꾸었다. 여유롭고 예쁜 마을에서 케이블 카도 타고 유람선도 타고 멋진 레스토랑에서 저녁도 먹고, 좋은 추억을 보내고 왔다. 


2. Check-in 은 15일 ~ 4시간 사이에 해야 함. 홈페이지에서 Check-in을 꼭 해야한다.


3. 그리고 Boarding Pass 를 직접 출력해 가야한다. 하지 않으면 공항에서 비싼 돈 주고 발급 받아야 한다. 출력은 다음과 비슷한 양식이며, A4용지에 출력해야 한다. 

4. 유럽사람이 아니면(ALL NON EU/EEA PASSENGERS) BAG DROP / VISA CHECK DESK 에서 스템프를 찍어야 한다. 일부 여행자들의 불만 중에 하나는 이 스템프가 없어서 탑승 게이트에서 탑승 거절당해 급하게 스템프 받고 다시 탔다는 이야기가 종종 있다. RyanAIr 수화물 맡기는 곳에 가서 이야기 하면 된다. 


5. 무료 수화물이 없고, 가방을 가지고 타는 것은 1인당 1개로 제한한다. 


우리는 대형 캐리어 1개(위탁수화물), 소형캐리어 1개. 백팩1개, 작은 크로스백 1개였다. 위탁 수화물을 제외하고 3개였으니 이것을 2개로 만들었다. 크로스백을 백팩에 넣어 2개로 만들었었다. 

탑승구에서 대기 중에 RyanAir 직원이 오더니 기내에 공간이 충분하지 않아 작은 캐리어를 무료로 위탁 수화물로 처리해주겠다고 했었는데 우리는 직원의 눈을 피해 기내로 가지고 가버렸다. 다음에 그런 상황이 오면 안에 중요한 것들이 있어서 위탁수화물로 맡기기는 곤란할 것 같다고 세련되게 말해야겠다. 


6. 비행기 좌석이 정해져 있지 않다. 좌석 버스 타는 것처럼 예약되지 않은 아무 자리로 가서 착석하면 된다.




유럽의 저가항공은 한국의 저가항공과 많이 다른 시스템이다. 요금이 싼 대신 직접 해야하는 것들이 있다. Check-in, Boarding Pass 출력 등을 직접 해야 한다. 위탁 수화물(Checked Bag)도 돈을 따로 받는다. 요금이 저렴한만큼 감수해야하는 것들이 있다. 


예약은 http://www.ryanair.com/ 에서 하면 된다. 익숙한 한국어가 아니라 약간 스트레스가 있겠지만 간단한 영어만 나오니 별 어려움이 없을 것이다. 좀 어렵다면 Chrome + 자동번역기를 쓰면 큰 두려움은 없을 것이다.

Posted by Picky Kang
,