Codebreaker 2bc08752a0894eb2c7afb345286e391d

14Feb/103

한자-한글 변환

오랜만의 한국어 포스팅이다.

나는 어렸을 때 한자 공부를 열심히 하지 않아서 그런지, 이런 글을 보면 무언가 거부감이 든다. 한자와 한글의 병용을 주장하는 글을 한자 혼용으로 작성해놓은 이유는 무엇인가.

본문에 따르자면 한자를 배워야 하는 이유를 다음의 몇가지로 요약할 수 있다.

  1. 성명의 한자 표기를 통해 자기의 근본을 알고 자기 정체성을 확립한다.
  2. 어휘력을 풍부하게 한다.
  3. 단어의 뜻을 명확하게 알 수 있다.

먼저, 자기의 성과 이름을 한자로 쓸 줄 알고 자기의 근본을 알고 자기정체성을 확립하는 것과 일상 생활에서 한자를 병용하는것은 별 관계가 없어보인다. 또, 흔한 경우는 아니지만, 한글 전용으로 인해 특정 단어의 의미가 명확하지 않은 경우가 있을수도 있는데, 이런 경우에 한해서만 괄호 안에 대응되는 한자를 넣어주는 한자 병용으로 문제를 해결할 수 있다. 대부분의 경우에 한글 전용으로도 의미가 확실히 전달되는데에도 불구하고 굳이 한자를 쓰는것은 대단한 자원의 낭비라고 생각된다.

본문 중에 다음과 같은 내용이 있다.

例를 들어 여기 흔히 쓰이는 정신 나간 사람이라고 할 때 ‘井神, 定身, 廷臣, 精神, 挺身, 正信, 貞臣, 淨神, 正身, 情神, 鼎臣’ 등이 있는데 이 중 어느 정신인지 漢字를 모르면 구분이 잘 안 된다.

주장하고자 하는 바가 무엇인지 대략 짐작이 가지만, 예를 조금 잘못 선택한것 같다. 위의 문맥에서 쓰인 '정신'이 어떤 뜻의 정신인지 모르면 정말로 정신 나간 사람이 아닐까 한다.

이것 이외에도 적절하지 않은 뒷받침 내용이나, 출처나 사실 여부를 알 수 없는 서술문, 논리적 오류가 보이지만, 이 글을 쓰는 목적이 위의 글을 비판하기 위함이 아니므로 본론으로 넘어가도록 하겠다.

오늘 이 글을 쓰는 목적은 한자-한글 변환기를 공개하는 것이다. 이것 덕분에 위의 한자 혼용 글도 읽고 이해할 수 있었다.

일단, 약 3만개의 한자-한글 매핑 데이터를 여기서 얻어왔다. 이것을 파이썬의 사전(dictionary) 형식으로 표현하고, 변환할 문자열에서 한 글자씩 한자에서 한글로 변환하는 방식이다. 핵심 기능을 하는 코드는 다음의 한 줄이 전부이고, 나머지는 사용자의 입력을 받고 결과물을 보여주기 위한 코드이다.

map(lambda x: x in dict and dict[x] or x, post['query'])

map 함수가 어떤 기능을 하는 것인지 모르겠으면 이 문서를 읽어보길 바란다. map, reduce, filter 과 같은 higher-order function 들을 잘 쓰면 프로그램을 간결하면서도 효과적으로 작성할 수 있다.

5Jul/061

한글 음절(syllable) 다루기

서론

음절은 하나 또는 그 이상의 말소리로 이루어져 독자적으로 발음되는 가장 작은 단위이다. 또 다른 말로는 '소리마디', 영어로는 syllable 이라고 한다. 한글의 음절은 초성, 중성, 종성으로 이루어진다. 초성과 중성은 반드시 있어야 하지만 종성은 없어도 음절을 구성하는데 지장이 없다. 더 자세히 들어가면 나의 국문학적 무지가 탄로날지도 모르니 서론은 여기서 그만 하도록 하겠다.

본론

간단하게 음절을 다루는 클래스, Syllable 을 작성하기로 했다. 내부적으로 초성, 중성, 종성을 분리하여 저장하고 있으며, 몇 가지 편리한 메소드를 제공한다.

Syllable 클래스를 작성하기 시작한지 얼마 지나지 않아서 문제에 봉착하게 되었다. 키보드에서 'ㄱ' 을 눌러서 타이핑된 글자의 코드는 0x3131 이지만, unicode specifications 에 나와있는 초성의 'ㄱ'은 0x1100, 종성의 'ㄱ'은 0x11A8 이다. 이 문제를 해결하기 위해 외부적으로는 0x31310x1100 이 모두 허용되도록 하고, 내부적으로는 specifications 에 나와있는 코드를 쓰기로 결정했다.

음절을 만드는 방법은 다음의 3가지가 있다.

방법 1

빈 음절 인스턴스를 만든 후, 초성, 중성, 종성을 따로 집어넣는다.

