루아와 MeCab-ko를 이용한 한국어 형태소 분석

Twitter icon류광, 2019-08-10 19:08
Windows에서 루아로 한국어 형태소 분석을 수행하기 위한 MeCab-ko 루아 바인딩 모듈 만들기와 기타 설정 방법.

Windows에서 루아로 한국어 형태소 분석을 해보자는 생각으로 가장 덜 번거로운 길을 찾아보았습니다.

제가 찾은 답은 다음과 같습니다.

lua-mecab 모듈을 빌드하되, 원래의 MeCab 대신 MeCab-ko의 라이브러리 파일을 링크한다.

lua-mecab 모듈은 C++로 구현된 MeCab의 주요 객체와 함수에 대한 루아 바인딩으로, 이를테면 다음과 같이 사용합니다.[1]

mecab = require "mecab" -- if you build it yourself, use the .so name (lua-mecab) here
parser = mecab:new("") -- you can pass mecab config options here, like "-Owakati"

print(parser:parse("吾輩は猫である"))

lua-mecab은 cpp 파일 하나로 된 상당히 간단한 모듈이며, 루아의 헤더들과 라이브러리 파일, MeCab의 헤더들과 라이브러리 파일에만 의존합니다.

예제에 일본어 예문이 쓰인 것은 MeCab이 원래 일본어 텍스트를 위해 만들어진 것이기 때문인데요. 한국의 훌륭한 개발자분들이 MeCab을 한국어에 맞게 고쳐서 공개했습니다. MeCab-ko가 바로 그것인데, 문서화에 따르면[2]

"최소한의 변경으로 한국어의 특성에 맞는 기능을 추가하는 것이 목표"

라고 합니다.

MeCab과 MeCab-ko 둘 다 소스 코드가 *nix 환경을 기준으로 합니다. 다행히 또 다른 훌륭한 개발자분이 MeCab-ko를 MS의 개발 도구로 빌드하기 편하게 만들어 주셨습니다. mecab-ko-msvc 프로젝트가 바로 그것입니다. 게다가 아예 미리 빌드한 이진 파일들도 제공합니다.

MeCab-ko는 MeCab의 기존 API를 최대한 따르기 때문에, lua-mecab을 빌드할 때 MeCab의 라이브러리 대신 MeCab-ko의 라이브러리를 링크해도 오류가 생기지 않습니다.따라서, Visual Studio에서 lua-mecab의 .cpp 파일 하나를 컴파일하고 루아 구현의 라이브러리 파일과 언급한 MeCab-ko 라이브러리 파일(libmecab.lib)을 링크하기만 하면 루아에서 MeCab-ko의 함수를 호출할 수 있는 확장 모듈 DLL 파일이 생깁니다. 이 글에 관심을 가지는 분이라면 아마 VS에서 의존성 두 개 짜리 DLL 프로젝트를 설정하고 빌드하는 데 별 어려움이 없을 것이므로 자세한 방법은 생략하겠습니다. 아주 간단하게는, 관련 파일들을 모두 한 디렉터리에 넣고 모듈 .cpp 소스 코드 자체에서 #pragma comment lib(...)으로 필요한 라이브러리들을 지정하면 될 것입니다. 그러면 프로젝트 속성에서 각종 경로와 추가 lib 파일을 설정할 필요도 없습니다.

여기까지가 기본적인 전략이고, 몇 가지 실천 세부 사항을 살펴보자면: 우선 lua-mecab 소스 코드에는 Windows DLL을 위한 배려가 빠져 있습니다. lua-mecab.cpp 파일 끝부분을 보면 다음과 같은 코드가 있는데,[3]

extern "C" int luaopen_mecab(lua_State *L)
{
... 중략 ...

}

Windows에서 루아가 모듈을 적재하는 과정에서 이 DLL 함수에 접근할 수 있으려면 다음처럼 이것이 외부로 공개된 DLL 함수임을 명시적으로 표시해 주어야 합니다(적어도 Microsoft VS에서는).

extern "C" __declspec(dllexport) int luaopen_mecab(lua_State *L)
{
... 중략 ...

}

