안녕하세요,
러시아에서 아주 가끔 코딩을 하는 개발자 윤진입니다.
유니코드를 뒤적뒤적 살펴보다가,
유니코드에 한글이 어떻게 매핑되어 있는지 궁금해졌습니다.
유니코드에 매핑된 문자를 확인하고 싶으면 유니코드 공식홈페이지를 찾으면 됩니다.
공식 홈페이지에 올라와있는 Unicode 9.0 Character Code Charts에는,
한글 자소와 완성형 한글이 45장에 걸쳐 빽빽하게 기록된 것을 볼 수 있습니다.
한글자소는 초성/중성/종성으로 나눠져 세 그룹으로 표현되어 있습니다.
현대 한글에서 사용하는 초성은,
'ㄱㄲㄴㄷㄸㄹㅁㅂㅃㅅㅆㅇㅈㅉㅊㅋㅌㅍㅎ'로 총 19자입니다.
그렇지만, 한글자소 테이블에는 위의 한글 외에도 기이한 형태의 자음이 복합된 초성이 포함되어 있습니다.
'ㅎ'에 이어서 'ㄴㄱ'이나 'ㄴㄴ', 'ㄴㄷ', 'ㄴㅂ'이 연이어 초성으로 등장하는데요.
어떻게 읽으면 좋을지 감도 떠오르지 않는 문자들이 이어집니다.
무언가 규칙이 있는 것으로 보이는데 쉽게 읽히지는 않습니다.
중성도 한국의 사전순서를 따르고 있습니다.
'ㅏㅐㅑㅒㅓㅔㅕㅖㅗㅘㅙㅚㅛㅜㅝㅞㅟㅠㅡㅢㅣ' 총 21자의 모음이 등장합니다.
그리고 초성과 마찬가지로 가지각색의 이중모음이 뒤따르고 있습니다.
종성도 실제 사용하는 한글부터 등장합니다.
'ㄱㄲㄳㄴㄵㄶㄷㄹㄺㄻㄼㄽㄾㄿㅀㅁㅂㅄㅅㅆㅇㅈㅊㅋㅌㅍㅎ' 총 27자의 받침이 나오고,
사용하지 않는 복합자음이 연이어 나옵니다.
초성과 중성까지 쓰여진 문자에는 종성이 붙지 않거나 27가지 중 한가지 받침이 붙을 수 있습니다.
곧, 종성에는 28가지 경우의 수가 나오게 됩니다.
따라서 완성형 한글을 모두 테이블에 기입하기 위해서는,
초성자음 19자 * 중성모음 21자 * 종성자음(무받침 포함) 28 = 11,172글자
16*16 사이즈의 테이블에는 총 256글자가 들어가니,
11,172글자를 모두 테이블에 담기 위해서는 16*16 테이블 44개가 필요합니다.
물론 11,172글자 중에는 실제로 사용되지 않는 글자도 많이 있습니다.
'퐓, 풺, 햤' 이런 글자는 평소에 구경해본 적도 없습니다.
그렇지만, 유니코드는 사용여부가 아니라, 그저 조합 가능한 모든 경우를 따져 한글코드를 배치하였습니다.
그렇기 때문에 초성/중성/종성 자소만 가지고 완성형 글자의 위치를 쉽게 파악할 수 있습니다.
한글시작위치는 U+AC00로 여기에는 '가'가 매핑되어 있습니다.
그리고 '각갂갃간...' 등 총 28가지의 종성 경우의 수를 지나 29번째에 '개'가 나옵니다.
다시 28개를 지나면 '갸'가 등장합니다.
중성은 총 21개이기 때문에, 'ㄱ'이란 초성이 들어가는 글자는 21 * 28 = 588글자입니다.
'가'가 첫번째에 등장했다면,
'나'는 589번째에 등장하고,
'다'는 1177번째에 등장합니다.
이런 논리라면 한글자모만으로 완성형 글자의 위치를 얻거나
역으로 완성형 코드를 보고 어떤 자모인지 찾을 수 있습니다.
한글_베이스 U+AC00
중성_경우의_수 21
종성_경우의_수 28
함수 자소합치기(초성, 중성, 종성)
{
완성형글자 = 한글베이스 +
(초성 * 중성_경우의_수 * 종성_경우의_수) +
(중성 * 종성_경우의 수) + 종성;
}
함수 자소나누기(완성형글자)
{
초성 = (완성형글자 - 한글_베이스) /
(중성_경우의_수 * 종성_경우의_수);
중성 = (완성형글자 - 한글_베이스) %
(중성_경우의_수 * 종성_경우의_수) / 종성_경우의_수;
종성 = (완성형글자 - 한글_베이스) %
종성_경우의_수;
}
원리를 명확하게 파악하기 위해,
위와 같이 코드를 풀어썼는데 반복되는 루틴이 많으니 실제로 코드에 옮길때는 최적화가 필요하겠네요.
그럼 오늘은 여기서 줄입니다.
좋은 하루 보내세요.
'IT' 카테고리의 다른 글
[C#] 소수점이 있는 숫자는 float일까 double일까. (30) | 2017.02.04 |
---|---|
[C#] readonly 변수를 사용하는 이유는? (30) | 2017.02.02 |
[C#] 왜 partial class를 사용하는걸까요? (34) | 2017.02.01 |
[C#] char[]를 string으로 변환하기 (30) | 2017.01.31 |
[C#] bool.Parser vs Convert.ToBoolean() (0) | 2017.01.30 |
[C#] UTF-16의 캐릭터 크기에 대한 간단한 탐구 (0) | 2017.01.28 |
[C#] int.MaxValue 코딩컨벤션에 대한 사소한 의문 (30) | 2017.01.27 |
[C#] 코딩컨벤션, linux_kernel_coding_style vs camelCase vs PascalCase (2) | 2017.01.26 |
[Visual Studio] Start debugging vs Start without debugging (1) | 2017.01.16 |
[Moonlight] 사요나라, 문라이트 프로젝트 (0) | 2017.01.02 |