본문 바로가기

[Python] 영문 > 한글 키보드 입력 변환하기 :: 자모결합 / 자소결합

Python 2021. 1. 29.

반응형

영어로 이루어진 키워드를 한글로 변환해야하는 일이 있었다. 예를들어 '사과'를 입력하고 싶었으나 'tkrhk'로 입력된 경우를 찾기 위해서다.

 

내가 생각한 방법은 'tkrhk'의 알파벳을 영-한 입력 딕셔너리에서 찾아서 대치하는 방법이다.

자세한건 아래에서 코드와 함께 봅시다!

 

 

1. 영문-한글 키보드 딕셔너리 생성

# 자음-초성/종성
cons = {'r':'ㄱ', 'R':'ㄲ', 's':'ㄴ', 'e':'ㄷ', 'E':'ㄸ', 'f':'ㄹ', 'a':'ㅁ', 'q':'ㅂ', 'Q':'ㅃ', 't':'ㅅ', 'T':'ㅆ',
           'd':'ㅇ', 'w':'ㅈ', 'W':'ㅉ', 'c':'ㅊ', 'z':'ㅋ', 'x':'ㅌ', 'v':'ㅍ', 'g':'ㅎ'}
# 모음-중성
vowels = {'k':'ㅏ', 'o':'ㅐ', 'i':'ㅑ', 'O':'ㅒ', 'j':'ㅓ', 'p':'ㅔ', 'u':'ㅕ', 'P':'ㅖ', 'h':'ㅗ', 'hk':'ㅘ', 'ho':'ㅙ', 'hl':'ㅚ',
           'y':'ㅛ', 'n':'ㅜ', 'nj':'ㅝ', 'np':'ㅞ', 'nl':'ㅟ', 'b':'ㅠ',  'm':'ㅡ', 'ml':'ㅢ', 'l':'ㅣ'}

# 자음-종성
cons_double = {'rt':'ㄳ', 'sw':'ㄵ', 'sg':'ㄶ', 'fr':'ㄺ', 'fa':'ㄻ', 'fq':'ㄼ', 'ft':'ㄽ', 'fx':'ㄾ', 'fv':'ㄿ', 'fg':'ㅀ', 'qt':'ㅄ'}

한글의 초성/중성/종성을 참고하여 영→한 키보드 입력에 따른 딕셔너리를 생성하였다.

- 초성: ㄱㄲㄴㄷㄸㄹㅁㅂㅃㅅㅆㅇㅈㅉㅊㅋㅌㅍㅎ (19개)

- 중성: ㅏㅐㅑㅒㅓㅔㅕㅖㅗㅘㅙㅚㅛㅜㅝㅞㅟㅠㅡㅢㅣ (21개)

- 종성: ㄱㄲㄳㄴㄵㄶㄷㄹㄺㄻㄼㄽㄾㄿㅀㅁㅂㅄㅅㅆㅇㅈㅊㅋㅌㅍㅎ (27개) - 종성이 없는 경우도 있음

 

초성에는 ㄳ, ㄵ, ㄶ... 등과 같은 두 자음이 결합된 글자가 없다. 그래서 초성은 cons(자음)에서 검색하면 된다.

하지만 종성은 두 자음이 결합된 글자가 있다. 이 자음을 어떨 때 분리해야할지가 핵심이다.

키워드 '물티슈'의 자모를 분리하면 'ㅁㅜㄹㅌㅣㅅㅠ'가 된다. 이중 ㄹㅌ을 종성의 ㄾ로 인식할지 종성과 초성의 ㄹㅌ로 인식할지가 중요하다. ㄾ로 인식하면 '뭁ㅣ슈'가 되어버리지만 ㄹㅌ로 인식하면 '물티슈'로 정상적으로 나타난다.

 

'어떻게하면 초성의 자음인지 종성의 자음인지 구분할 수 있을까?'를 고민해보았다.

- 초성 뒤에는 무조건 모음(중성)이 온다.

- 초성은 자음이 한 글자이다. 

- 모음은 중성이다.

- 초성과 중성은 무조건 있다. 종성은 있을 수도 있고 없을 수도 있다.

 

위 세가지에 따라 아래 코드를 작성하였다.

 

 

2. 딕셔너리에서 영문에 따른 한글 찾기 & 자모 합치기

# 자모결합 패키지
pip install hangul-utils
#! pip install hangul-utils
from hangul_utils import join_jamos

