✅ Elasticsearch의 검색기능이 좋은 점이 뭘까?
Mysql로도 충분히 검색 기능을 구현할 수 있다. 하지만 Elasticseach를 활용하면 더욱 사용자를 위한 검색 기능을 구현할 수 있다.
어떤 장점이 있길래 Elasticsearch를 고려하게 되는걸까?
- 검색어의 순서가 바꿔어도 검색 가능
- 기호,부호가 포함되지 않게 검색 가능
- 대소문자 고려하지 않고 검색 가능
- 동의어를 고려한 검색 가능
- 중요하지 않은 문자 제외 후 검색 가능
위 같은 검색 기능을 편하게 제공해주니까 충분히 일단 RDBMS보다 검색 기능 구현시 Elasticsearch를 고려할 만 하다.
✅ Elasticsearch의 검색기능을 제공하는 원리
Elasticsearch는 저장할 때 문자열을 토큰으로 분리해 역인덱스(Inverted Index)로 저장한다. (text타입만 가능)
역색인 (Inverted Index)
Elasticsearch가 빠르게 텍스트를 검색할 수 있는 핵심 구조이다.
일반적으로 문서 -> 단어 구조지만, 역색인은 단어 -> 문서 리스트 구조이기 때문
Lucene 엔진
Elasticsearch는 내부적으로 Lucene을 기반으로 동작하며, 색인 저장, 검색 쿼리 처리,
점수 계산 등을 실제로 수행하는 역할은 Lucene이 함.
즉, 문서를 저장하면 Analyzer가 텍스트를 단어 단위로 분석하고, Lucene이 이를 역색인 구조로 저장한다.
이 구조 덕분에 빠른 검색이 가능하다.
✅ Elasticsearch 대략적인 score 계산 로직은?
역색인 구조로 검색 되는데 만약 검색어가 들어오면 어떤 방식으로 상관관계가 높다고 판단하는지 대략적으로 정리해보자!!
Term Frequency (TF)
- 문서 내에서 검색어가 얼마나 자주 등장하냐
Inverse Document Frequency (IDF)
- 검색어가 전체 문서 중 얼마나 희귀하냐
Field Length Normalization
-문자(필드)가 짧을수록 관련도 상승
참고 이런 작동 구조는 데이터 타입 text에 한정
✅ 애널라이저(Analyzer)란?
문자열(text) 토큰으로 변환시켜 주는 장치를 보고 애널라이저(analyzer)라고 부른다.
3가지 과정이 존재한다.
캐릭터 필터(character filter), 토크나이저(tokenizer), 토큰 필터(token filter)
캐릭터 필터(character filter)
캐릭터 필터(character filter)는 문자열을 토큰으로 자르기 전에 문자열을 다듬는 역할을 한다.
다양한 종류의 필터가 존재하며, 여러 개의 필터를 적용시킬 수 있다.
mapping 필터, pattern replace 필터 등이 존재
ex)
예시 <h1>아이폰 15 사용 후기</h1> → 아이폰 15 사용 후기
토크나이저(tokenizer)
토크나이저(tokenizer)는 문자열을 토큰으로 자르는 역할을 한다. (공백 또는 . , ! ? 와 같은 문장 부호를 기준으로 자른다.)
classic 토크나이저, keyword 토크나이저, pattern 토크나이저 등 존재
ex)
The Brown-Foxes jumped over the roof.
-> [The, Brown, Foxes, jumped, over, the, roof]
토큰 필터(token filter)
최종적으로 다듬는다. 여러개 적용 가능
lowercase, stop 필터, stemmer 필터
ex)
소문자 변환, 의미 없는 단어 제거(a, the, is 등), 단어의 원래 형태(ing -> 기본형)
✅ standard Analyzer
Elasticsearch의 기본 Analyzer를 보면서 전반적인 구조를 이해해보자!
애널라이저는 3가지로 구성됨
standard Analyzer는 charcater filter는 설정되어 있지 않고, tokenizer는 standard로 설정되어 있고, token filter는 lowercase인 애널라이저를 뜻한다.
standard analyzer 표현 방식 (방법 1 = 방법 2 )
// 방법 1
"analyzer": "standard"
// 방법 2
"char_filter": [],
"tokenizer": "standard",
"filter": ["lowercase"]
캐릭터 필터는 없고, 토크나이저는 standard 이므로 공백 , . ! ? 와 같은 문장 부호를 기준으로 문자열을 자름
토큰 필터는 소문자 변환으로 해석 가능하다.
Apple 2025 맥북 에어 13 M4 10코어 문자열을 analyzer standard를 적용해서 확인해봤다.
Apple -> apple 소문자 변환, 공백 기준으로 토큰 필터 적용 확인 가능하다.
// 어떻게 analyzer가 텍스트를 나누는지 확인 가능한 문법이다.
GET /_analyze
{
"text":"Apple 2025 맥북 에어 13 M4 10코어",
"analyzer":"standard"
}
결과 :
{
"tokens": [
{
"token": "apple",
"start_offset": 0,
"end_offset": 5,
"type": "<ALPHANUM>",
"position": 0
},
{
"token": "2025",
"start_offset": 6,
"end_offset": 10,
"type": "<NUM>",
"position": 1
},
{
"token": "맥북",
"start_offset": 11,
"end_offset": 13,
"type": "<HANGUL>",
"position": 2
},
{
"token": "에어",
"start_offset": 14,
"end_offset": 16,
"type": "<HANGUL>",
"position": 3
},
{
"token": "13",
"start_offset": 17,
"end_offset": 19,
"type": "<NUM>",
"position": 4
},
{
"token": "m4",
"start_offset": 20,
"end_offset": 22,
"type": "<ALPHANUM>",
"position": 5
},
{
"token": "10코어",
"start_offset": 23,
"end_offset": 27,
"type": "<ALPHANUM>",
"position": 6
}
]
}
✅ 실질적인 실습을 통해서 알아보자
토큰을 어떻게 나누는지 확인하는법
// 방법 1
GET /_analyze
{
"text": "Apple 2025 맥북 에어 13 M4 10코어",
"analyzer": "standard"
}
// 방법 2
GET /_analyze
{
"text": "Apple 2025 맥북 에어 13 M4 10코어",
"char_filter": [],
"tokenizer": "standard",
"filter": ["lowercase"]
}
테스트 해보기!
인덱스 생성 + 매핑 정의 + Custom Analyzer 적용해보자!
// 기존 인덱스 삭제
DELETE /products
// 인덱스 생성 + 매핑 정의 + Custom Analyzer 적용
PUT /products
{
"settings": {
"analysis": {
"analyzer": {
"products_name_analyzer": {
"char_filter": [],
"tokenizer": "standard",
"filter": []
}
}
}
},
"mappings": {
"properties": {
"name": {
"type": "text",
"analyzer": "products_name_analyzer"
}
}
}
}
// 잘 생성됐는 지 확인
GET /products
POST /products/_create/1
{
"name": "Apple 2025 맥북 에어 13 M4 10코어"
}
자 standard와 다르게 토큰 필터(lowercase)가 없다
이제 apple로 검색해도 아무것도 안 나온다.
GET /products/_search
{
"query": {
"match": {
"name": "apple"
}
}
}
정확하게 Apple로 검색하면 나온다.
GET /products/_search
{
"query": {
"match": {
"name": "Apple"
}
}
}
어떻게 적용 됐는지 확인하고 싶다면
// 특정 인덱스의 필드에 적용된 Analyzer를 활용해 분석
GET /products/_analyze
{
"field": "name"
"text": "Apple 2025 맥북 에어 13 M4 10코어"
}
-> 우리가 기본적인 필터에서 커스텀 필터로 바꾸고 lowercase를 빼니까 이제 대소문자를 구분한다!
html_strip(태그 제거), stop(a an the or 등 제거), stemmer(영단어 기본형으로), synonym(동의어)
등의 기능도 있는데 이건 찾아서 학습하도록 하자!
✅ 정리
Elasticsearch 검색 기능을 제공할 때 어떻게 동작하는지 원리를 파악하였고, 구체적인 필터 적용 방법도 배웠다.
실습 내용을 더 추가할 수 있지만 스스로 검색해서 적용하는게 효율적일 듯 해서 뺐다.
✅ 참고
[Elasticsearch] 역색인(Inverted Index)과 형태소 분석
Elasticsearch는 Apache Lucene 기반의 오픈소스 실시간 분산 검색 엔진이다. Apache Lucene은 내부적으로 Inverted File Index를 활용하여 색인 구조를 생성한다. 이를 기반으로 하는 Elasticsearch 또한 동일한 방식
velog.io
https://rebugs.tistory.com/883
'DB > Elasticsearch' 카테고리의 다른 글
SpringBoot 와 Elasticsearch 연동 매우 기본 CRUD 해보기! (1) | 2025.06.07 |
---|---|
Elasticsearch의 기본 개념 (0) | 2025.05.25 |