suenjeon 라이브러리 빌드해보기
이 문서에서는 스칼라(자바)로 구현된 형태소 분석기 seunjeon 라이브러리의 빌드 및 사전 업데이트 방법 등을 소개합니다. 중앙 저장소에 공개된 1.5.0 버전에는 자체적으로 사전 데이터가 포함되어 있습니다. 여기서는 라이브러리를 빌드해서 사전 데이터를 외부로 빼내는 과정을 정리합니다.
1. 준비사항
다음과 같은 개발 환경을 준비합니다.
- Intellij - 소스코드가 scala 로 작성되었고 sbt(scala build tool)로 빌드 작업을 하기 때문에 Intellij(Community Eidition)에서 작업을 진행합니다.
- ㅇㅇ
1.1. IntelliJ Scala Plugin
IntelliJ를 다운로드하고 설치했다면 scala 개발 설정을 합니다.
메뉴에서 ItelliJ IDEA
> Preferences
클릭 후 왼쪽 메뉴에서 Plugins
선택합니다.
Scala
플러그인를 설치합니다.
1.2. Repository Url
seunjeon 저장소 링크
페이지 오른쪽에 [CLONE] 버튼을 눌러서 저장소 주소를 복사합니다.
저장소주소https://bitbucket.org/eunjeon/seunjeon.git
1.3. New Project
IntelliJ 설치 후 Clone Repository
를 클릭합니다.
Clone RepositoryVersion Control: [Git]
URL : _________________
Directory:
저장소 주소를 URL에 입력하고 [CLONE] 버튼을 클릭합니다.
다음과 같이 seunjeon 저장소를 내려받았습니다.
프로젝트구조.
├── CONTRIBUTORS.md
├── README.md
├── TODOS.md
├── build.sbt
├── elasticsearch
├── mecab-ko-dic -> mecab-ko-dic-2.0.1-20150920
├── project
│ ├── build.properties
│ └── plugins.sbt
├── scripts
└── src
2. sbt(build tool for scala)
scala로 작성된 빌드 도구로서 maven이나 gradle과 같은 역할을 합니다.
2.1. sbt 설정 및 소개
[프로젝트구조]에 보면 build.sbt
라는 파일이 gradle의 build.gradle
에 해당합니다.
빌드에 관여하는 파일은 아래의 3개입니다.
TXT├── build.sbt
...
├── project
│ ├── build.properties
│ └── plugins.sbt
...
- build.sbt - 빌드 절차를 기술함
- build.properties - sbt 버전(1.0.4)
- plugin.sbt - 사용할 플러그인 목록. 파일을 열어보면
"com.eed3si9n:sbt-assembly:0.14.6"
을 추가했다.
파일을 열어보면 sbt 설정이 없어서 오류가 나오는 상태입니다.
원래는 따로 sbt 를 설치하고 CLI에서 다음과 같이 실행해야 합니다.
sbtsbt clean package
- mvn clean package 와 동일함
하지만 IntelliJ에서는 IDE에서 필요한 도구와 환경 설정을 자동으로 제공합니다.
IntelliJ에서 오른쪽 아래쪽에 sbt shell
을 클릭합니다.

