UNICODE Seminar – 한국에서 프로그래머 하기 2005.11.22 By bleujin
Global Software? 영역(Territory)별 지원 달력 설정 방법 - 첫번째 요일 - 첫번째 주 날짜 포맷 - 05/08/10 - May.8.2005 - 中華民國94年07月21日 통화 기호 - W, Kč, $, Dual Currency 숫자그룹 - 2,0000.00 - 20,000.00 - 20.000,00 1 / 26
Global Software? 언어(Language)적 지원 캐릭터 셋 - KO16MSWIN949, KO16KSC5601 정렬방식 - Linguistic Sorting(KOREAN_M) 날짜 표기에 사용되는 기호 - month, day, day of week, year 에러메시지 및 번역 2 / 26
Example Example 3 / 26 인코딩, 디코딩 Content-type in HTML, ISO-8859-1?, ISO-8859-5 이메일(웹)이 ????? 보여요, 글자가 깨졌어요.. request.getParam(“val”).getBytes(“euc-kr”), (new FileWriter(“aaa.txt”)).writeln(“abc”) 조합형 한글와 완성형 한글? UTF8? Unicode? ALUTF32, UCS-2, UTF16, UTF32??? UTF7 ??? Code947, i18n, L10N ?c각하, 아?? NLS-Lang?? KO16MSWIN949, KO16KSC5601 3 / 26
Legend Of ASCII 왜 1byte는 8bit 인가? 1byte -> 8bit -> 2^8 -> 256
Legend Of ASCII OEM ASCII의 문제 5 / 26 - OEM 문자 (127) - Code Page (win98, cp437, cp949) - DBCS(아시아권) 5 / 26
Myth of Unicode 유니코드 야사 6 / 26 세계의 모든 문자를 표현할 수 있는 코드 체계를 만들자 - 영어 알파벳 몇백자, 한글 1만자, 한자 2만자.. - 모두 합쳐도 6만자도 안되겠네.. - BMP(Basic Multilingual Plane) - Unicode 3.0 이하 세상일은 그리 만만하지 않다-_- - 한글 고어, 옛 한자 - SP(Supplementary Planes)를 정의 - 1024 * 1024 = 10 ex) 한자는 추가적으로 약 4만자 유니코드 콘소시엄 + 세계 표준기구(ISO) - 1991년 이후 동일한 표준 - ISO / IEC 10646 6 / 26
Myth of Unicode 유니코드 3.1에 정의된 언어 영역 (List of block names for Unicode Standard 3.1) http://www.jinsuk.pe.kr/Unicode/Unicode_intro-kr.html#mislead 유니코드의 구조는 17개의 언어판으로 구성 - 1개의 기본 언어판 + 16개의 보충 언어판 - 17 * 65536 = 114112개 - 2048 7 / 26
Myth of Unicode 유니코드 용어 8 / 26 - 기본언어판, BMP BMP는 Basic Mulitilingual Plane의 약자입니다. 유니코드의 첫 65,536개의 코드를 의미합니다. - 언어판, Plane 256x256 즉 65,536 개씩의 코드 묶음을 이릅니다. 유니코드에서는 현재 17개의 언어판을 사용할 수 있습니다. 모두 그룹 00에 포함됩니다. - 언어판 그룹, Group 256개씩의 언어판을 묶어 하나의 그룹으로 명명합니다. 유니코드의 17개 언어판은 모두 Group 00에 있습니다. 유니코드는 17개의 언어판에 한정되어 정의됩니다. 반면 ISO 표준(UCS-4)에서는 모두 128개의 언어판 그룹이 정의될 수 있습니다. - 1 Plane = 65,536 code points - 1 Group = 256 planes = 256x65,536 = 16,777,216 code points - UCS-4 = 128 groups = 128x16,777,216 = 2,147,483,648 code points 8 / 26
Myth of Unicode 유니코드 용어 9 / 26 - 인코딩, Encoding 문자집합을 표현하는 방식을 말합니다. 유니코드는 코드체계 또는 문자집합을 명명하는 것이며 이를 표현하기 위해서는 UTF-8, UTF-16, UTF-32 등과 같은 인코딩이 필요합니다. UCS-2: Universal Character Set 2(octets) 좀더 정확하게는 Universal Multipe-Octet Coded Character Set 2입니다. ISO/IEC 10646의 용어로 BMP의 65,536 코드를 정의하며, 2바이트로 표현됩니다. 1개의 언어판, 즉 BMP만이 이에 해당합니다. UCS-2는 인코딩 방법이 아니며 문자코드 자체입니다. 인코딩으로 봐도 무방하겠군요. 여기서 octet이라는 용어를 사용했는데 이 용어는 ISO쪽에서 사용하는 용어로, 유니코드 진영에서 사용하는 바이트와 같은 뜻입니다 UCS-4: Universal Character Set 4(octets) ISO/IEC 10646의 용어로 4바이트로 표현됩니다. 모두 128개의 언어판 그룹, 즉 128*256 언어판 = 32,768 언어판을 정의합니다. 이는 대략 231 = 2,147,483,648개의 코드에 해당합니다. UCS-4는 인코딩 방법이 아니며 문자코드 자체입니다. 9 / 26
Myth of Unicode 유니코드 용어 10 / 26 UTF-8: UCS Transformation Format, 8-bit form Unicode 표준의 인코딩 방식중의 하나입니다. 표준에서는 17개 언어판의 문자만을 표현할 수 있으나 기술적으로는 UCS-4 전영역의 문자를 표현할 수 있습니다. 문자에 따라 1 ~ 4(또는 6) 바이트로 표현됩니다. UTF-16: UCS Transformation Format, 16-bit form 유니코드 3.0에서는 16을 16비트로 해석한 것이 아니라, 그룹 00의 16개 언어판이라고 써 놓았군요. UTF-32의 32가 32비트를 지칭하므로 통일성을 위해 16비트로 이해하시는 게 좋습니다. 16비트로 표현한다는 점에서는 UCS-2와 흡사하지만 대행문자영역(Surrogates)을 이용하여 16개의 보충 언어판 코드를 표현할 수 있는 인코딩입니다. 대행문자영역 2개로 16개의 보충 언어판을 표현할 수 있습니다. UCS-2에서는 65536개의 코드만을 정의할 수 있으나 UTF-16에서는 1백만여자를 더 표현할 수 있습니다. UTF-32: UCS Transformation Format, 32-bit form 32비트 즉 4바이트로 각 문자를 표현합니다. 이점에서 UCS-4와 동일하지만 17개의 언어판만을 정의한다는 점에서는 UCS-4의 부분집합으로 간주하면 됩니다. UCS-4와 동일하나 0x00000000 ~ 0x0010FFFF 범위만을 문자코드로 간주한다고 이해하시면 됩니다. 10 / 26
Myth of Unicode 유니코드 인코딩 11 / 26 유니코드에서 지원하는 인코딩 방식은 UTF-8, UTF-16, UTF-32의 세가지 방식입니다. UTF는 UCS Transformation Format의 약자이며, 뒤에 붙은 숫자는 인코딩에 사용되는 단위의 비트수를 의미합니다. 즉 UTF8은 8비트 단위, UTF16은 16비트 단위, UTF32는 32비트 단위로 문자를 표현합니다. 세가지 방식의 공통점이라면 16개의 보충언어판에 위치한 1,048,576개의 코드를 표현할 때는 4바이트를 사용한다는 점입니다. 하지만 그 방식은 모두 다릅니다. UTF8은 4개의 바이트로, UTF16은 2개의 16비트로, UTF32는 1개의 32비트 단위로 표현합니다. 이제 각 인코딩 방식에 대해 좀더 상세하게 설명하겠습니다. 11 / 26
Myth of Unicode 유니코드 인코딩 – UTF16 12 / 26 UCS-2와 거의 동일합니다. 이 인코딩의 기본 단위는 16비트, 즉 2바이트입니다. 대행문자 영역 2,048개를 제외한 63,488개의 코드를 문자로 사용할 수 있으며(BMP), 대행문자 영역 2개의 쌍을 이용하여 16개의 보충언어판에 위치한 1,048,576개의 코드를 표현할 수 있습니다. 대행 문자 2개의 쌍으로 1개의 문자를 인코딩한다는 점에서 UTF-16의 인코딩은 가변적인 인코딩이라고 할 수 있겠군요. 즉 기본언어판의 문자는 2바이트로 보충언어판의 문자는 4바이트로 인코딩됩니다. 이러한 인코딩 방식때문에 UTF-16에서는 유니코드 표준에서 지원하는 17개의 언어판 코드만 표현이 가능합니다. 가장 유니코드다운 인코딩이라고 할 수 있겠군요 :-) UTF-16에서는 상위대행코드가 나타나면 반드시 뒤이어 하위대행코드가 따라와야 합니다. UCS-2에서는 그렇지 아니한 점이 UTF-16과 UCS-2의 차이점입니다. 12 / 26
Myth of Unicode 유니코드 인코딩 – UTF8 13 / 26 UTF-16의 문제 - null byte -> 소프트웨어 재개발 - 저장 공간의 문제 -> DB 설계 다시 - 대안 : UTF8 - 중간 바이트에서 0이 나타나지 않도록) - 1byte에서 4byte의 가변 바이트 UCS-4 UTF-8 0x00000000 - 0x0000007F 0xxxxxxx 0x00000080 - 0x000007FF 110xxxxx 10xxxxxx 0x00000800 - 0x0000FFFF 1110xxxx 10xxxxxx 10xxxxxx 0x00010000 - 0x001FFFFF 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx 0x00200000 - 0x03FFFFFF 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 0x04000000 - 0x7FFFFFFF 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 13 / 26
Myth of Unicode 유니코드 인코딩 – UTF32 Byte Order Mark (ex 0x4E00 b:-, l:N) UTF-8과 UTF-16에 대비해서 고정길이 인코딩이라고 할 수 있겠군요. 4바이트 단위로 표현한다해서 UCS-4와 동일하게 볼 수는 없습니다. 17개의 언어판만을 대상으로 하는 UCS-4의 부분집합이라고 보시면 됩니다(표준상 그렇습니다). 즉 UTF-32의 인코딩 영역은 0x00000000에서 0x0010FFFF로 제한되어야 합니다 (이 제한을 무시하면 UCS-4와 동일합니다). Byte Order Mark (ex 0x4E00 b:-, l:N) 구분 Little-endian Big-endian UTF-16 0xFFFE 0xFEFF UTF-32 0x0000FFFE 0x0000FEFF 플랫폼 Intel, DEC/Alpha 프로세서 RISC 프로세서, Microprocessor 운영체제 MS Window, 리눅스/인텔 Unix, Mac OS 14 / 26
CAMEL PROGRAMMER 한글 한글 한글… 15 / 26 일반 텍스트? - 가가 가가? 제 웹사이트가 깨져 보여요 - Content-type: text/plain; charset=“utf-8” - Explorer 언어 추측 - 언어의 UCS-2 java, c++, c# php 조합형 한글 vs 완성형 한글 - 1 + 2^5 + 2^5 + 2^5 - 아래한글과 MS워드의 싸움 15 / 26
오라클 NLS Setup 16 / 26 위 창은 한국어 저장 여부하고는 아무 Never 절대 상관이 없다. - 번역된 메시지 - 폰트 - 로케일정보 16 / 26
오라클 NLS 올바른 캐릭터 셋을 선택하자 17 / 26 올바른 캐릭터셋이라 함은 한글을 저장할 수 있는 캐릭터 셋을 말한다. 정해진 캐릭터 셋을 가지고 있지 않은 데이터베이스에 결코 한글 데이터를 저장할 수 없다. 이제 US7ASCII와는 헤어질때다. - KO16KSC5601 - KO16MSWIN949 - UTF8 - AL32UTF8 17 / 26
오라클 NLS KO16KSC5601 한글 완성형 코드와 일치( 2350한글(25*94), 4888자의 한자, 히라카나, 카타카나, 영문, 기호 등) UNIX (Lang=ko) default 하지만~~~ KO16KSC5601 캐릭터 셋 사용은 자제하라… 아햏햏 모두에게 먄하게 되었소. 솔믜가 예약했던 커피숖이 배신을 때리는 바람에 그만 낙동강 오리알이 되었지요. 정말 먄하오. 똠방각하 아? ? 모두에게 ?하게 되었소. 솔?가 예약했던 커피?이 배신을 때리는 바람에 그만 낙동강 오리알이 되었지요. 정말 ?하오. ?방각하 18 / 26
오라클 NLS KO16MSWIN949 Windows-949 캐릭터셋은 마이크로소프트사의 Windows Codepage 949번, 즉 한글 코드 페이지를 따른 코드셋이다 완성형(KO16KSC5601)을 그대로 포함하고 있으며, 추가로 현대 한글 조합으로 표현할 수 있는 모든 가짓수에 해당하는 8822자의 한글을 추가해 포함하고 있다. 그러니까 "Windows-949 캐릭터셋은 KSC5601의 수퍼셋(Superset)"이 되며, 따라서 "KO16MSWIN949 또한 KO16KSC5601의 수퍼셋" 이다 다른 운영 체제에서도 사용할 수 있다!" 19 / 26
오라클 NLS UTF8/AL32UTF8 UTF8은 유니코드를 구현한 캐릭터셋 중에 가변길이 인코딩 방식을 택하고 있는 캐릭터셋이다. 자세한 인코딩 방식은 여기에서 논할 필요가 없지만, 가변 길이를 위해 일종의 플래그 비트를 각 바이트마다 포함시켜야 하다보니, 한 글자를 표한하는데 필요한 바이트의 길이가 최대 3바이트(AL32UTF8의 경우 6바이트)까지 늘어날 수 있다. 유니코드는 잘 알려진 바와 같이 현대 한글 11172자를 모두 가나다 순으로 잘 정렬된 상태로 포함하고 있다. 그래도 한글 한 자가 3바이트의 물리적 공간을 차지하므로, 오로지 모든 한글을 지원한다는 이유만으로 사용하는 것은 곤란하다. 하지만, 한글 이외에도 다른 언어들을 함께 데이타베이스에 저장해야 한다면 다른 선택의 여지가 없는 유일한 선택이 된다. 20 / 26
오라클 NLS 한글 캐릭터 셋 비교 21 / 26 KO16KSC5601 KO16MSWIN949 UTF8 AL32UTF8 한글 지원 한글 2350 2350+확장 8822(총11172자) 한글 11172자 인코딩 버전 한글 완성형 확장은 MS949에 따라 배열 Unicode2.1, 3.0 Unicode 3.0, 3.1, 3.2, 4.0 한글 바이트 2 byte 2byte 3byte 지원버전 7.x 8.0.6 이상 8.0 이후 9i R1 이상 Nchar로 설정가능 불가 가능 한글정렬 단순 바이너리정렬 KOREAN_M, UNICODE_BINARY 한글 : 바이너리 한자 : KOREAN_M 장점 없음 2byte로 모든 한글 입출력 가능 정렬이 효과적, 다른언어들과 같이 저장되어야 할 경우 다른 대안이 없음 동일 단점 한글 2350 가능한 사용자제 완성형과 호환 문제로 글자배열순과 정렬순서가 다름 공간의 소모 인코딩/디코딩 시간 21 / 26
오라클 NLS 자. 이걸 기억하자 - KOREAN_KOREA.KO16MSWIN949 (in window) 22 / 26 - 한글 지원을 위해서는 반드시 위의 네 가지 캐릭터셋 중에 하나를 선택해야 한다 - 한국에서만 사용하는 시스템이라면 KO16MSWIN949를 선택한다 - 한국어 뿐 아니라 중국어, 일본어, 러시아어 등 다양한 언어로 된 데이타를 저장해야 한다면 UTF8, AL32UTF8을 선택한다. - 대부분이 한글이며, “일부” 컬럼에 외국어가 필요하다면, 한국어 기반의 캐릭터셋(KO16MSWIN949)을 사용하되, National Characterset을 이용한 컬럼에 외국어를 저장한다. ex) CREATE TABLE test_table ( varchar_value VARCHAR2(2000), nvarchar_value NVARCHAR2(2000) ); NLS_LANG 변수는 데이타베이스에게 사용자의 환경을 알려주는 인식표 역할을 한다. - KOREAN_KOREA.KO16MSWIN949 (in window) - AMERICAN_AMERICA.KO16MSWIN949 - KOREAN_KOREA.KO16KO16KSC5601 (in unix) 22 / 26
오라클 NLS KSC5601에서 지원되지 않는 글자들의 입출력 23 / 26 KO16KSC5601 CS에 얼마든지 그런 글자들을 삽입할 수 있던데요? insert into test(a) values(‘숖’) ; select * from test ? NLS_LANG를 KO16KSC5601로 하면 ? Insert 실패 숖, 똠, 믜, 뾃, 햏 KSC5601 CS의 정렬 한글, 그리고 한문도 한자의 음에 맞게 정렬 그러나 한글 2350자와 한자 4888자에 대한 정렬 지원하지 않는 글자에 대한 정렬은 되지 않음 23 / 26
오라클 NLS MS949에서의 정렬 24 / 26 기존 KO16KSC5601의 수퍼셋으로 군림하려다 보니 총 11172자의 한글의 바이트 코드가 한글의 언어적 정렬 순서와 불일치할 수 밖에 없다 Select * From test Order by a 똠방각하 먄해 가나다라마바사 라디오를켜라 햏햏 Select * From test Order by NLSSORT(a, ‘NLS_SORT=UNICODE_BINARY’) 똠각하 Select * From test Order by NLSSORT(a, ‘NLS_SORT=KOREAN_M’) 24 / 26
오라클 NLS 바로잡기의 필요성을 인식하라 확장 불가, 마이그레이션 불가 25 / 26 Ex) String p_UserComment = new String(request.getParameter(“val").getBytes("KSC5601"),"8859_1"); pstmt.setString(1,p_UserComment); pstmt.executeUpdate(); if(resultSet.next()) { String v_UserComment = new String(resultSet.getString(“val").getBytes("8859_1"),"KSC5601"); 확장 불가, 마이그레이션 불가 25 / 26
오라클 NLS 캐릭터 셋 변경의 위험성 26 / 26 데이터 절삭 데이터 깨짐 - US7ASCII에서 한글데이타를 exp/imp를 이용하여 MS949나 UTF8로 마이그레이션 - 불가능 - KO16KSC5601에서 한글 데이터를….. - 일부 데이터 깨짐 어플리케이션 오동작 - 글자 길이 연산의 오동작 length, instr, substr 기존 캐릭터 셋 새로운 캐릭터 셋 변경가능여부 US7ASCII KSC5601/MS949/UTF8/AL32UTF8 가능 KO16KSC5601 KO16MSWIN949 UTF8 불가능 AL32UTF8 26 / 26
참조 참조 Joel 의 블로그 http://kangcom.com/common/bookinfo/bookinfo.asp?sku=200503170001 www.unicode.org http://ww.unicode.org 오라클 NLS http://www.oracle.com/technology/global/kr/pub/columns/oracle_lns_1.html http://www.oracle.com/technology/global/kr/pub/columns/oracle_lns_2.html 진숙의 Unicode 이야기 http://www.jinsuk.pe.kr/Unicode/Unicode_intro-kr.html Windows tool charmap