def engkor(text):
    result = ''   # 영 > 한 변환 결과
    
    # 1. 해당 글자가 자음인지 모음인지 확인
    vc = '' 
    for t in text:
        if t in cons :
            vc+='c'
        elif t in vowels:
            vc+='v'
        else:
            vc+='!'
	
    # cvv → fVV / cv → fv / cc → dd 
    vc = vc.replace('cvv', 'fVV').replace('cv', 'fv').replace('cc', 'dd')
	
    
    # 2. 자음 / 모음 / 두글자 자음 에서 검색
    i = 0
    while i < len(text):
        v = vc[i]
        t = text[i]

        j = 1
        # 한글일 경우
        try:
            if v == 'f' or v == 'c':   # 초성(f) & 자음(c) = 자음
                result+=cons[t]

            elif v == 'V':   # 더블 모음
                result+=vowels[text[i:i+2]]
                j+=1

            elif v == 'v':   # 모음
                result+=vowels[t]

            elif v == 'd':   # 더블 자음
                result+=cons_double[text[i:i+2]]
                j+=1
            else:
                result+=t
                
        # 한글이 아닐 경우
        except:
            if v in cons:
                result+=cons[t]
            elif v in vowels:
                result+=vowels[t]
            else:
                result+=t
        
        i += j


    return join_jamos(result)       

1 ) 해당 글자가 자음인지 모음인지 확인

anfxltb=물티슈 일 때,

우선 a n f x l t b 이 알파벳 하나하나가 자음인지 모음인지 확인하여 순서대로 vc에 담았다.

알파벳이 자음이면 c 모음이면 v를 받아오도록 하였다.

특수문자, 숫자, 한자의 경우 ! 를 받아올 수 있도록 하였다. 글자수만큼 vc가 채워져야하기 때문에 아무거나 넣었다.

자 이제, anfxltb의 vc는 'cvccvcv'가 되었다. 

 

- 초성 뒤에는 무조건 모음(중성)이 온다.

- 초성은 자음이 한 글자이다. 

- 모음은 중성이다.

- 초성과 중성은 무조건 있다. 종성은 있을 수도 있고 없을 수도 있다.

 

위에서 말한 네 가지에 따라 한글의 음절에 'cv'는 무조건 들어있게 된다. 

즉, v앞의 c는 무조건 초성이고, v는 무조건 중성이 된다. 

v뒤에 오게되는 c(자음)가 초성인지, 종성인지가 관건이다.

- 만약 종성이 없어서, 뒤따라 오는 자음이 초성이라면 또다시 'cv'가 반복될 것이다. ex. 사자=cvcv

- 종성이라면 'ccv'(물티) 혹은 'cccv'(묽다)가 된다.

 

cv에서 v는 무조건 중성이니까 계속 v로 표현하지만, c는 초성임을 구분지을 필요가 있었다.

그리하여 cv=fv로 대치하였다. 

 

하지만 중성에도 ㅘ(hk), ㅞ(np)와 같이 영타 두 글자가 한글 한 글자를 나타나는 글자도 있었다.

이는 'cvv'로 나타날 것이기에 'fVV'로 대치해주었다. 'fV'로 하지 않은 것은 vc와 text의 글자수가 같도록 유지해야했기 때문이다.   ex. 사과 = cvcvv → 잘못 분리하면 '사고ㅏ' 됨

 

anfxltb는 이제 'fvcfvfv'가 되었다. 이제 남은 c는 종성을 의미한다.

- cc이면 자음 두개가 합쳐진 글자인 것이다. ㄺ, ㄶ → cons_double(두 글자 자음)에서 검색하도록

- c이면 그냥 자음을 의미한다. → cons(자음)에서 검색하도록

 

 

2 ) 자음 / 모음 / 두글자 자음 에서 검색

text의 알파벳 하나하나를 딕셔너리에 검색하도록 한다. 

 

- f(초성)이거나 c(자음) 이면 cons에서 검색하도록 한다.

- V(두 글자 모음)이면 vowels에서 연속되는 알파벳 두개를 검색하도록 한다. 이때 while문에서 다음 글자는 건너가야하므로 j+=1을 해주었다. (그냥 j는 1인데 여기에 j + 1을 해줌)

- v(모음)이면 vowels에서 검색하도록 한다.

- dd(두 글자 자음)이면 cons에서 연속되는 알파벳 두개를 검색하도록 한다. 마찬가지로 while문에서 다음 글자는 건너가야하니 j+1을 해주었다.

 

한글일 경우 초성/중성/종성의 규칙에 맞는다. 하지만 apple과 같은 일반 영단어는 초성/중성/종성의 규칙에 따르지 않아 오류가 발생한다. 따라서 try ~ except문으로 한글일 경우와 한글이 아닐 경우를 구분지어줬다. 

사실 이 작업은 결과가 온전한 단어여야해서 except로 빠진 경우는 대충 해줬다.

처음에는 except로 빠진 경우는 return ''로 했는데 그냥 최소한이라도 값을 받아오도록 했다.

 

아무튼 anfxltb는 이제 'ㅁㅜㄹㅌㅣㅅㅠ'가 되었다. 이것을 join_jamos로 자모결합을 하였다.

 

결과가 아주 잘 나온다! 

 

 

+) 자모결합 패키지는 hangul-utils를 사용하였다.

github.com/kaniblu/hangul-utils

 

kaniblu/hangul-utils

An integrated library for Korean language preprocessing. - kaniblu/hangul-utils

github.com

 

 

 

728x90

Comments