다음과 같은 prompt를 볼 수 있습니다.
TXT(initializing)>
- 설치 중 - 설치 및 초기화에 시간이 걸립니다.
다음과 같은 오류가 나옵니다.
TXT...
[info] Updating {file:/____/seunjeon/project/}seunjeon-build...
[info] Done updating.
/____/seunjeon/build.sbt:9: error: not found: value useGpg
useGpg := true,
^
[error] sbt.compiler.EvalException: Type error in expression
[error] sbt.compiler.EvalException: Type error in expression
[error] Use 'last' for the full log.
Project loading failed: (r)etry, (q)uit, (l)ast, or (i)gnore?
useGpg := true
- Maven 저장소에 배포할 때 PGP signing을 하는 듯
seunjeon 개발자가 maven 저장소에 jar 파일을 배포할 때 PGP signing 을 하려고 추가한 듯 합니다.
여기서는 산출물만(jar) 필요하기 때문에 다음의 두 가지 방법 중 하나를 시도합니다.
방법1 주석처리
useGpg:=true
를 주석처리합니다.
주석 처리 publishArtifact in Test := false,
// useGpg := true,
publishTo := {
방법2 pgp 플러그인 추가
plugins.sbt
파일을 열어서 다음과 같이 sbt-pgp
플러그인을 추가합니다.
TXTaddSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.14.6")
addSbtPlugin("com.jsuereth" % "sbt-pgp" % "1.1.0")
com.jsuereth:sbt-pgp:1.1.0
을 추가했음.useGpg
를 false로 바꿉니다.
두가지 방법 중 하나를 선택해서 설정을 수정한 후에 sbt shell
로 돌아가서 중지시킨 후 다시 shell 을 시작합니다.
sbt shell[info] Loading settings from idea.sbt ...
[info] Loading global plugins from /Users/____/.sbt/1.0/plugins
[info] Loading settings from plugins.sbt ...
[info] Loading project definition from /Users/____/workspace/ws-scala/seunjeon/project
[info] Loading settings from build.sbt ...
[info] Loading settings from build.sbt ...
[info] Set current project to seunjeon (in build file:/Users/____/workspace/ws-scala/seunjeon/)
[IJ]sbt:seunjeon>
sbt shell에서 clean
과 package
명령을 각각 실행합니다.
(sbt shell) clean 명령어> clean
[success] Total time: 1 s, completed Nov 15, 2024 2:44:50 PM
[IJ]sbt:seunjeon>
(sbt shell) package 명령어> package
[info] Updating {...}seunjeon...
[info] Done updating.
[info] Compiling 21 Scala sources and 1 Java source to /____/seunjeon/target/scala-2.12/classes ...
[info] Done compiling.
[info] Packaging /____/seunjeon/target/scala-2.12/seunjeon_2.12-1.5.0.jar ...
[info] Done packaging.
[success] Total time: 19 s, completed Nov 15, 2024 2:46:06 PM
[IJ]sbt:seunjeon>
다음과 같이 target 디렉토리에 class 파일들과 jar 파일을 빌드했습니다.
산출물target
├── scala-2.12
│ ├── classes
│ │ └── ...class files
│ ├── resolution-cache
│ └── seunjeon_2.12-1.5.0.jar
하지만 seunjeon_2.12-1.5.0.jar
파일을 살펴보면 파일 용량이 160KB로 매우 작습니다.
Maven 저장소에 등록된 jar 파일은 약 24MB 정도인데 dictionary를 포함하고 있기 때문입니다.
TXTjava/main/resources/dictionalry
+- termDict.dat
+- dictMapper.dat
+- trie.dat
...
2.2. 사전 빌드
DictBuilder.scala
파일에는 사전을 빌드하는 기능이 이미 추가되어 있습니다.
DictBuilder.scala def main(args: Array[String]): Unit = {
clear()
copyUnkDef()
copyLeftIdDef()
copyRightIdDef()
println("compiling lexicon dictionary...")
buildLexiconDict()
println("compiling connection-cost dictionary...")
buildConnectionCostDict()
println("complete")
}
src/main/resources/dictionary
안에 사전을 생성합니다.
IntelliJ 를 사용하면 main 메소드를 실행할 수 있는 UI 화면을 제공합니다.

버튼을 눌러서 실행하면 다음과 같이 실패합니다.
TXTException in thread "main" java.nio.file.NoSuchFileException: /____/seunjeon/mecab-ko-dic/unk.def
at sun.nio.fs.UnixException.translateToIOException(UnixException.java:86)
at sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:102)
at sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:107)
at sun.nio.fs.UnixCopyFile.copy(UnixCopyFile.java:526)
at sun.nio.fs.UnixFileSystemProvider.copy(UnixFileSystemProvider.java:253)
at java.nio.file.Files.copy(Files.java:1274)
at org.bitbucket.eunjeon.seunjeon.DictBuilder$.copyDefFile(DictBuilder.scala:82)
at org.bitbucket.eunjeon.seunjeon.DictBuilder$.copyUnkDef(DictBuilder.scala:68)
at org.bitbucket.eunjeon.seunjeon.DictBuilder$.main(DictBuilder.scala:54)
at org.bitbucket.eunjeon.seunjeon.DictBuilder.main(DictBuilder.scala)
Process finished with exit code 1
DictBuilder.main
은 mecab-ko-dic
디렉토리 안에서 사전을 빌드하는데 필요한 .csv
, .def
파일을 읽습니다.
TXT```txt:프로젝트구조
.
├── mecab-ko-dic -> mecab-ko-dic-2.0.1-20150920
mecab-ko-dic
은 symbolic link인데 참조하는 실제 디렉토리가 없습니다.
사전에 신조어를 등록하고 새로 빌드하려면 https://bitbucket.org/eunjeon/mecab-ko-dic
저장소에서 사전 정보를 다운로드해야 합니다.
- mecab-ko-dic - 사전을 제공함 (2018년도가 최신 버전)
이 기능은 이미 scripts/download-dict.sh
에서 제공합니다.
download-dict.sh...
wget -O ${DICT_NAME}.tar.gz "https://bitbucket.org/eunjeon/mecab-ko-dic/downloads/${DICT_NAME}.tar.gz"
tar zxvf $DICT_NAME.tar.gz
rm mecab-ko-dic
ln -sf $DICT_NAME mecab-ko-dic
아래와 같이 실행하면 되는데 다운로드할 사전의 버전을 입력해야 합니다.
사전 다운로드$ ./scripts/download-dict.sh 사전버전
mecab-ko-dict/downlaod 페이지에서 가장 최근의 사전 이름을 복사합니다.
TXTmecab-ko-dic-2.1.1-20180720.tar.gz
mecab-ko-dic-2.1.0-20180716.tar.gz
...
.tar.gz
은 빼고 파일명만 다음과 같이 입력합니다.
사전 다운로드$ ./scripts/download-dict.sh mecab-ko-dic-2.1.1-20180720
실행 결과
로그$ ./scripts/download-dict.sh mecab-ko-dic-2.1.1-20180720
Resolving bitbucket.org (bitbucket.org)
HTTP request sent, awaiting response... 302 Found
...
HTTP request sent, awaiting response... 200 OK
Length: 49775061 (47M) [application/x-tar]
Saving to: ‘mecab-ko-dic-2.1.1-20180720.tar.gz’
2024-11-15 15:30:47 (7.72 MB/s) - ‘mecab-ko-dic-2.1.1-20180720.tar.gz’ saved [49775061/49775061]
파일을 다운로드하고 압축을 해제한 후 symbolic link도 수정되었습니다.
사전 구조├── mecab-ko-dic -> mecab-ko-dic-2.1.1-20180720
├── mecab-ko-dic-2.1.1-20180720
├── mecab-ko-dic-2.1.1-20180720.tar.gz
mecab-ko-dic
는 2018년도 사전 디렉토리를 링크함.
다시 DictBuilder.main
을 실행하면 src/main/resources/dictionary
아래에 사전 파일들이 생성됩니다.
DictBuilder.main 로그compiling lexicon dictionary...
INFO: csv parsing is completed. (191 ms)
INFO: terms & mapper building is completed. (800 ms)
INFO: added to trie builder (523 ms)
INFO: double-array trie building is completed. (21282 ms)
building LexiconDict OK. (termSize = 816243 mapper size = 774556)
compiling connection-cost dictionary...
INFO: connectionDict loading is completed. (25395 ms)
building connection cost dictionary OK. (rightSize : 3822, leftSize : 2693, size : 10292648)
complete
사전 데이터src/main/resources/
├── char.def
└── dictionary
├── connection_cost.dat
├── dictMapper.dat
├── left-id.def
├── right-id.def
├── termDict.dat
├── trie.dat
└── unk.def