6.7.2 노리 (nori) 한글 형태소 분석기
이 문서의 허가되지 않은 무단 복제나 배포 및 출판을 금지합니다. 본 문서의 내용 및 도표 등을 인용하고자 하는 경우 출처를 명시하고 김종민([email protected])에게 사용 내용을 알려주시기 바랍니다.
한글은 형태의 변형이 매우 복잡한 언어입니다. 특히 복합어, 합성어 등이 많아 하나의 단어도 여러 어간으로 분리해야 하는 경우가 많아 한글을 형태소 분석을 하려면 반드시 한글 형태소 사전이 필요합니다. 오픈 소스 커뮤니티에서 개발되어 Elasticsearch에서 사용 가능한 한글 형태소 분석기는 다음과 같은 것들이 있습니다.
- 아리랑 (arirang)
- 설명: korean analyzer (lucene analyzer kr arirang)
- License: as-is
- 은전한닢 (seunjeon)
- 설명: mecab-ko-dic 기반으로 만들어진 JVM 상에서 돌아가는 한국어 형태소분석기입니다. 기본적으로 java와 scala 인터페이스를 제공합니다. 사전이 패키지 내에 포함되어 있기 때문에 별도로 mecab-ko-dic을 설치할 필요가 없습니다. 특징으로는 (시스템 사전에 등록되어 있는 단어에 한하여) 복합명사 분해와 활용어 원형 찾기가 가능합니다.
- License: Apache 2.0
- Open Korean Text
- 설명: 오픈소스 한국어 처리기 (Official Fork of twitter-korean-text). 스칼라로 쓰여진 한국어 처리기입니다. 현재 텍스트 정규화와 형태소 분석, 스테밍을 지원하고 있습니다. 짧은 트윗은 물론이고 긴 글도 처리할 수 있습니다.
- License: Apache 2.0
Elasticsearch가 한글을 지원하지 않던 시절에 위의 형태소 분석기들은 한글 사용자들에게 큰 도움이 되었습니다. 하지만 외부에서 만들어진 기능이다 보니 Elasticsearch 버전이 올라가 구조가 변경되면 사용이 불가능해지고, 버그가 오류가 있어도 누군가가 나서서 쉽게 고치기 어려운 문제가 있었습니다.
Elasticsearch 6.6 버전 부터 공식적으로 Nori(노리) 라고 하는 한글 형태소 분석기를 Elastic사에서 공식적으로 개발해서 지원을 하기 시작했습니다. 특이하게 nori는 프랑스 엔지니어인 Jim Ferenczi 에 의해 처음 개발이 되었습니다. Jim 은 아파치 루씬의 커미터이며 Elasticsearch의 일본어 형태소 분석기인 Kuromoji(구로모지) 역시 Jim 이 처음 개발했습니다. Nori 는 은전한닢에서 사용하는 mecab-ko-dic 사전을 재 가공 하여 사용하고 있습니다. Nori 는 루씬의 기능으로 개발되었으며 루씬 소스에 반영되어 있으며 개발 이력은
https://issues.apache.org/jira/browse/LUCENE-8231
에서 확인 할 수 있고 프로그램 소스는
https://github.com/apache/lucene-solr/tree/master/lucene/analysis/nori
에서 확인이 가능합니다.
Nori 에 관련한 설명은 공식 홈페이지의 문서 페이지의 Elasticsearch : Plugins and Integrations > Analysis Plugins > Nori 페이지에서 찾을 수 있습니다.
Nori 를 사용하기 위해서는 먼저 elasticsearch에 analysis-nori 플러그인을 설치해야 합니다. elasticsearch 홈 디렉토리에서 다음 명령을 실행하면 버전에 맞는 nori 플러그인을 받아서 자동으로 설치합니다.
nori 플러그인 설치
$ bin/elasticsearch-plugin install analysis-nori
설치된 nori 플러그인을 제거하려면 다음 명령을 실행합니다.
nori 플러그인 제거
$ bin/elasticsearch-plugin remove analysis-nori
Elastic 클라우드 서비스에서 사용하기 위해서는 클러스터를 배포할 때 Customize deployment 메뉴의 Manage plugins and settings 부분에서 analysis-nori 부분을 선택합니다.