그리고 이런 식으로 얻은 lua-mecab DLL을 바로 루아에서 사용할 수는 없습니다. 몇 가지 준비 작업이 필요한데요.

먼저, lua-mecab에 링크한 MeCab-ko 라이브러리 파일은 실제 코드를 담고 있는 것이 아니라 MeCab-ko 자체의 DLL 파일인 libmecab.dll에 대한 링크 정보만 담고 있습니다. 따라서 그 libmecab.dll(MeCab-ko-msvs의 이진 파일 모음에 포함되어 있습니다)을 호스트 실행 파일(루아를 독립적으로 사용한다면 lua5.x.exe)이 있는 디렉터리 또는 시스템 환경 변수 PATH에 등록된 디렉터리에 복사해야 합니다.

또한 lua-mecab 모듈 DLL 파일 자체도 호스트가 접근할 수 있는 곳에 배치해야 하고요. LuaBinaries 기준으로는 루아 exe 파일(lua5.1.exe 등)이 있는 디렉터리 또는 그 디렉터리의 clib 디렉터리에 넣으면 됩니다.

그리고 MeCab-ko는 형태소 분석을 위해 설정 파일과 외부 사전 파일을 참조합니다. 사전 파일들은 MeCab-ko-dic라는 개별 프로젝트에서 관리하는데, MeCab-ko-msvc 프로젝트를 만든 윤원섭 님이 MeCab-ko-dic의 MSVC 버전과 이진 파일들도 제공합니다. 해당 GitHub 저장소는 https://github.com/Pusnow/mecab-ko-dic-msvc입니다.

MeCab-ko-msvc의 미리 빌드된 실행 파일과 DLL은 설정 파일이 c:\mecab\mecabrc라고 가정합니다. 그리고 사전 파일들을 찾을 폴더는 mecabrc 설정 파일 안에 지정되어 있는데, 기본은 c:\mecab\mecab-ko-dic\입니다. 설정 파일과 사전 파일들을 딱 이대로 배치했다면, 루아에서

mecab = require "mecab"
parser = mecab:new("")

print(parser:parse("아버지가방에들어가신다"))

를 실행해서

아버지 NNG,*,F,아버지,*,*,*,*
가   JKS,*,F,가,*,*,*,*
방   NNG,장소,T,방,*,*,*,*
에   JKB,*,F,에,*,*,*,*
들어가 VV,*,F,들어가,*,*,*,*
신다  EP+EC,*,F,신다,Inflect,EP,EC,시/EP/*+ㄴ다/EC/*
EOS

라는 결과를 얻을 수 있습니다. 띄어쓰기를 하지 않았는데도 '가방'을 하나의 명사로 인식하지 않고 '가'를 조사로, '방'을 명사로 인식했네요. 똑똑합니다.

만일 설정 파일과 사전 파일들을 다른 곳에 두었다면, mecab:new()를 호출할 때 다음처럼 MeCab 설정 파일의 위치를 명시적으로 지정해야 합니다.

parser = mecab:new([[-r C:\설정파일이\있는\경로\설정파일이름]])

또한 MeCab 설정 파일에는 dicdir = C:\사전파일들이\있는\디렉터리 형태로 사전 파일 디렉터리의 절대 경로를 지정해야 하고요.


모듈 빌드 과정과 사용 준비 과정을 번호를 착착 붙여서 단계별로 깔끔하게 정리하면 좋겠지만, 시간이 부족해서 일단 필요한 내용만 주절주절 써 보았습니다. 각 단계의 의도와 함정을 염두에 두고 관련 파일들을 실제로 살펴보면 전체적인 과정이 별거 아니라는 점을 아실 겁니다:) 번역서 독자 지원 경험에 비추어 볼 때 단계들을 너무 명시적으로 제시하면 오히려 읽는 이가 수동적으로 되어서 사소한 문제도 스스로 해결하지 못하는 경우가 있다는 변명으로 글을 마무리합니다.

태그: 프로그래밍 Lua NLP

comments powered by Disqus