본문 바로가기

공부방/Elasticsearch

노리 (nori) 한글 형태소 분석기

커뮤니티 한글 형태소 분석기 - 아리랑, 은전한닢, Open Korean Text
한글은 형태의 변형이 매우 복잡한 언어입니다.
특히 복합어, 합성어 등이 많아 하나의 단어도 여러 어간으로 분리해야 하는 경우가 많아 한글을 형태소 분석을 하려면 반드시 한글 형태소 사전이 필요합니다. 오픈 소스 커뮤니티에서 개발되어 Elasticsearch에서 사용 가능한 한글 형태소 분석기는 다음과 같은 것들이 있습니다.
 
Elasticsearch가 한글을 지원하지 않던 시절에 위의 형태소 분석기들은 한글 사용자들에게 큰 도움이 되었습니다. 하지만 외부에서 만들어진 기능이다 보니 Elasticsearch 버전이 올라가 구조가 변경되면 사용이 불가능해지고, 버그가 오류가 있어도 누군가가 나서서 쉽게 고치기 어려운 문제가 있었습니다.
 

Nori 개요


 
Elasticsearch 공식 플러그인

공식 플러그인이지만 바로 사용하면 nori 라는 analyzer가 존재하지 않는다는 에러가 발생합니다.

 

GET _analyze
{
	"analyzer": "nori",
    "text": ["동해물과 백두산이"]
}
 

반면에 standard analyzer를 사용하면 적용이 되지만 띄어쓰기 기준으로만 분리가 되는 것을 확인할 수 있습니다.

 

GET _analyzer
{
	"analyzer" : "standard"
    "text" : ["동해물과 백두산이"]
}

 

Elasticsearch 6.6 버전 부터 공식적으로 Nori(노리) 라고 하는 한글 형태소 분석기를 Elastic사에서 공식적으로 개발해서 지원을 하기 시작했습니다.
 
 
개발 이력은
 
프로그램 소스는

 

Nori 설치


Nori 를 사용하기 위해서는 먼저 elasticsearch에 analysis-nori 플러그인을 설치해야 합니다. elasticsearch 홈 디렉토리에서 다음 명령을 실행하면 버전에 맞는 nori 플러그인을 받아서 자동으로 설치합니다.

 

1. nori 플러그인 설치

 
bin/elasticsearch-plugin install analysis-nori

 

2. 설치된 nori 플러그인을 제거

 

nori 플러그인 제거
$ bin/elasticsearch-plugin remove analysis-nori

 

3. nori 토크나이저를 이용해서 분석

 
GET _analyze
{
  "tokenizer": "nori_tokenizer",
  "text": [
    "동해물과 백두산이"
  ]
}

 

Standard 토크나이저는 공백 외에 아무런 분리를 하지 못했지만 nori_tokenizer는 한국어 사전 정보를 이용해 "token" : "동해", "token" : "산" 같은 단어을 분리 한 것을 확인할 수 있습니다. nori_tokenizer 에는 다음과 같은 옵션들이 있습니다.

 

  • user_dictionary : 사용자 사전이 저장된 파일의 경로를 입력합니다.
  • user_dictionary_rules : 사용자 정의 사전을 배열로 입력합니다.
  • decompound_mode : 합성어의 저장 방식을 결정합니다. 다음 3개의 값을 사용 가능합니다.
    • none : 어근을 분리하지 않고 완성된 합성어만 저장합니다.
      • 동해물 -> 동해물
    • discard (디폴트) : 합성어를 분리하여 각 어근만 저장합니다.
      • 동해물 ->  동해 + 물
    • mixed : 어근과 합성어를 모두 저장합니다.
      • 동해물 -> 동해 + 물 + 동해물

 

user_dictionary_rules 예제

 

PUT my_nori
{
  "settings": {
    "analysis": {
      "tokenizer": {
        "my_nori_tokenizer": {
          "type": "nori_tokenizer",
          "user_dictionary_rules": [
            "해물"
          ]
        }
      }
    }
  }
}

 

이렇게 사용자 사전에 "해물" 이라는 단어를 추가하면 "동해물과" 는 "동"+"해물"+"과" 로 분석이 되어 이 문장이 포함된 도큐먼트는 "동해" 로는 검색이 되지 않고 "해물"로 검색이 됩니다.

 

유투버, 크리에이터를 다룰때 "대도서관" -> 사용자 사전에 저장해서 사용할 수도 있다.

elasticsearch로 한글 검색을 구현한다면 어떤 사전을 만들어야 할 지 꼭 고민을 해봐야 한다.

 

 

GET my_nori/_analyze
{
  "tokenizer": "my_nori_tokenizer",
  "text": [
    "동해물과"
  ]
}

 

노리 옵션을 조금 더 살펴보겠습니다.

세팅을 바꿔도 바뀌지 않는 것들이 있기 때문에, 세팅을 바꿀때 마다 인덱스를 삭제해야합니다.

 

 

 

 

DELETE my_nori

 

none, discard, mixed에 대한 옵션을 조금 더 살펴보겠습니다.

각각의 설정을 추가해줍니다.

 

PUT my_nori
{
  "settings": {
    "analysis": {
      "tokenizer": {
        "nori_none": {
          "type": "nori_tokenizer",
          "decompound_mode": "none"
        },
        "nori_discard": {
          "type": "nori_tokenizer",
          "decompound_mode": "discard"
        },
        "nori_mixed": {
          "type": "nori_tokenizer",
          "decompound_mode": "mixed"
        }
      }
    }
  }
}

none

GET my_nori/_analyze
{
  "tokenizer": "nori_none",
  "text": [ "백두산이" ]
}


"백두산" + "이"
백두산 검색 가능
백두 검색 불가능

 

 

discard : dfault

 

GET my_nori/_analyze
{
  "tokenizer": "nori_discard",
  "text": [ "백두산이" ]
}

"백두" + "산" + "이"
백두 검색가능
산 검색 가능
백두산은 경우에 따라서 검색 될수도 안될 수도 있다.

 

mixed

 

GET my_nori/_analyze
{
  "tokenizer": "nori_mixed",
  "text": [ "백두산이" ]
}


백두산이
백두산 + 백두 + 산 + 이