OpenSearch Analyzer 이해하기

2024년 12월 05일

opensearch

# OpenSearch# Analyzer# Nori# 검색엔진

들어가며

검색 엔진에서 “삼성전자”를 검색했는데 결과가 안 나온다면? 대부분 Analyzer 설정 문제입니다. Analyzer가 텍스트를 어떻게 쪼개는지 이해하면 검색 품질을 크게 개선할 수 있습니다.


Analyzer란?

Analyzer는 텍스트를 검색 가능한 토큰으로 변환하는 파이프라인입니다.

문자 정제

토큰 분리

토큰 가공

삼성전자 주가 상승

Character Filter

Tokenizer

Token Filter

[삼성, 전자, 주가, 상승]

3가지 구성 요소

입력 텍스트

Character Filter

(0개 이상)

Tokenizer

(1개 필수)

Token Filter

(0개 이상)

토큰 목록

구성 요소 역할 예시
Character Filter 문자 단위 전처리 HTML 태그 제거, 특수문자 치환
Tokenizer 텍스트를 토큰으로 분리 공백 기준, 형태소 분석
Token Filter 토큰 후처리 소문자 변환, 불용어 제거, 동의어 처리

_analyze API로 토큰화 확인하기

가장 중요한 디버깅 도구입니다. 실제로 텍스트가 어떻게 분석되는지 확인할 수 있습니다.

Standard Analyzer (기본)

GET _analyze
{
  "analyzer": "standard",
  "text": "삼성전자 주가 10% 상승"
}

결과:

{
  "tokens": [
    { "token": "삼성전자", "position": 0 },
    { "token": "주가", "position": 1 },
    { "token": "10", "position": 2 },
    { "token": "상승", "position": 3 }
  ]
}

Standard Analyzer는 공백과 특수문자 기준으로만 분리합니다. “삼성전자”가 하나의 토큰으로 남아있죠.

Nori Analyzer (한글 형태소 분석)

GET _analyze
{
  "analyzer": "nori",
  "text": "삼성전자 주가 10% 상승"
}

결과:

{
  "tokens": [
    { "token": "삼성", "position": 0 },
    { "token": "전자", "position": 1 },
    { "token": "주가", "position": 2 },
    { "token": "10", "position": 3 },
    { "token": "상승", "position": 4 }
  ]
}

Nori는 “삼성전자”를 “삼성” + “전자”로 분리합니다. 형태소 분석의 결과죠.


Standard vs Nori 비교

주식 종목명으로 비교해봅시다.

입력 Standard Nori
삼성전자 [삼성전자] [삼성, 전자]
SK하이닉스 [sk하이닉스] [sk, 하이닉스] 또는 [sk, 하이, 닉스]
LG에너지솔루션 [lg에너지솔루션] [lg, 에너지, 솔루션]
카카오뱅크 [카카오뱅크] [카카오, 뱅크]

검색 시나리오

사용자가 “삼성”으로 검색했을 때:

Nori Analyzer

일치!

인덱싱: 삼성전자

[삼성, 전자]

검색: 삼성

[삼성]

Standard Analyzer

불일치

인덱싱: 삼성전자

[삼성전자]

검색: 삼성

[삼성]

❌ 매칭 안 됨

✅ 매칭됨


Nori Tokenizer 옵션

AWS OpenSearch에서는 Nori가 기본 내장되어 있습니다.

decompound_mode

복합어를 어떻게 처리할지 결정합니다.

PUT /stocks
{
  "settings": {
    "analysis": {
      "tokenizer": {
        "nori_tokenizer_mixed": {
          "type": "nori_tokenizer",
          "decompound_mode": "mixed"
        }
      },
      "analyzer": {
        "nori_mixed": {
          "type": "custom",
          "tokenizer": "nori_tokenizer_mixed"
        }
      }
    }
  }
}

mixed

[삼성전자, 삼성, 전자]

discard

[삼성, 전자]

none

[삼성전자]

삼성전자

모드 설명 “삼성전자” 결과
none 분해 안 함 [삼성전자]
discard 원본 버리고 분해 [삼성, 전자]
mixed 원본 + 분해 모두 [삼성전자, 삼성, 전자]

mixed 모드를 쓰면 “삼성전자”로 검색해도, “삼성”으로 검색해도 모두 매칭됩니다.

분석 결과 확인

GET /stocks/_analyze
{
  "analyzer": "nori_mixed",
  "text": "삼성전자"
}

인덱스 매핑에 Analyzer 적용

PUT /stocks
{
  "settings": {
    "analysis": {
      "analyzer": {
        "korean": {
          "type": "nori",
          "decompound_mode": "mixed"
        }
      }
    }
  },
  "mappings": {
    "properties": {
      "name": {
        "type": "text",
        "analyzer": "korean"
      },
      "ticker": {
        "type": "keyword"
      }
    }
  }
}
  • name: 종목명, Nori로 형태소 분석
  • ticker: 종목코드, keyword로 정확 매칭 (005930, AAPL)

실전 예시: 주식 종목 인덱싱

POST /stocks/_bulk
{ "index": {} }
{ "name": "삼성전자", "ticker": "005930" }
{ "index": {} }
{ "name": "SK하이닉스", "ticker": "000660" }
{ "index": {} }
{ "name": "LG에너지솔루션", "ticker": "373220" }
{ "index": {} }
{ "name": "카카오뱅크", "ticker": "323410" }

검색:

GET /stocks/_search
{
  "query": {
    "match": {
      "name": "삼성"
    }
  }
}

결과: 삼성전자가 검색됨!


주의사항

인덱싱과 검색 시 같은 Analyzer 사용

인덱싱할 때와 검색할 때 다른 Analyzer를 쓰면 토큰이 달라져서 매칭이 안 됩니다.

검색 시점

인덱싱 시점

Analyzer A

Analyzer B

토큰 불일치!

삼성전자

[삼성전자]

삼성전자

[삼성, 전자]

{
  "mappings": {
    "properties": {
      "name": {
        "type": "text",
        "analyzer": "nori",           // 인덱싱 시
        "search_analyzer": "nori"     // 검색 시 (생략하면 analyzer와 동일)
      }
    }
  }
}

Analyzer 변경 시 재인덱싱 필요

매핑의 Analyzer를 변경하면 기존 데이터는 이전 Analyzer로 토큰화된 상태입니다. 새 Analyzer를 적용하려면 재인덱싱이 필요합니다.

재인덱싱 시

방치 시

이전 토큰 유지

재인덱싱

Analyzer 변경

기존 데이터는?

검색 불일치 발생

새 토큰으로 갱신

정상 검색

→ 이전 글 무중단 인덱스 교체 전략 참고


정리

항목 Standard Nori
한글 처리 공백 기준 분리 형태소 분석
“삼성전자” 1개 토큰 2개 토큰 (삼성, 전자)
부분 검색 안 됨
사용 케이스 영문, 코드 한글 텍스트

다음 글에서는 term, match, match_phrase 쿼리의 차이를 알아보겠습니다.


참고자료

© 2025, 미나리와 함께 만들었음