brunch

You can make anything
by writing

C.S.Lewis

by 이영민 Jul 15. 2016

KoNLP를 이용한 한국어 형태소 분석

R의 한글 자연어 분석 패키지인 KoNLP(Korean Natural Language Processing)패키지에는 한국어를 분석할 수 있는 총 27개의 함수가 들어 있다. 오늘은 그중에서도 형태소 분석과 관련된 함수들에 대해 다뤄보려 한다.


KoNLP 패키지에 포함된 함수들


먼저, KoNLP 패키지를 설치하고 불러와 보자.

> install.packages('KoNLP')
> library(KoNLP)


library 함수로 KoNLP 패키지를 불러올 때 에러가 발생하기도 하는데, 대부분 rJAVA가 깔려 있지 않아서 그런 것으로, rJAVA를 설치하면 된다. 설치했는데도 에러가 나는 경우에는 아래와 같이 자바의 경로를 설정해 주면 해결된다.

> Sys.setenv(JAVA_HOME='C:/Program Files/Java/jre1.8.0_91')


형태소 분석을 하기 위해서는 reference로 삼을 사전이 필요하다. 내가 분석할 문장에 포함된 단어들이 사전에 알맞은 형태(품사)로 포함되어 있어야만 정확한 분석이 가능하기 때문이다. 그러므로 KoNLP 패키지에도 당연히 그런 사전이 존재한다. 시스템(system) 사전과 세종(sejong) 사전이 있는데, 여기서는 세종 사전을 사용해 보자.  

> useSejongDic()
Backup was just finished!
87007 words were added to dic_user.txt.


사전을 불러왔으니, 이제 '아버지가 방에 스르륵 들어가신다.'라는 문장을 가지고 형태소 분석을 해 보자.

> sentence <- '아버지가 방에 스르륵 들어가신다.'



extractNoun: 명사를 추출하는 함수


먼저, 'extractNoun' 함수를 이용해서 문장에서 명사만을 추출해 보기로 한다.

> extractNoun(sentence)
[1] "아버지" "방" "스르륵"

sentence 중에서 '아버지', '방', '스르륵'이 명사로 추출되었다. 스파이가 숨어 있다. '스르륵'은 명사가 아니라 부사다.  아마도 세종 사전에 '스르륵'이라는 단어가 포함되어 있지 않아서 명사로 추출된 것 같다. 이럴 땐 어떻게 해야 할까?



mergeUserDic: 사전에 단어를 추가하는 함수


'mergeUserDic' 함수를 이용하여 sejong 사전에 '스르륵'이라는 단어를 '부사'로 추가하면 된다. 이때의 주의 사항은, sejong 사전이 데이터 프레임의 형태이기 때문에 새로운 단어를 추가할 때도 데이터 프레임으로 넣어주어야 한다는 것이다. 그리고 앞부분에는 내가 사전에 추가하고자 하는 단어인 '스르륵'을 넣어 주고, 뒤에는 해당 단어의 품사를 선언해 주어야 하는데, 이때 품사의 종류는 KAIST 품사 태그셋을 이용하면 된다. '스르륵'은 부사 중에서도 '일반부사'이므로 KAIST 품사 태그셋에 지정된 'mag' 태그를 달아 주었다.

> mergeUserDic(data.frame(c('스르륵'), c('mag')))
1 words were added to dic_user.txt.


다시 'extractNoun'을 해 보자.

> extractNoun(sentence)
[1] "아버지" "방"  

'스르륵'은 더 이상 명사로 추출되지 않는 것을 확인할 수 있다.



MorphAnalyzer: 형태소를 분석해 주는 함수


이제 'MorphAnalyzer'를 이용하여 sentence 전체에 대한 형태소를 분석해 보자.

> MorphAnalyzer(sentence)
$`아버지가`
[1] "아버지/ncn+가/jcc" "아버지/ncn+가/jcs"

$방에
[1] "방/ncn+에/jca"


$스르륵
[1] "스르륵/mag"

$들어가신다
[1] "들/pvg+어/ecx+가/px+시/ep+ㄴ다/ef" "듣/pvg+어/ecx+가/px+시/ep+ㄴ다/ef" "들어가/pvg+시/ep+ㄴ다/ef"   

 $.
[1] "./sf" "./sy"

