본문 바로가기

프로그래밍

유니코드 관련 일부 정리....

유니코드 한글처리

유니코드는 대부분의 모든 문자를 포함하는 표준이다. 이 중 한글은 256자의 한글자모 관련 코드와 11184개의 한글 음절 코드, 기타 확장 코드들로 구성된다. 즉, 자모는 초성,중성,종성 각각을 표시하기 위한 집합이며, 이들이 조합되어 완성된 문자가 정의된 부분이 음절코드이다. 이러한 문자들은 정의된 순서대로 정렬되어 있으므로, 해당 코드와 정렬 순서를 이용해 필요한 코드를 조합하거나 분리할 수 있다.(한글자모의 경우 위 순서 뒤로 추가적인 문자들이 들어간다. 하지만 현재 사용하지 않는 글자들이므로, 이곳에서는 언급하지 않는다.)



한글자모 : 0x1100 ~ 0x11FF

완성된 한글코드를 만들기 위해서는 한글자모를 초성,중성,종성 순서표의 값으로 분리해야 한다. 'ㄱ'의 경우 0x1100 이므로, 자모코드 시작값인 0x1100을 빼주면 정렬 순서상 0번째가 되고. 반대로 0번째에 0x1100을 더해주면 초성 'ㄱ'이 되는 식이다.

 

한글자모 시작코드

초성 : 0x1100

중성 : 0x1161

종성 : 0x11A8



한글 초,중,종성 정렬 순서

 0

 ㄱ

 ㅏ

 채움

 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

 

 

 ㅎ

 



 

 

한글자모 : 0x3131 ~ 0x319E

뭐냐? 같은게 왜 또 나오냐? 위의 한글자모는 자모를 혼합해 초,중,종성이로 구분한것이고, 아래 자모는 그 구분이 없는  호환용 코드라 할 수 있다. 즉, 'ㄱ'이 입력되면, 초성 'ㄱ'이 아닌 한글 자음 'ㄱ'(0x3131) 으로 인식하고, 다음 글자에 따라 자음 'ㄱ'(0x3131)이 될수도 초성(0x1100)이 될 수도 있는것이다. 


주요 자모 호환 코드

0x3131

0x314F

0x3132

0x3150

0x3134

0x3151

0x3137

0x3152

0x3138

0x3153

0x3139

0x3154

0x3141

0x3155

0x3142

0x3156

0x3143

0x3157

0x3145

0x3158

0x3146

0x3159

0x3147

0x315A

0x3148

0x315B

0x3149

0x315C

0x314A

0x315D

0x314B

0x315E

0x314C

 0x315F

0x314D

0x3160

0x314E

0x3161

 

 

0x3162

 

 

0x3163



한글음절 : 0xAC00 ~ 0xD7AF

11184개 문자를 표시하며, 완성형 한글처럼 모든 문자가 정의되어 있다. 코드는 0xAC00부터 0xD7A3 까지 사용하며, 나머지는 비어있고, 이후 0xD7FF까지는 자모 확장을 위해 예약된 영역이다. 즉, 한글처리를 위해 사용해야 하는 코드는 아래와 같다.

 

음절 시작코드(10진값, 문자) : 0xAC00 (44032 ,'가' )

음절 마지막코드 : 0xD7A3 ( 55203, '힣' )

 

 

한글음절에서 자모 분해하기

자모는 옛문자등 추가 문자가 포함되어 있으나 음절코드에는 위의 초,중,종성 순서표(코드아님)에 맞게 순차적으로 문자가 구성되어 있다. 초성 19자, 중성 21자, 종성 28자가 서로 합쳐져 모든 조합을 생성하게 되는데, 하나의 초성에 구성 가능한 글자수는 21*28 = 588자가 되고, 마찬가지로 하나의 중성은 28자씩 구성될 수 있다. 즉, 초성은 588자마다 변경되며, 중성은 매 28자마다 변경된다. 이를 바탕으로 실제 코드를 분해하거나 조합할 수 있게 된다.

 

 

한글코드

= 음절 시작코드 + ((( 초성 * 21 ) + 중성 ) * 28 + 종성 )

= 음절 시작코드 + (( 초성 * 588 ) + (중성 * 28 ) + 종성 )

 

 

종성 = (한글코드-음절 시작코드)%28

중성 = ((한글코드-음절 시작코드)/28)%21

초성 = ((한글코드-음절 시작코드)/28)/21


이렇게 분해된 값은 한글 자모의 초/중/종성의 정렬순서가 된다. 당연히 이곳에 자모 시작코드를 더해주면, 한글 자모 코드 값이 나오게 된다.


 

JAVA에는?

JAVA에서는 이러한 처리들을 지원하고 있다. 코드값을 얻기위한 java.lang.String 클래스에서 codePointAt 메쏘드를 사용할 수 있고, 코드를 분해하거나 조합하기 위해 java.text.Normalizer  클래스의 normalize 메쏘드를 사용하면 된다. 사용법이야 별것 없고, 내부적으로는 위의 코드 계산들이 이루어진다고 생각하면 된다. 안타깝게도 codePointAt은 java1.5 부터, Normalizer는 java 1.6부터 지원하고 있으니 소형 플랫폼쪽 개발자들은 직접 구현해야 하는 것에 변함이 없다. -_-;;; 다행히 java가 유니코드를 지원하므로, 내부야 어떻든 사용자가 UTF-8로 인코딩을 설정한다면 세부적인 인코딩 처리는 별도로 필요가 없다. (뭐 시간이 남는다면 바이트별로 쪼개서 비트연산을 해도 된다.)


String han = "한";


일단 코드값을 얻어보자.

int ret = han.codePointAt( 0 );

결과는 '한'의 음절값 0xD55C 가 나오게 된다.  

(char의 경우 int ret = (int)'한' 으로도 코드값을 얻을 수 있으므로, String.charAt 등을 사용할 수 있다.)


자모 분해.

이 값을 자모 분해하기로 계산해 분해해도 되나 Normalizer를 사용해 자모값을 얻을 수 있다.

String jamo = Normalizer.normalize( han, Normalizer.Form.NFD ); 


합치기.

해당 코드는 다시 음절로 합쳐질 수 있다.

String um = Normalizer.normalize( jamo, Normalizer.Form.NFC );


 

 

UTF-8

비트연산을 기어이 하겠다면, 16비트 인코딩 처리를 하면된다. UTF-8은 인코딩에 따라 가변이나 한글의 경우 3바이트 인코딩 영역이므로, 한글은 무조건 3바이트로 처리된다.

0000 ~ 007F : 7비트

0080 ~ 07FF : 11비트  : 110xxxxx 10xxxxxx

0800 ~ FFFF : 16비트 : 1110xxxx 10xxxxxx 10xxxxxx

10000 ~ 1FFFF : 21비트 : 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

 

 

'프로그래밍' 카테고리의 다른 글

[OpenCV] Ball tracking  (0) 2017.10.24
[COCOS2D-X] cocos2d-x 3.0 Eclipse 설정  (0) 2014.05.03