Syllable s1 = new Syllable();
s1.setChoSeong('ㅂ');
s1.setJungSeong('ㅡ');
s1.setJongSeong('ㄹ');

방법 2

방법 1과 비슷하다. 단지 생성자가 그 일을 대신할 뿐이다.

Syllable s2 = new Syllable('ㄹ', 'ㅗ');

방법 3

마지막으로, 생성자에 완전한 음절을 집어넣는 방법이 있다.

Syllable s3 = new Syllable('그');

예제

System.out.print(s1);
System.out.print(s2);
System.out.print(s3);

실행 결과는

블로그

전체 코드를 공개하면 좋겠지만, 안타깝게도 Syllable 클래스의 소스코드는 당분간 공개하지 않기로 결정했다. 대신, 프로토타입 정도는 공개한다.

public class Syllable {

    private char choSeong;
    private char jungSeong;
    private char jongSeong;

    public Syllable();
    public Syllable(char syllable);
    public Syllable(char choSeong, char jungSeong);
    public Syllable(char choSeong, char jungSeong, char jongSeong);

    public void setChoSeong(char choSeong);
    public char getChoSeong();
    public void setJungSeong(char jungSeong);
    public char getJungSeong();
    public void setJongSeong(char jongSeong);
    public char getJongSeong();

    public String toString();

    public static boolean isSyllable(char character);
    public static char[] split(char syllable);
    public static char build(char choSeong, char jungSeong, char jongSeong);
}

참고 자료

Tagged as: , 1 Comment
27Jun/069

한글 자소 분리

레몬향기혜성님이 쓴 포스트를 보고 Java 로 conversion 해봤다.

학교 도서관 컴퓨터로 프로그래밍 하는 일은 그다지 유쾌한 일이 아니다. 개발도구가 설치되어있지 않음은 물론이고 Administrator Privilege 도 없어서 소프트웨어를 마음대로 설치할 수 없다. 그래도 다행인것은 Eclipse는 설치하지 않고 실행이 가능하다는 점과, Mac 에서는 Netbeans 도 설치하지 않고 실행할 수 있다는 점이다.

아무튼, 이 클래스는 도서관에 있는 Power Mac 으로 힘들게;; 작성했다. 인코딩은 UTF-8 으로 설정해야 된다.

/*
 * Jaso.java
 *
 * Created on June 27, 2006, 3:12 PM
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */

import java.util.Vector;

/**
 *
 * @author guest
 */
public class Jaso {

    public static char[] ChoSeong = { 0x3131, 0x3132, 0x3134, 0x3137, 0x3138,
            0x3139, 0x3141, 0x3142, 0x3143, 0x3145, 0x3146, 0x3147, 0x3148,
            0x3149, 0x314a, 0x314b, 0x314c, 0x314d, 0x314e };
    public static char[] JungSeong = { 0x314f, 0x3150, 0x3151, 0x3152, 0x3153,
            0x3154, 0x3155, 0x3156, 0x3157, 0x3158, 0x3159, 0x315a, 0x315b,
            0x315c, 0x315d, 0x315e, 0x315f, 0x3160, 0x3161, 0x3162, 0x3163 };
    public static char[] JongSeong = { 0x0000, 0x3131, 0x3132, 0x3133, 0x3134,
            0x3135, 0x3136, 0x3137, 0x3139, 0x313a, 0x313b, 0x313c, 0x313d,
            0x313e, 0x313f, 0x3140, 0x3141, 0x3142, 0x3144, 0x3145, 0x3146,
            0x3147, 0x3148, 0x314a, 0x314b, 0x314c, 0x314d, 0x314e };

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        try {
            char[] chars = "대한민주주의공화국".toCharArray();
            Vector<character> v = new Vector<character>();

            for (int i = 0; i < chars.length; i++) {
                if (chars[i] >= 0xAC00 && chars[i] <= 0xD7A3) {
                    int i1, i2, i3;

                    i3 = chars[i] - 0xAC00;
                    i1 = i3 / (21 * 28);
                    i3 = i3 % (21 * 28);
                    i2 = i3 / 28;
                    i3 = i3 % 28;

                    v.add(ChoSeong[i1]);
                    v.add(JungSeong[i2]);
                    if (i3 != 0x0000)
                        v.add(JongSeong[i3]);
                }
                else {
                    v.add(chars[i]);
                }
            }

            System.out.println(v);
        }
        catch (Exception e) {
            e.printStackTrace();
        }
    }

}

결과는 다음과 같다.

[ㄷ, ㅐ, ㅎ, ㅏ, ㄴ, ㅁ, ㅣ, ㄴ, ㅈ, ㅜ, ㅈ, ㅜ, ㅇ, ㅢ, ㄱ, ㅗ, ㅇ, ㅎ, ㅘ, ㄱ, ㅜ, ㄱ]
Tagged as: , 9 Comments