한글 형태소 분석기: Nori 확장 플러그인
- 엘라스틱서치에서 한글 형태소 분석기 중 가장 널리 사용되는 것은 “nori”이다.
- nori는 카카오에서 개발한 형태소 분석기로, 엘라스틱서치에서 공식적으로 지원된다.
- 아래와 같이 elasticsearch가 루트 디렉토리에 analysis-nori 를 설치해서 사용한다.
docker exec -it 엘라스틱서치컨테이너이름 ./bin/elasticsearch-plugin install analysis-nori
엘라스틱서치 컨테이너의 엘라스틱 플러그인을통해 nori를 설치한다.
위 사진과 같이 nori 설치가 완료되면 엘라스틱서치를 restart해주어야 한다
docker-compose restart
필자는 도커 컴포즈 파일로 ELK Stack을 구성해놓앗기 때문에 컴포즈파일만 다시 시작해주면 된다.
💥 도커 컴포즈 파일 작성하는법을 잘 익혀두자 💥
이 후 키바나를 들어가서 왼쪽 설정 맨 아래에
Dev Tools로 테스트를 한다.
❗️‘standard’ tokenizer VS ‘nori_tokenizer’ tokenizer
- GET _analyze를 이용해서 standard와 nori_tokenizer를 비교해볼 수 있다.
// 기본 분석기 => 결과: '하나몬의', '웹사이트에'
GET _analyze
{
"analyzer": "standard",
"text": "하나몬의 웹사이트에"
}
// 기본 토크나이저 => 결과: '하나몬의', '웹사이트에'
GET _analyze
{
"tokenizer": {
"type": "standard"
},
"text": "하나몬의 웹사이트에"
}
// 노리 분석기 => 결과: '하나', '몬', '웹', '사이트'
GET _analyze
{
"analyzer": "nori",
"text": "하나몬의 웹사이트에"
}
// 노리 토크나이저 => 결과: '하나', '몬', '의', '웹', '사이트', '에'
GET _analyze
{
"tokenizer": {
"type": "nori_tokenizer"
},
"text": "하나몬의 웹사이트에"
}
GET _analyze 옆에 재생버튼을 누르면 테스트가 실행된다.
❗️인덱스 생성 및 설정에서 토크나이저 analyzer 세팅하기
nori+tokenizer를 이용한 한글 형태소 분석하기
/*
* [인덱스 생성 및 설정]
*/
PUT nori_sample
{
"settings": {
"index": {
// elasticsearch에서 기본 제공하는 설정, 색인에 대한 분석 구성을 정의한다.
"analysis": {
// 색인에 대한 토크나이저를 구성한다.
"tokenizer": {
"my_nori_tokenizer": {
"type": "nori_tokenizer",
"decompound_mode": "mixed", // 'mixed' 복합 명사를 분해하는 기능을 수행
"discard_punctuation": "false" // 문장 부호 제거하지 않도록 설정한다. (기본적으로 제거한다.)
}
},
// analyzer는 분할된 토큰에 필터링과 정규화 처리 통헤 섹인에 추가할 단어의 집합을 만드는 데 사용된다.
"analyzer": {
// analyzer를 여러 개 만들어서 사용 가능하다.
"my_nori_analyzer": {
"type": "custom",
"tokenizer": "my_nori_tokenizer",
// lowercase: 알파벳 소문자로 통일 시킨다.
// stop: 문서에서 자주 사용되는 불용어를 제거한다.(검색 품질 향상: "the", "a", "an", "and" 와 같은 단어 검색에서 제외)
"filter": ["lowercase", "stop"],
// html_strip: HTML 태그 제거
"char_filter": ["html_strip"]
}
}
}
}
},
"mappings" : {
"properties" : {
"title": {
"type" : "text",
"analyzer": "my_nori_analyzer"
}
}
}
}
// 데이터 삽입
POST nori_sample/_doc
{
"title": "조직 핵심습관"
}
// 테스트
GET _analyze
{
"tokenizer": {
"type": "nori_tokenizer",
"decompound_mode": "mixed",
"discard_punctuation": "false"
},
"filter": ["lowercase", "stop"],
"text": ["조직 핵심습관"]
}
“조직”, ” “, “핵심”, “습관”으로 토큰이 분할된다. 그래서 검색할 때 “조직습관”이라고만 해도 색인된다.
그러나 “핵심습관”이라고 검색하면 standard 토크나이저를 사용했을 때와 다르게 검색이 되지 않는다.
물론 query.term 으로 검색했을 때 그렇다.
그래서 term 말고 match를 이용해서 검색하면 검색이 된다.
term은 정확한 일치 검색을 수행하고, match는 입력된 검색어 기반으로 가장 적합한 문서를 찾는다.
"token": "습관"
토큰화된 텍스트의 실제 값이다.
"start_offset": 5
해당 토큰의 시작 오프셋. 즉, 토큰이 원본 텍스트에서 시작하는 위치를 나타낸다. 이 경우에는 "습관"이 원본 텍스트에서 5번째 문자부터 시작한다는 것을 의미한다.
"end_offset": 7
해당 토큰의 종료 오프셋. 즉, 토큰이 원본 텍스트에서 끝나는 위치를 나타낸다. 이 경우에는 "습관"이 원본 텍스트에서 7번째 문자까지 포함한다는 것을 의미한다.
"type": "word"
토큰의 유형을 나타냅니다. "word"는 단어 토큰을 의미합니다. ElasticSearch에서는 기본적으로 텍스트를 단어 단위로 토큰화합니다. 다른 유형으로는 "whitespace" (공백에 따라 토큰화), "keyword" (전체 문자열을 하나의 토큰으로 간주), "ngram" 등이 있다.
"position": 3
토큰의 위치를 나타냅니다. 이 경우에는 "습관"이 해당 문서에서 3번째 위치에 있다는 것을 의미한다.
❗️analysis.tokenizer VS analysis.analyzer
- Elasticsearch 에서 인텍스를 생성할 때 analysis 설정을 이용해서 구성할 수 있다.
- analysis 구성에서 tokenizer와 analyzer 구성은 무슨 차이가 있을까?
- 둘 다 elasticsearch에서 기본 제공하는 설정으로 색인에 대한 분석 구성을 정의한다.
- tokenizer는 색인에 대한 토크나이저를 구성한다.
- analyzer는 분할된 토큰에 필터링과 정규화 처리 통헤 색인에 추가할 단어의 집합을 만드는 데 사용된다.
- my_standard_analyzer 라는 걸 만들어서 standard 토크나이저와 lowercase 필터를 조합해서 사용할 수 있다.
띄어쓰기 제거
✅ 커스텀 필터 만들어서 사용하기
- 띄어쓰기가 토큰으로 있으면 검색어와 연관성이 떨어지는 컨텐츠가 검색될 수 있다.
- 이럴 때는 필터를 이용해서 띄어쓰기는 토큰에서 제거할 수 있다.
- 추가로 trim 내장 필터를 이용해서 문자열의 좌우 여백을 토큰에서 제거할 수 있다.
// 아래와 같은 필터를 만들어서 analyzer 에서 사용할 수 있다.
"analysis": {
"tokenizer": {
"my_nori_tokenizer": {
"type": "nori_tokenizer",
"decompound_mode": "mixed",
"discard_punctuation": "false"
}
},
// 'stop' type의 커스텀 필터를 만들어 준다.
"filter": {
"stopwords": {
"type": "stop",
"stopwords": [" "]
}
},
"analyzer": {
"my_nori_analyzer": {
"type": "custom",
"tokenizer": "my_nori_tokenizer",
// 내장된 trim 필터를 이용하면 문자열의 좌우 여백은 토큰에서 제거한다.
"filter": ["lowercase", "stop", "trim", "stopwords"],
"char_filter": ["html_strip"]
}
}
}
품사 제거 [“은”, “는”, “이”, “가” ]
Nori 의 nori_part_of_speech 필터 사용하기
## 기존에 생성한 인덱스 삭제
DELETE nori_sample
## stoptags를 nori_part_of_speech 추가한 새로운 인덱스 생성
PUT nori_sample
{
"settings": {
"index": {
"analysis": {
"tokenizer": {
"my_nori_tokenizer": {
"type": "nori_tokenizer",
"decompound_mode": "mixed",
"discard_punctuation": "false"
}
},
"filter": {
"stopwords": {
"type": "stop",
"stopwords": [" "]
}
},
"analyzer": {
"my_nori_analyzer": {
"type": "custom",
"tokenizer": "my_nori_tokenizer",
// nori_part_of_speech 필터 추가
"filter": ["lowercase", "stop", "trim", "stopwords", "nori_part_of_speech"],
"char_filter": ["html_strip"]
}
}
}
}
},
"mappings" : {
"properties" : {
"title": {
"type" : "text",
"analyzer": "my_nori_analyzer",
"search_analyzer": "my_nori_analyzer"
}
}
}
}
- 위와 같은 조사 형용사가 같이 검색되면 검색 품질이 저하된다.
- 보통 한글 검색에서는 명사, 동명사 정도만 검색하는 것이 바람직하다.
- nori_part_of_speech 토큰 필터를 이용해서 제거할 품사 정보를 지정할 수 있다.
"stoptags": [
"E", "IC", "J", "MAG", "MAJ",
"MM", "SP", "SSC", "SSO", "SC",
"SE", "XPN", "XSA", "XSN", "XSV",
"UNA", "NA", "VSV"
]
위의 stoptags 들이 있는데 각 파라미터 값이 뜻하는건 아래 링크로 확인 가능하다
https://lucene.apache.org/core/8_4_0/analyzers-nori/org/apache/lucene/analysis/ko/POS.Tag.html
끗
'개-발 > Infra' 카테고리의 다른 글
[Kafka] Kafka 란 ? (0) | 2023.06.07 |
---|---|
[Kafka] Zookeeper 란? (1) | 2023.06.07 |
[Docker] 네트워크란 ? (0) | 2023.06.03 |
[Docker] 도커 이미지 그룹화 ( label , network ) (0) | 2023.05.29 |
[Elastic] Docker + Filebeat 설치 (0) | 2023.05.24 |