2012년 11월 17일 토요일

Unicode 2.0 에서 한글의 이해

요즘 SNS이나 SNG등등 기계적으로 문장을 생성하는 프로그램들이 넘쳐나는 시대에 의외로 한글처리를 제대로는 프로그램들이 드물구나 하는 생각에 간단한 한글 자소 분석기를 만들어보았다.
링크는 이쪽(http://jsbin.com/ofoqal/10/edit)

애초에 만든 목적은 다음과 같다.
조사처리(은/는, 이/가, 을/를 등등)를 위해 단어의 마지막 글자의 종성을 조사하기 위함인데 예문을 들어보자면

"준기 강남에서 사진 찍었다."
"예슬 홍대에서 식사 했다."
"슬기 대화방에서 나갔습니다."

"준기님은 강남에서 사진님을 찍으셨습니다 고갱님" 이라고 말하면 할말 없다.

한국식 소프트웨어(꼭 소프트웨어가 아니더라도)의 특징이자 장점이 무엇이냐라고 물으면
귀찮을 정도로 깨알같은 디테일이라고 대답할텐데 한글 기계화 작업에 대한 중요성은 프로그램을 만드는 사람들에게도 별로 중요하게 다가오지 않나보다.

에또 사설이 길었다.
한때 우리는 한글코드체계의 비표준 숲속에서 너무도 괴로운 나날들을 보낸 역사가 있다.
KSC5601부터 시작해서 Microsoft통합형한글을 지나 Unicode 2.0의 시대가 왔다.

개인적으로 UTF-8을 사용하지 않고 EUC-KR이나 CP949를 쓰는 제품이나 서비스의 업체의 대표/관계자에게 1억 미만의 벌금 혹은 3년 이하의 금고형의 실형을 내려줬으면 할 정도로 너무나 많은 사람들을 불행하게 하고 막대한 비용을 지출한 악의 근원이라고 생각한다.

하지만 광명이 왔다.
기계적으로 납득이 가능한 검색 및 정렬이 용이한 Unicode 의 시대가 열렸단 말이다.
지금 당신이 복사해서 붙이고 있는 팁들 보다 훨씬 쉽고 명쾌하니 다음 그림을 한번 보자.
어떤가?
무쟈게 쉽지 않은가?

현대 한글은 초성 19자, 중성 21자, 종성 27자로. 총 19 x 21 x 28 (종성없음 포함) = 11172자 되겠습니다.
빈값이 없이 빽빽하게 들어찼단 말이다.

초성은 ㄱㄲㄴㄷㄸㄹㅁㅂㅃㅅㅆㅇㅈㅉㅊㅋㅌㅍㅎ (19자)
중성은 ㅏㅐㅑㅒㅓㅔㅕㅖㅗㅘㅙㅚㅛㅜㅝㅞㅟㅠㅡㅢㅣ(21자)
종성은 (없음)ㄱㄲㄳㄴㄵㄶㄷㄹㄺㄻㄼㄽㄾㄿㅀㅁㅂㅄㅅㅆㅇㅈㅊㅋㅌㅍㅎ(28자)

이것 밖에 없다.
교ㅑ
  ㄱ
이런거 안된단 말이다.

자 지금 당장 javascript console을 열고 이렇게 쳐보자.
저 대로라면 한글의 가장 첫번째 글자는 무엇일까?
당연 '가' 되겠다.

> '가'.charCodeAt().toString(16).toUpperCase()
"AC00"

그렇다. 이게 시작이다. 0xAC00. 10진수로 44032.
그럼 '문' 이건 어떻게 될까?
초성인 'ㅁ'이 6번째
중성인 'ㅜ'이 13번째
종성인 'ㄴ'이 4번째 되시겠다.
44032+6*21*28+13*28+4 = 47928 인거다.

> String.fromCharCode('가'.charCodeAt() + 6*21*28 + 13*28 + 4 )
"문"

아름답다. 아름다와.
같은 방법으로 초중종을 분리해보자.

47928(문)-44032(가)=3896 이니
3896 을 기준으로

초성 Math.floor(3896/21/28) = 6(ㅁ)
중성 Math.floor((3896 - 6*21*28)/28)=Math.floor(3896/28-6*21) = 13(ㅜ)
종성 3896 % 28 = 4(ㄴ)

이게 전부다. 코드도 그냥 이것대로 한거고.
애초에 초반에 말했던 을/를, 이/가 등의 조사를 구분하는 함수를 만든다면 어떨까?

var hasJongsung = function(word) {
  return !!(word && word[word.length -1].charCodeAt()>=0xAC00 && word[word.length -1].charCodeAt()<=0xD7A3 && (word[word.length -1].charCodeAt()-0xAC00)%28);
};

그저 이렇게 한 줄 코드로 해결할 수 있다.
종성이 있을 경우 true를
종성이 없거나 한글이 아닐 경우 false를 반환한다.

지금 만들고 있는 프로그램에도 한번 적용해보자. 고기덕후세종대왕느님들이 고생해서 만든 글인데 아깝지 않은가?