Unicode 와 mac 그리고 루비
루비로 맥에서 윈도우 공유폴더 파일을 웹에서 처리하는 것을 하다가 유니코드쪽때문에 엄청 고생했다. ㅠ.ㅠ
결과에 여러 인코딩이 섞여서 변환도 안되고 눈으로 보기에는 정상적인 한글로 보이고 ㅍ,ㅍ 헥사를 까보고 윈도우에서 열어보고 했더니 한글의 인코딩이 뒤죽박죽 ㅋ
우선 루비에서 인코딩 변경
보통 다른 프로그래밍에서도 많이 사용했던 iconv를 사용했다.
<사용법>
# module 선언
require 'iconv'...
# EUC-KR을 UTF-8로 변환하기 위한 선언
conv = Iconv.new('UTF-8', 'EUC-KR')#Convert 'document'
converted = conv.iconv(document)
여기까지는 일반적으로 많이 하는 방식이고 쉽다.
인코딩을 하다가 보면 한글에 확장완성형(?), 특이한 글자가 있으면 에러가 발생하고 멈춘다.
이 때 이 에러를 무시하고 값을 얻을려면 아래와 같이 //IGNORE 를 추가하면 된다.
conv = Iconv.new('UTF-8//IGNORE', 'EUC-KR')
루비에서 이런 형태로 언하는 인코딩간에 서로 변환을 한다.
* 참고로 루비에서는 유니코드 형태가 1.8x에서는 지원이 안되어서 그냥 byte단위 string을 가지고 있는 그냥 뭉텅이 메모리이다. 그래서 한글에 대해서는 스트링 연산자가 정상동작을 안한다.
여기까지 알면 보통 내가 사용하는 곳들의 인코딩 종류만 알면 그것에 맞추어 변경을 해서 통일만 시켜주면 왠만큼 문제가 없다. 보통 웹이랑 다른 곳에 utf8을 많이 사용하고 나도 이런저런곳에 많이 이용해서 utf8을 기본으로 맞추려고 했다.
윈도우: CP949 (or EUC-KR 등..)
Mac: UTF-8 (UTF-8-MAC)
윈도우에서 가져오는 것이니 그냥 CP949를 UTF-8 로 변환하면 될 줄 알았다.
그런데 변환을 하니 이상해서 윈도우에서 가져오는 부분의 한글 헥사를 까보면 UTF-8 과 전혀 다른 형태의 헥사값이 나오는 것이다.
E1 84 92 E1 ~ 이런 헥사들이 나열되는데 이 형태는 UTF-8-MAC 이다.
이 형태를 본적이 없고 갯수도 많아서 무슨 인코딩인지를 몰라 엄청 해멧다.
이 UTF-8-MAC 라는 놈이 어떤 놈인지 잘 모르는 것도 크게 기인을 하였다. 웹마다 설명이 조금씩 다르게 되어있고 용어도 달라서 검색도 잘 안되고 ㅠ.ㅠ
UTF-8-MAC은 기본 UTF-8에서 한글같은 것을 맥 파일시스템에 맞춰 자소 단위로 분해해서 처리하는 것이다.
UTF-8 값들을 보면 한글에서 '하' 같은 경우 '하' 도 있고 'ㅎ' 'ㅏ' 각각도 있다.
Mac에서는 파일쪽 처리에서 특히 파일시스템과 연관되어 '하' 같은 것을 'ㅎ' 'ㅏ' 형식으로 나누어서 저장되고 이 것을 UTF-8-MAC로 부른다. 그래서 헥사값을 보면 한글은 첫 헥사값이 E1 이 많다.
이 부분 때문에 맥과 윈도우간에 파일 이름을 변경하거나 하면 자소단위로 분해된 형태로 보이게 된다.
여기서 헥사값을 보는 부분에서도 많이 고생하게 되었는데 헥사값을 UTF-16형태로 보면 'ㅅ' 같은 경우 0x1109 가 된다.
근데 이걸 UTF-8 형식의 헥사로 보면 0xE18489 가 된다. (정확히는 3바이트와 4바이트 처리에서 오는 듯.)
보통 설명할 때 UTF-16 값으로 설명을 많이 하고 나같은 경우 VC에서 많이 보다 보니 UTF-16 헥사에 눈이 익어서 더 헷갈렸다.
맥은 UTF-8이므로 헥사의 자모를 찾을 때도 UTF-8의 자모를 찾아서 보면 된다.
UnicodeChecker 라는 툴을 웹들을 보다가 알게 되었는데 엄청 괜찮다. 애가 없었으면 얼마나 고생을 더 했을지 ㅠ.ㅠ
한글 글자를 치면 자기가 해당 hex값을 찾아주고 utf8, utf16등 몇가지 헥사값을 같이 보여준다.
자소분해되고 합쳐지는 부분을 사람들 마다 약간씩 다르게 부르는데 여기서 말한 것 처럼 자소분해라고 하기도 하고 NFD와 NFC로 표현하기도 하고 처가끝 형태라고도 하고 기타 등등 다양한 용어로 설명을 해주심.
기타 도움 된 설명들 인용
<출처: http://www.appleforum.com/application/6069-jterminal.html>
맥에서 파일 시스템은 UTF-8을 씁니다.
UTF-8이긴 한데, disjoint된 한글 셋인 U+1100 영역의
유니조합형을 쓰기때문에 웬만하면 그냥 해서는 잘 안보입니다.
제대로 보이게 하려면 파일 시스템에 접근할 때에만
U+AC00 영역으로 conjoin 해줘야하는데, 그게 한글음절
영역에만 적용되는 거라서.. 애플에서 왜 유독 파일시스템에만
U+1100을 쓰는지는 도저히 이해할 수 없습니다.
U+1100이 단점만 있는 건 아니지만, 다른 글자로 된
것은 POSIX레이어로 접근해도 아주 쉬운데 오직 한글만
특별처리를 해야하는게.....
한글패치 메일링리스트 (http://www.kr.freebsd.org/ml/archive...patch/2002/06/)
에서는 유니조합형을 위한 폰트를 만들려는 움직임도
약간 있었는데 어떻게 됐는지는 잘 모르겠네요..
여담으로, GTK2에서는 입력장치에서 U+1100을 쓰는 한글 입력기가
얼마전 등장했습니다.
참 그리고, U+1100뿐 아니라 U+AC00도 허용하기때문에 파일이름이
겉보기엔 같은게 사실 상 2개가 존재할 수 있습니다. -.-;;;
그게 사실은 UTF-8과 UTF-16은 그냥 그 인코딩으로 변환만 해주면
되는 거라 애플리케이션에서 쉽게 처리가 가능한데요. 가장 큰 문제는
한글을 다른데서는 다 U+AC00을 쓰면서 파일시스템에서만 U+1100을
쓴다는 문제입니다. (또는 Finder만 U+1100을 쓰는지도 모르겠습니다.)
U+1100영역은 한글 조합형이구요. 초성, 중성, 종성, 고어초성, 고어중성,
고어종성을 가지고 있습니다. 그리고, U+AC00은 한글 완성형이라서
초성 19벌, 중성 21벌, 종성 28벌(종성없는것 포함)을 조합한
19x21x28=11172글자를 순서대로 가지고 있는데, 조합형으로 하면
UTF-16이나 UCS2로 써도 한글 한 글자에 4~6바이트이고,
UTF-8로 쓰면 한글자에 9바이트씩 되어버려서
사실상 한글유니코드라고 하면 U+AC00을 다 쓰고 있습니다.
그런데, MacOS X에서 파일시스템에는 유독 U+1100으로 인코딩된
코드를 집어 넣는다는 것이 문제가 됩니다.
예.. UFS에서는 UTF-8을 쓰는 것 같은데, 속도가 워낙 느려서
못 쓰겠더군요 흐르르;;
음.. 이해를 돕기 위해서 한글이 저장되는 단계를 순서대로 해보면..
'한글' 이란 파일을 만들때
파일을 만들려고 타이핑을 한다:
unicode-aware한 API로 접근할때 // 0xd55c 0xae00 (UCS2)
BSD API를 사용할 때 // 0xed 0x95 0x9c 0xea 0xb8 0x80 (UTF-8)
BSD API-Mach또는 아쿠아-Mach 간의 인터페이스 상에서 파일관련 API로 전달하면서 변환:
0x1112 0x1161 0x11ab 0x1100 0x1173 0x11af (UCS2)
Mach에서 FS담당 서브시스템에 전달:
HFS+를 쓸 때 //
0x11 0x12 0x11 0x61 0x11 0xab 0x11 0x00 0x11 0x73 0x11 0xaf
(UTF-16)
UFS를 쓸 때 //
0xe1 0x84 0x92 0xe1 0x85 0xa1 0xe1 0x86 0xab 0xe1 0x84 0x80 0xe1 0x85 0xb3 0xe1 0x86 0xaf
(UTF-8)
다시 디렉토리 읽는 API가 호출됐을 때 전달:
BSD API인 경우:
0xe1 0x84 0x92 0xe1 0x85 0xa1 0xe1 0x86 0xab 0xe1 0x84 0x80 0xe1 0x85 0xb3 0xe1 0x86 0xaf
(UTF-8)
그 외의 경우:
0x1112 0x1161 0x11ab 0x1100 0x1173 0x11af (UCS2)
아시겠지만 그냥 참고로 0x1112는 초성 기역, 0x1161은 중성 아,
0x11ab는 종성 ㄴ 이구요.0xd55c는 완성형 '한'.. 이런 식입니다.
유니코드 0x1112를 UTF-16으로 쓰면 0x11 0x12가 되구요.
UTF-8로 쓰면 0xe1 0x84 0x92 세바이트로 늘어납니다.
흠 앞에 적은 내용이랑 거의 같은 말인데 중간에 추가 이해에 도움을 주신 부분들이 있어서 같이 인용합니다.
결과적으로 한 것은 iconv는 그냥 utf-8-mac => utf-8 로 변환해주면 끝이다.
utf8Encoder = Iconv.new('UTF-8//IGNORE','UTF-8-MAC')
눈에 보이는게 문제다. ㅠ.ㅠ 에디터에서 한글을 잘보여주니 인코딩이 서로 막 섞여 개판인 것도 같은 한글로 보여주어서 문슨 인코딩 상태인지를 몰라 더 고생했네.
예전에 리눅스랑 친하게 지낼일이 생겨 심하게 고생하고는 인코딩으로 한동안 크게 고생은 안했는데 맥에 와서 또 한번 심하게 당하네 ㅠ.ㅠ
* 이게 입력이나 에디터 같은 곳은 UTF-8 처리를 하는 곳이 있고 파일 관련 검색이나 파일시스템 관련된 쪽은 UTF-8-MAC으로 처리되어 꼬일때도 좀 있다.
아래는 터미널 예제 (출처: http://mcchae.egloos.com/10686522)
터미널에서$ find . | grep 시크릿이렇게 주었을 때, find . 의 결과는 UTF-8-MAC 인코딩 결과로 나오지만,터미널의 "시크릿"은 UTF-8 인코딩 입니다.고로,OSX에서는$ find . | iconv -c -f UTF-8-MAC -t UTF-8 | grep 시크릿이런 식으로 검색하면 한글 검색이 잘 됩니다.~/.profile 등에alias hgrep='iconv -c -f UTF-8-MAC -t UTF-8 | grep '와 같이 alias 를 추가하시면,$ find . | hgrep 시크릿와 같은 식으로 검색 가능합니다. ^^
참고자료
http://sirius2k.springnote.com/pages/135738
http://namoda.springnote.com/pages/4922363
http://aero2blog.blogspot.com/2011/07/macos-x.html
[Unicode_1.0.pdf]: http://jamestic.egloos.com/2634510
http://parkpd.egloos.com/3367783
http://b.mytears.org/2005/01/101
<Util> UnicodeChecker (http://earthlingsoft.net/UnicodeChecker/)
기타 응용에 도움을 줌
http://www.cogno.org/2011/01/blog-post_6147.html