![[ElasticSearch] 역인덱스(Inverted Index)](https://img1.daumcdn.net/thumb/R750x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FF6XNe%2FbtsOlUQVgJu%2FK9Pz4EqrAgdrqj7or15eY0%2Fimg.png)
이 글은 인프런의 지식 공유자 박재성님의 강의를 듣고 개인적으로 정리하는 글임을 알립니다.
유연한 검색 기능
RDBMS의 검색 한계
MySQL의 products 테이블의 name 컬럼에 맥북 에어 13 M4라고 저장해놓고, 특정 키워드로 데이터를 검색하려면 아래와 같이 SQL문을 작성해야한다.
SELECT * FROM products WHERE name = “%맥북 에어 13%”;
만약 MySQL에서 맥북 13 에어라고 검색하면 데이터가 검색되지 않는다.
SELECT * FROM products WHERE name = “%맥북 13 에어%”;
하지만 실제로 우리가 쿠팡 등에서 물건을 검색할 때 단어의 순서를 정확하게 기억하고 검색하진 않는다.
위 제품을 쿠팡에 검색해서 구매하고 싶다고 할 때, 우린 쿠팡에 맥북 에어 13 M4라고 검색할 수도 있지만, 맥북 13 에어 M4라고 검색할 수도 있다.
이와 같이 쿠팡에서는 제품 이름의 단어 순서를 지키지 않고 검색해도 같은 결과를 얻을 수 있다.
위와 같은 검색 기능을 구현하려면 Elasticsearch를 활용하면 된다.
ElasticSearch의 검색 기능
ElasticSearch는 보다 유연한 검색기능을 지원한다.
PUT /products/_mappings { "properties": { "name": { "type": "text" } } } |
이렇게 정의된 인덱스에 아래와 같이 도큐먼트를 삽입
# 도큐먼트 삽입 # POST /{인덱스명}/_doc POST /products/_doc { "name": "Apple 2025 맥북 에어 13 M4 10코어" } |
"Apple 2025 맥북 에어 13 M4 10코어" 라는 도큐먼트 삽입
# 특정 조건을 만족하는 도큐먼트 조회 # (name 필드에 '맥북 에어 13 M4'가 포함된 도큐먼트 조회) GET /products/_search { "query": { "match": { "name": "맥북 에어 13 M4" } } } |
"맥북 에어 13 M4"라고 검색을 하면 아래와 같이 결과가 나온다.
GET /products/_search { "query": { "match": { "name": "맥북 13 에어 M4" } } } |
"맥북 13 에어 M4"라고 검색을 해도 똑같은 결과가 나온다.
이러한 결과가 나오는 까닭은 RDBMS와는 다르게 역인덱스를 사용하고 있기 때문이다.
역인덱스(Inverted Index)
이론
역인덱스(Inverted Index)는 필드 값을 단어마다 쪼개서 찾기 쉽게 정리해놓은 목록이다.
analyze 과정(단어 단위로 자르는 과정)
"<h1>The Quick Brown Foxes jumped over the lazy Dog's back.</h1>" |
- 캐릭터 필터 (HTML 태그 제거, 특수 문자 치환 등)
→ "The Quick Brown Foxes jumped over the lazy Dog's back." - 토크나이저(tokenizer)
→ 공백, 특수문자 등 기준으로 토큰 분리
→ ["The", "Quick", "Brown", "Foxes", "jumped", "over", "the", "lazy", "Dog", "s", "back"]
→ Dog's는 "Dog"과 "s"로 분리됨 (구두점 제거 후 나누는 방식) - 토큰 필터(token filter)
→ 소문자 변환, 불용어(크게 의미 없는 단어) 제거, 스템머(복수형, 과거형 제거) 등 추가 처리
→ ["quick", "brown", "fox", "jump", "lazy", "dog", "back"]
POST /products/_create/1 { "name": "Apple 2025 맥북 에어 13 M4 10코어" } POST /products/_create/2 { "name": "Apple 2024 에어팟 4세대" } POST /products/_create/3 { "name": "Apple 2024 아이패드 mini A17 Pro" } |
위와 같은 3개의 도큐먼트를 Elasticsearch에 저장한다고 가정하자. 그러면 Elasticsearch는 내부적으로 아래와 같이 데이터를 저장해둔다.
- "Apple 2025 맥북 에어 13 M4 10코어"
→ [apple, 2025, 맥북, 에어, 13, m4, 10코어] - "Apple 2024 에어팟 4세대"
→ [apple, 2024, 에어팟, 4세대] - "Apple 2024 아이패드 mini A17 Pro"
→ [apple, 2024, 아이패드, mini, a17, pro]
이렇게 데이터를 정제하는 과정을 analyze 과정이라고 하며, 여러개의 애널라이저가 존재하기 때문에 다른 애널라이저를 사용하면 결과가 달라질 수 있다.
역인덱스로 저장
products의 name 필드에 대한 역인덱스
토큰(token) | 도큐먼트 id |
apple | [1, 2, 3] |
2025 | [1] |
맥북 | [1] |
에어 | [1] |
13 | [1] |
m4 | [1] |
10코어 | [1] |
2024 | [2, 3] |
에어팟 | [2] |
4세대 | [2] |
아이패드 | [3] |
mini | [3] |
a17 | [3] |
pro | [3] |
- 필드값에서 추출돼 역인덱스에 저장된 단어를 보고 토큰(token)이라고 부른다.
- 생성된 역인덱스를 직접 눈으로 확인할 수는 없다. 시스템 내부적으로 생성될 뿐이다.
검색을 할 경우 역인덱스를 활용
"Apple 2024 아이패드"라고 검색하면 역인덱스를 활용해 일치하는 단어가 많은 도큐먼트를 우선적으로 조회한다.
토큰(token) | 도큐먼트 id |
apple | [1, 2, 3] |
2025 | [1] |
맥북 | [1] |
에어 | [1] |
13 | [1] |
M4 | [1] |
10코어 | [1] |
2024 | [2, 3] |
에어팟 | [2] |
4세대 | [2] |
아이패드 | [3] |
mini | [3] |
A17 | [3] |
Pro | [3] |
- id가 1인 도큐먼트 : 단어 1개 일치
- id가 2인 도큐먼트 : 단어 2개 일치
- id가 3인 도큐먼트 : 단어 3개 일치
이와 같은 Elasticsearch의 자체적인 로직으로 score(점수)를 매겨 score가 높은 순(id=3 → id=2 → id=1)으로 도큐먼트를 조회한다.
일반적으로 검색어와 관련성이 높으면 높을수록 score(점수)가 높게 측정된다.
대략적인 score 계산 로직
TF (Term Frequency)
한 도큐먼트 안에서 검색어가 많이 나올수록 점수↑
예: "맥북"이 1번보다 5번 나오면 더 중요하게 본다.
IDF (Inverse Document Frequency)
전체 도큐먼트에서 드문 단어일수록 점수↑
예: 100개의 도큐먼트에서 "맥북"은 1번 등장하고, "노트북"은 100번 등장하면 → "맥북"에 더 높은 점수.
Field Length Normalization
같은 검색어라도 짧은 문서/필드에 등장하면 점수↑
예: 긴 문장에서 보다 짧은 문장에서 검색어가 등장하면 더 중요한 단서로 간주.
Elasticsearch가 역인덱스(Inverted Index)의 기능을 가지고 있기 때문에, 단어의 순서랑 상관없이 도큐먼트를 조회해올 수 있는 것이다.
이런 작동 구조는 데이터 타입이 keyword가 아닌 text 타입에 한해서만 적용된다.
실습
인덱스 생성
# 인덱스 생성 + 매핑 정의 PUT /products { "mappings": { "properties": { "name": { "type": "text" } } } } |
도큐먼트 삽입
# 데이터 넣기 POST /products/_create/1 { "name": "Apple 2025 맥북 에어 13 M4 10코어" } POST /products/_create/2 { "name": "Apple 2024 에어팟 4세대" } POST /products/_create/3 { "name": "Apple 2024 아이패드 mini A17 Pro" } |
도큐먼트 조회
# 'Apple 2024 아이패드'로 검색 GET /products/_search { "query": { "match": { "name": "Apple 2024 아이패드" } } } |
응답값
{ "took": 14, "timed_out": false, "_shards": { "total": 1, "successful": 1, "skipped": 0, "failed": 0 }, "hits": { "total": { "value": 3, "relation": "eq" }, "max_score": 1.5471337, "hits": [ { "_index": "products", "_id": "3", "_score": 1.5471337, "_source": { "name": "Apple 2024 아이패드 mini A17 Pro" } }, { "_index": "products", "_id": "2", "_score": 0.6860854, "_source": { "name": "Apple 2024 에어팟 4세대" } }, { "_index": "products", "_id": "1", "_score": 0.12180668, "_source": { "name": "Apple 2025 맥북 에어 13 M4 10코어" } } ] } } |
'Back-End > ElasticSearch' 카테고리의 다른 글
[ElasticSearch] 데이터 타입(data type)과 매핑(mapping) (0) | 2025.05.31 |
---|---|
[ElasticSearch] 애널라이저(Analyzer) (0) | 2025.05.31 |
[ElasticSearch] 인덱스, 도큐먼트, 매핑, 필드 (0) | 2025.05.30 |
[ElasticSearch] 작동 방식 및 Kibana (0) | 2025.05.30 |
[ElasticSearch] 기본 개념 및 설치 방법 (0) | 2025.05.30 |