Elastic Cloud 서비스에서 nori 설치
Nori는 nori_tokenizer 토크나이저와 nori_part_of_speech, nori_readingform 토큰 필터를 제공합니다. 먼저 nori_tokenizer 토크나이저를 사용해서 한글을 간단하게 테스트 할 수 있습니다. 다음은 standard와 nori_tokenizer 를 비교해서 "동해물과 백두산이" 를 분석한 예제입니다. 당연히 테스트 하는 elasticsearch 에는 analysis-nori 플러그인이 설치되어 있어야 합니다.
request
response
standard 토크나이저로 "동해물과 백두산이" 문장 분석
GET _analyze
{
"tokenizer": "standard",
"text": [
"동해물과 백두산이"
]
}
standard 토크나이저로 "동해물과 백두산이" 문장 분석 결과
{
"tokens" : [
{
"token" : "동해물과",
"start_offset" : 0,
"end_offset" : 4,
"type" : "<HANGUL>",
"position" : 0
},
{
"token" : "백두산이",
"start_offset" : 5,
"end_offset" : 9,
"type" : "<HANGUL>",
"position" : 1
}
]
}
request
response
nori_tokenizer 토크나이저로 "동해물과 백두산이" 문장 분석
GET _analyze
{
"tokenizer": "nori_tokenizer",
"text": [
"동해물과 백두산이"
]
}
nori_tokenizer 토크나이저로 "동해물과 백두산이" 문장 분석 결과
{
"tokens" : [
{
"token" : "동해",
"start_offset" : 0,
"end_offset" : 2,
"type" : "word",
"position" : 0
},
{
"token" : "물",
"start_offset" : 2,
"end_offset" : 3,
"type" : "word",
"position" : 1
},
{
"token" : "과",
"start_offset" : 3,
"end_offset" : 4,
"type" : "word",
"position" : 2
},
{
"token" : "백두",
"start_offset" : 5,
"end_offset" : 7,
"type" : "word",
"position" : 3
},
{
"token" : "산",
"start_offset" : 7,
"end_offset" : 8,
"type" : "word",
"position" : 4
},
{
"token" : "이",
"start_offset" : 8,
"end_offset" : 9,
"type" : "word",
"position" : 5
}
]
}
Standard 토크나이저는 공백 외에 아무런 분리를 하지 못했지만 nori_tokenizer는 한국어 사전 정보를 이용해
"token" : "동해"
, "token" : "산"
같은 단어을 분리 한 것을 확인할 수 있습니다. nori_tokenizer 에는 다음과 같은 옵션들이 있습니다.- user_dictionary : 사용자 사전이 저장된 파일의 경로를 입력합니다.
- user_dictionary_rules : 사용자 정의 사전을 배열로 입력합니다.
- decompound_mode : 합성어의 저장 방식을 결정합니다. 다음 3개의 값을 사용 가능합니다.
none
: 어근을 분리하지 않고 완성된 합성어만 저장합니다.discard
(디폴트) : 합성어를 분리하여 각 어근만 저장합니다.mixed
: 어근과 합성어를 모두 저장합니다.
user_dictionary는 다른 애널라이저들과 마찬가지로 config 디렉토리의 상대 경로를 입력하며 변경시 인덱스를 _close / _open 하면 반영됩니다. 사전의 단어들에는 우선순위가 있으며 문장 "동해물과" 에서는 "동해" 가 가장 우선순위가 높아 "동해" 가 먼저 추출되고 다시 "물" 그리고 "과" 가 추출되어 "동해"+"물"+"과" 같은 형태가 됩니다. user_dictionary 경로에 있는 사전 파일이나 user_dictionary_rules 설정값에 단어만 나열 해 주면 이 단어들을 가장 우선으로 추출합니다.
다음은 my_nori 인덱스에 user_dictionary_rules옵션을 이용하여 사용자 사전 "해물" 을 지정하고 "동해물과" 를 분석한 예제입니다.
my_nori 인덱스에 "해물" 사전을 추가한 my_nori_tokenizer 생성
PUT my_nori
{
"settings": {
"analysis": {
"tokenizer": {
"my_nori_tokenizer": {
"type": "nori_tokenizer",
"user_dictionary_rules": [
"해물"
]
}
}
}
}
}
request
response
my_nori_tokenizer 토크나이저로 "동해물과" 분석
GET my_nori/_analyze
{
"tokenizer": "my_nori_tokenizer",
"text": [
"동해물과"
]
}
my_nori_tokenizer 토크나이저로 "동해물과" 분석 결과
{
"tokens" : [
{
"token" : "동",
"start_offset" : 0,
"end_offset" : 1,
"type" : "word",
"position" : 0
},
{
"token" : "해물",
"start_offset" : 1,
"end_offset" : 3,
"type" : "word",
"position" : 1
},
{
"token" : "과",
"start_offset" : 3,
"end_offset" : 4,
"type" : "word",
"position" : 2
}
]
}
이렇게 사용자 사전에 "해물" 이라는 단어를 추가하면 "동해물과" 는 "동"+"해물"+"과"