Elasticsearch
목차
검색 엔진의 역할
Elasticsearch는 검색과 분석에 특화된 분산 검색 엔진이다. 텍스트를 분석해 인덱스를 만들고, 빠른 전문 검색과 실시간 집계를 제공한다.
관계형 DB 검색과의 차이
관계형 DB 검색:
1
2
3
4
-- LIKE로 전문 검색하면 느림
SELECT * FROM articles
WHERE content LIKE '%linux network%';
-- 전체 행을 스캔해야 함 (풀 스캔)
Elasticsearch 검색:
1
2
3
4
5
6
7
8
9
// 인덱싱된 데이터에서 빠르게 검색
GET /articles/_search
{
"query": {
"match": {
"content": "linux network"
}
}
}
Elasticsearch는 “linux”, “network” 같은 단어가 어느 문서에 있는지 미리 인덱싱해두므로, LIKE 검색보다 훨씬 빠르다.
사용 시나리오
1
2
3
4
로그 분석 수백만 개의 로그 라인에서 특정 에러 검색
검색 엔진 제품명, 설명으로 상품 검색
시계열 데이터 메트릭, 추적 데이터 수집 및 분석
원본 DB 아님 읽기 전용 인덱스 (원본은 관계형 DB)
Elasticsearch는 원본 데이터베이스를 완전히 대체하지 않는다. 대신 빠른 검색과 분석을 위해 관계형 DB 위에 구축된다.
1
2
3
4
5
관계형 DB (원본)
↓ (데이터 동기화)
Elasticsearch (인덱스)
↓
빠른 검색 제공
Index와 Document
Elasticsearch의 기본 구조는 Index(인덱스)에 Document(문서)를 저장하는 것이다.
Index
Index는 관계형 DB의 테이블에 해당한다. 문서들의 집합이다.
1
2
3
4
5
Elasticsearch 관계형 DB
----------------- -----------
Index Table
Document Row
Field Column
Document
각 Document는 JSON 형식의 데이터다.
1
2
3
4
5
6
7
8
9
10
11
{
"_id": "1",
"_index": "articles",
"_type": "_doc",
"title": "Linux Networking Basics",
"content": "Learn about network packets, IP, TCP...",
"author": "john",
"tags": ["linux", "network", "beginner"],
"published_date": "2026-05-23",
"view_count": 1234
}
Index 생성 및 Document 저장
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# Index 생성
PUT /articles
{
"settings": {
"number_of_shards": 1,
"number_of_replicas": 0
}
}
# Document 저장 (자동 ID 생성)
POST /articles/_doc
{
"title": "Linux Networking Basics",
"content": "Learn about network packets...",
"author": "john",
"tags": ["linux", "network"]
}
# Document 저장 (ID 지정)
PUT /articles/_doc/1
{
"title": "Elasticsearch Basics",
"content": "How to use Elasticsearch for searching...",
"author": "jane"
}
# Document 조회
GET /articles/_doc/1
# Document 수정
POST /articles/_doc/1/_update
{
"doc": {
"view_count": 5000
}
}
# Document 삭제
DELETE /articles/_doc/1
Mapping (스키마)
Mapping은 각 필드의 데이터 타입을 정의한다 (SQL의 CREATE TABLE과 유사).
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
PUT /articles
{
"mappings": {
"properties": {
"title": {
"type": "text"
},
"content": {
"type": "text"
},
"author": {
"type": "keyword" // 분석하지 않음 (정확히 일치)
},
"tags": {
"type": "keyword"
},
"published_date": {
"type": "date"
},
"view_count": {
"type": "integer"
}
}
}
}
필드 타입:
-
text: 전문 검색 (분석됨, 토큰화) -
keyword: 정확한 매칭 (분석 안 됨) -
integer,long: 숫자 -
date: 날짜 -
object: 중첩된 객체 -
array: 배열
Inverted Index
Inverted Index(역색인)는 Elasticsearch가 빠른 검색을 제공하는 핵심 이유다.
일반 인덱스 vs 역색인
일반 인덱스 (Document → Term):
1
2
3
Document 1: "linux network basics"
Document 2: "network security guide"
Document 3: "linux kernel design"
“network”를 찾으려면 모든 문서를 스캔해야 한다.
역색인 (Term → Document):
1
2
3
4
5
6
7
linux → Document 1, Document 3
network → Document 1, Document 2
basics → Document 1
security → Document 2
guide → Document 2
kernel → Document 3
design → Document 3
“network”를 검색하면 역색인에서 바로 [Document 1, Document 2]를 찾을 수 있다. (매우 빠름)
역색인 구성 과정
1
2
3
4
5
6
7
8
9
Document 입력
↓
Analyzer가 토큰화 및 정규화
↓ (예: "Linux NETWORK Basics" → ["linux", "network", "basics"])
역색인 생성
↓
term: "linux" → [doc_id: 1, doc_id: 3, ...]
term: "network" → [doc_id: 1, doc_id: 2, ...]
term: "basics" → [doc_id: 1, ...]
역색인이 있으면 검색이 O(1) ~ O(log n) 시간에 가능하다. (DB LIKE는 O(n))
Analyzer
Analyzer(분석기)는 텍스트를 토큰(단어)으로 나누고 정규화하는 도구다.
Analyzer 구성
1
2
3
4
5
6
Character Filter (문자 필터)
↓ (특수 문자 제거, HTML 태그 제거 등)
Tokenizer (토큰화)
↓ (공백, 구두점 기준으로 단어 분리)
Token Filter (토큰 필터)
↓ (소문자 변환, 불용어 제거, 형태소 분석 등)
기본 Analyzer
1
2
3
4
5
6
7
8
9
// Standard Analyzer (기본값)
GET /articles/_analyze
{
"analyzer": "standard",
"text": "The quick brown fox jumps!"
}
// 결과
["the", "quick", "brown", "fox", "jumps"]
언어별 Analyzer
English Analyzer (영어):
1
2
3
4
5
6
7
8
GET /articles/_analyze
{
"analyzer": "english",
"text": "running runs runner"
}
// 결과 (형태소 분석: 어간 추출)
["run", "run", "runner"]
Korean Analyzer (한국어, 플러그인 필요):
1
2
3
4
5
6
7
8
GET /articles/_analyze
{
"analyzer": "korean",
"text": "엘라스틱서치는 검색 엔진입니다"
}
// 결과 (형태소 분석)
["엘라스틱", "서치", "검색", "엔진"]
커스텀 Analyzer
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
PUT /articles
{
"settings": {
"analysis": {
"analyzer": {
"my_analyzer": {
"type": "custom",
"char_filter": ["html_strip"],
"tokenizer": "standard",
"filter": ["lowercase", "stop"] // 불용어 제거
}
}
}
},
"mappings": {
"properties": {
"content": {
"type": "text",
"analyzer": "my_analyzer"
}
}
}
}
Full-text Search
Full-text Search(전문 검색)는 문서 내 단어를 검색하는 기능이다.
기본 검색
1
2
3
4
5
6
7
8
9
10
11
// match: 텍스트를 분석해서 검색
GET /articles/_search
{
"query": {
"match": {
"title": "linux network"
}
}
}
// 결과: "linux"나 "network"를 포함하는 문서
검색 연산자
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
// AND (둘 다 포함)
GET /articles/_search
{
"query": {
"match": {
"title": {
"query": "linux network",
"operator": "and" // 기본값은 "or"
}
}
}
}
// Phrase Search (정확한 구문)
GET /articles/_search
{
"query": {
"match_phrase": {
"content": "network packets" // "network packets" 순서대로
}
}
}
// Boolean 쿼리 (복합 조건)
GET /articles/_search
{
"query": {
"bool": {
"must": [
{ "match": { "title": "linux" } }
],
"must_not": [
{ "match": { "tags": "advanced" } }
],
"filter": [
{ "range": { "published_date": { "gte": "2026-01-01" } } }
]
}
}
}
검색 결과
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
{
"hits": {
"total": { "value": 2 },
"hits": [
{
"_id": "1",
"_score": 1.234, // 관련도 점수 (높을수록 관련도 높음)
"_source": {
"title": "Linux Networking Basics",
"content": "..."
}
},
{
"_id": "2",
"_score": 0.567,
"_source": { ... }
}
]
}
}
Aggregation
Aggregation(집계)는 데이터를 분석하고 통계를 내는 기능이다. SQL의 GROUP BY와 유사하다.
기본 집계
Terms Aggregation (카테고리별 개수):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
GET /articles/_search
{
"size": 0, // 문서 반환하지 않음 (집계만)
"aggs": {
"tags_count": {
"terms": {
"field": "tags",
"size": 10 // 상위 10개
}
}
}
}
// 결과
{
"aggregations": {
"tags_count": {
"buckets": [
{
"key": "linux",
"doc_count": 45
},
{
"key": "network",
"doc_count": 38
},
...
]
}
}
}
Date Histogram (시간대별 분석):
1
2
3
4
5
6
7
8
9
10
11
12
13
GET /articles/_search
{
"aggs": {
"articles_per_day": {
"date_histogram": {
"field": "published_date",
"calendar_interval": "day"
}
}
}
}
// 결과: 일별 문서 개수
Range Aggregation (범위별 분석):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
GET /articles/_search
{
"aggs": {
"views_range": {
"range": {
"field": "view_count",
"ranges": [
{ "to": 100 },
{ "from": 100, "to": 1000 },
{ "from": 1000 }
]
}
}
}
}
Avg/Sum (평균/합계):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
GET /articles/_search
{
"aggs": {
"average_views": {
"avg": {
"field": "view_count"
}
},
"total_views": {
"sum": {
"field": "view_count"
}
}
}
}
중첩 집계
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
GET /articles/_search
{
"aggs": {
"by_author": {
"terms": {
"field": "author"
},
"aggs": {
"average_views": {
"avg": {
"field": "view_count"
}
}
}
}
}
}
// 결과: 작성자별 평균 조회수
정리
Elasticsearch의 특징:
- 빠른 검색: 역색인으로 대규모 데이터에서 밀리초 단위 검색
- 언어 지원: 언어별 Analyzer로 다양한 텍스트 처리
- 분석 기능: 집계를 통해 즉각적인 인사이트 도출
- 분산 구조: 대규모 데이터를 여러 노드에 분산 저장
사용 시 주의:
- 원본 DB 아님: 항상 원본 데이터는 관계형 DB에 유지
- 읽기 최적화: 쓰기는 느릴 수 있음 (인덱싱 비용)
- 메모리 사용: 인덱싱은 메모리/디스크를 많이 사용
- 일관성: 검색 결과가 즉시 반영되지 않을 수 있음 (refresh interval)