위 결과를 보면, 띄어쓰기 단위, 즉 어절 단위로 분석이 되는 것을 알 수 있다. 그리고 각 어절에 대해서는 (프로그램이 판단했을 때) 모든 가능한 상황에 대한 분석이 행해지고 있다. 예를 들어, '아버지가'의 경우, '아버지'는 '비서술성 명사'인 'ncn'만으로 분석이 된 반면, '가'는 '보격조사'인 'jcc'와 '주격조사'인 'jsc' 두 가지가 모두 가능하다고 분석되었다. 하지만 여기서의 '가'는 '주격조사'가 맞다. '되다'나 '아니다' 앞에 오는 조사를 제외하고는 모두 '주격조사'로 보면 된다. 코드도 그렇게 짜면 될 것 같은데 왜 이런 식으로 나오게 했는지 모르겠다. 


'들어가신다' 결과를 보면 '어가신다', '어가신다', '들어가신다' 이렇게 3가지 경우로 분석한 것을 알 수 있다. 마침표(.) 마저도 '마침표'인 'sf'와 '기타기호'인 'sy'의 2가지 경우로 분석되었다. 아무래도 'MorphAnalyzer'라는 함수가 각 단어에 대한 품사를 확정 짓는다기 보다는 형태소를 분석한 결과를 산출해 주기 때문인 것 같다. 

 


SimplePos09: 09개의 품사 태그를 달아 주는 함수

SimplePos22: 22개의 품사 태그를 달아 주는 함수


이번에는 품사를 확정시킬 뿐 아니라 각 단어들에 태그를 붙여 주는 함수인 'SimplePos09' 함수와 'SimplePos22' 함수에 대해 알아보자. 두 함수는 무슨 차이일까? 이에 대한 답을 찾기 위해 앞에서 언급한 KAIST 품사 태그셋을 한번 열어 보자.

 

KAIST 품사 태그셋

   

보다시피 두 개 함수의 차이는 분류 수준의 차이에서 온다. 'SimplePos09' 함수는 품사의 가장 상위 분류인 9개의 기준으로만 분류를 수행하고, 'SimplePos22' 함수는 그다음 분류인 22개의 기준으로 분류를 수행하게 되는 것이다. 그리고 가장 상세한 수준의 분류는 앞에서 보았듯이 'MorphAnalyzer' 함수가 사용하는 부분이다. 코드를 돌려 보면서 함수들 간의 차이를 느껴보자. 

> SimplePos09(sentence)
$`아버지가`
[1] "아버지/N+가/J"

$방에
[1] "방/N+에/J"

$스르륵
[1] "스르륵/M"

$들어가신다
[1] "들/P+어/E+가/P+시ㄴ다/E"

$.
[1] "./S"

'MorphAnalyzer'의 결과보다 훨씬 간단하다. 앞에서 논란이 되었던 '아버지가'의 '가'도 '관계언'인 'J'로 퉁쳐 버릴 수 있으니 간편하긴 하다. 그러나 이 정도 수준으로는 제대로 된 형태소 분석을 하기에는 무리가 있어 보인다.


이번에는 'SimplePos22'의 결과다.

> SimplePos22(sentence)
$`아버지가`
[1] "아버지/NC+가/JC"

$방에
[1] "방/NC+에/JC"

$스르륵
[1] "스르륵/MA"

$들어가신다
[1] "들/PV+어/EC+가/PX+시/EP+ㄴ다/EF"

$.
[1] "./SF"

'MorphAnalyzer'보다 간단하면서 'SimplePos09'보다는 한 차원 높은 수준이라는 것을 알 수 있다. '아버지'가 단순 '체언(N)'이 아니라 '보통명사(NC)'라는 것까지 파악이 되고, '스르륵'이 '수식언(M)' 중에서도 '부사(MA)'라는 것을 알 수 있으니, 이 정도면 적절한 것 같다는 생각이 든다. 이에 본인도 공간 감성어 사전 구축을 위한 형태소 분석 시에 'SimplePos22' 함수를 이용하여 품사 태그를 달아 주었다. 그 결과에 대해서는 다음 기회에 이야기 하겠다. 


KoNLP에 포함된 함수들을 하나씩 뜯어서 보면 하나하나가 유용하고 또 재미있다. 한글을 기반으로 텍스트 마이닝 등의 분석을 하고 싶다면 꼭 사용해 보시길.



(제목 배경 이미지 출처)

브런치는 최신 브라우저에 최적화 되어있습니다. IE chrome safari