Elasticsearch 간편 가이드: 필수 명령어 및 팁
검색, 인덱싱 및 분석을 위한 Elasticsearch 명령어
Page content
Elasticsearch은 Apache Lucene 기반의 강력한 분산 검색 및 분석 엔진입니다.
이 포괄적인 체크리스트는 Elasticsearch 클러스터와 함께 작업할 때 필수 명령어, 최선의 실천 방법, 그리고 빠른 참조를 다룹니다.

참고: 이 가이드의 대부분 예제는 HTTP 요청에 cURL을 사용합니다. cURL에 익숙하지 않거나 고급 옵션에 대한 빠른 참조가 필요하다면, cURL 체크리스트에서 자세한 명령줄 HTTP 요청 기술을 확인해 보세요.
클러스터 관리
클러스터 상태 확인
이 섹션의 모든 명령어는 Elasticsearch의 REST API와 상호작용하기 위해 cURL을 사용합니다. 필요에 따라 추가 헤더, 인증, 기타 옵션으로 이러한 요청을 맞춤화할 수 있습니다.
# 기본 상태 확인
curl -X GET "localhost:9200/_cluster/health?pretty"
# 세부 클러스터 상태 및 샤드 정보 확인
curl -X GET "localhost:9200/_cluster/health?level=shards&pretty"
# 노드 정보 확인
curl -X GET "localhost:9200/_cat/nodes?v"
# 클러스터 설정 확인
curl -X GET "localhost:9200/_cluster/settings?pretty"
노드 작업
# 모든 노드 목록 보기
curl -X GET "localhost:9200/_cat/nodes?v&h=name,node.role,heap.percent,ram.percent,cpu,load_1m"
# 노드 통계
curl -X GET "localhost:9200/_nodes/stats?pretty"
# 핫 스레드 (문제 해결)
curl -X GET "localhost:9200/_nodes/hot_threads"
인덱스 관리
인덱스 생성 및 삭제
# 인덱스 생성
curl -X PUT "localhost:9200/my_index?pretty"
# 설정을 포함한 인덱스 생성
curl -X PUT "localhost:9200/my_index" -H 'Content-Type: application/json' -d'
{
"settings": {
"number_of_shards": 3,
"number_of_replicas": 1
}
}
'
# 인덱스 삭제
curl -X DELETE "localhost:9200/my_index?pretty"
# 모든 인덱스 목록 보기
curl -X GET "localhost:9200/_cat/indices?v"
# 인덱스 통계
curl -X GET "localhost:9200/my_index/_stats?pretty"
인덱스 매핑
# 매핑 정의
curl -X PUT "localhost:9200/products" -H 'Content-Type: application/json' -d'
{
"mappings": {
"properties": {
"name": { "type": "text" },
"price": { "type": "float" },
"created_at": { "type": "date" },
"tags": { "type": "keyword" },
"description": {
"type": "text",
"analyzer": "english"
}
}
}
}
'
# 매핑 확인
curl -X GET "localhost:9200/products/_mapping?pretty"
# 매핑 업데이트 (필드 추가)
curl -X PUT "localhost:9200/products/_mapping" -H 'Content-Type: application/json' -d'
{
"properties": {
"category": { "type": "keyword" }
}
}
'
인덱스 템플릿
# 인덱스 템플릿 생성
curl -X PUT "localhost:9200/_index_template/logs_template" -H 'Content-Type: application/json' -d'
{
"index_patterns": ["logs-*"],
"template": {
"settings": {
"number_of_shards": 1
},
"mappings": {
"properties": {
"timestamp": { "type": "date" },
"message": { "type": "text" },
"level": { "type": "keyword" }
}
}
}
}
'
# 템플릿 목록 보기
curl -X GET "localhost:9200/_index_template?pretty"
문서 작업 (CRUD)
문서 생성
# 자동 생성된 ID로 문서 인덱싱
curl -X POST "localhost:9200/products/_doc?pretty" -H 'Content-Type: application/json' -d'
{
"name": "Laptop",
"price": 999.99,
"tags": ["electronics", "computers"]
}
'
# 특정 ID로 문서 인덱싱
curl -X PUT "localhost:9200/products/_doc/1?pretty" -H 'Content-Type: application/json' -d'
{
"name": "Laptop",
"price": 999.99
}
'
# 대량 인덱싱
curl -X POST "localhost:9200/_bulk?pretty" -H 'Content-Type: application/json' -d'
{ "index": { "_index": "products", "_id": "1" }}
{ "name": "Laptop", "price": 999.99 }
{ "index": { "_index": "products", "_id": "2" }}
{ "name": "Mouse", "price": 29.99 }
'
문서 읽기
# ID로 문서 가져오기
curl -X GET "localhost:9200/products/_doc/1?pretty"
# 여러 문서 가져오기
curl -X GET "localhost:9200/_mget?pretty" -H 'Content-Type: application/json' -d'
{
"docs": [
{ "_index": "products", "_id": "1" },
{ "_index": "products", "_id": "2" }
]
}
'
# 문서 존재 여부 확인
curl -I "localhost:9200/products/_doc/1"
문서 업데이트
# 문서 업데이트
curl -X POST "localhost:9200/products/_update/1?pretty" -H 'Content-Type: application/json' -d'
{
"doc": {
"price": 899.99
}
}
'
# 스크립트로 업데이트
curl -X POST "localhost:9200/products/_update/1?pretty" -H 'Content-Type: application/json' -d'
{
"script": {
"source": "ctx._source.price *= params.discount",
"params": {
"discount": 0.9
}
}
}
'
# 업데이트 또는 삽입 (업데이트 또는 삽입)
curl -X POST "localhost:9200/products/_update/1?pretty" -H 'Content-Type: application/json' -d'
{
"doc": {
"price": 899.99
},
"doc_as_upsert": true
}
'
문서 삭제
# ID로 삭제
curl -X DELETE "localhost:9200/products/_doc/1?pretty"
# 쿼리로 삭제
curl -X POST "localhost:9200/products/_delete_by_query?pretty" -H 'Content-Type: application/json' -d'
{
"query": {
"match": {
"name": "old"
}
}
}
'
검색 쿼리
기본 검색
# 모든 문서 검색
curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d'
{
"query": {
"match_all": {}
}
}
'
# 매치 쿼리
curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d'
{
"query": {
"match": {
"name": "laptop"
}
}
}
'
# 멀티 매치 쿼리
curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d'
{
"query": {
"multi_match": {
"query": "laptop gaming",
"fields": ["name", "description"]
}
}
}
'
텀 레벨 쿼리
# 텀 쿼리 (정확한 일치)
curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d'
{
"query": {
"term": {
"tags": "electronics"
}
}
}
'
# 텀스 쿼리 (여러 값)
curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d'
{
"query": {
"terms": {
"tags": ["electronics", "computers"]
}
}
}
'
# 범위 쿼리
curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d'
{
"query": {
"range": {
"price": {
"gte": 100,
"lte": 1000
}
}
}
}
'
# 존재 쿼리
curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d'
{
"query": {
"exists": {
"field": "description"
}
}
}
'
불린 쿼리
# 불린 쿼리 (must, should, must_not, filter)
curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d'
{
"query": {
"bool": {
"must": [
{ "match": { "name": "laptop" }}
],
"filter": [
{ "range": { "price": { "gte": 500 }}}
],
"should": [
{ "term": { "tags": "gaming" }}
],
"must_not": [
{ "term": { "tags": "refurbished" }}
]
}
}
}
'
고급 검색
# 와일드카드 쿼리
curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d'
{
"query": {
"wildcard": {
"name": "lap*"
}
}
}
'
# 퍼지 쿼리 (오타 허용)
curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d'
{
"query": {
"fuzzy": {
"name": {
"value": "laptpo",
"fuzziness": "AUTO"
}
}
}
}
'
# 프리픽스 쿼리
curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d'
{
"query": {
"prefix": {
"name": "lap"
}
}
}
'
집계
메트릭 집계
# 평균, 합, 최소, 최대
curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d'
{
"size": 0,
"aggs": {
"avg_price": { "avg": { "field": "price" }},
"max_price": { "max": { "field": "price" }},
"min_price": { "min": { "field": "price" }},
"total_sales": { "sum": { "field": "price" }}
}
}
'
# 통계 집계
curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d'
{
"size": 0,
"aggs": {
"price_stats": {
"stats": { "field": "price" }
}
}
}
'
버킷 집계
# 텀 집계 (그룹화)
curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d'
{
"size": 0,
"aggs": {
"popular_tags": {
"terms": {
"field": "tags",
"size": 10
}
}
}
}
'
# 범위 집계
curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d'
{
"size": 0,
"aggs": {
"price_ranges": {
"range": {
"field": "price",
"ranges": [
{ "to": 50 },
{ "from": 50, "to": 100 },
{ "from": 100 }
]
}
}
}
}
'
# 날짜 히스토그램
curl -X GET "localhost:9200/logs/_search?pretty" -H 'Content-Type: application/json' -d'
{
"size": 0,
"aggs": {
"logs_over_time": {
"date_histogram": {
"field": "timestamp",
"calendar_interval": "day"
}
}
}
}
'
중첩 집계
# 중첩 집계
curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d'
{
"size": 0,
"aggs": {
"categories": {
"terms": { "field": "category" },
"aggs": {
"avg_price": {
"avg": { "field": "price" }
}
}
}
}
}
'
정렬 및 페이지네이션
# 필드로 정렬
curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d'
{
"query": { "match_all": {} },
"sort": [
{ "price": { "order": "desc" }},
{ "_score": { "order": "desc" }}
]
}
'
# from/size로 페이지네이션
curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d'
{
"from": 0,
"size": 10,
"query": { "match_all": {} }
}
'
# 깊은 페이지네이션을 위한 search_after
curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d'
{
"size": 10,
"query": { "match_all": {} },
"sort": [{ "price": "asc" }, { "_id": "asc" }],
"search_after": [100, "product_123"]
}
'
필드 선택 및 하이라이팅
# 특정 필드 선택
curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d'
{
"query": { "match_all": {} },
"_source": ["name", "price"]
}
'
# 하이라이팅
curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d'
{
"query": {
"match": { "description": "gaming laptop" }
},
"highlight": {
"fields": {
"description": {}
}
}
}
'
인덱스 별칭
# 별칭 생성
curl -X POST "localhost:9200/_aliases?pretty" -H 'Content-Type: application/json' -d'
{
"actions": [
{ "add": { "index": "products_v1", "alias": "products" }}
]
}
'
# 새 인덱스로 별칭 전환 (중단 없는 전환)
curl -X POST "localhost:9200/_aliases?pretty" -H 'Content-Type: application/json' -d'
{
"actions": [
{ "remove": { "index": "products_v1", "alias": "products" }},
{ "add": { "index": "products_v2", "alias": "products" }}
]
}
'
# 별칭 목록 보기
curl -X GET "localhost:9200/_cat/aliases?v"
재인덱싱
# 하나의 인덱스에서 다른 인덱스로 재인덱싱
curl -X POST "localhost:9200/_reindex?pretty" -H 'Content-Type: application/json' -d'
{
"source": {
"index": "old_products"
},
"dest": {
"index": "new_products"
}
}
'
# 쿼리와 함께 재인덱싱
curl -X POST "localhost:9200/_reindex?pretty" -H 'Content-Type: application/json' -d'
{
"source": {
"index": "products",
"query": {
"range": {
"price": { "gte": 100 }
}
}
},
"dest": {
"index": "expensive_products"
}
}
'
스냅샷 및 백업
# 스냅샷 저장소 등록
curl -X PUT "localhost:9200/_snapshot/my_backup?pretty" -H 'Content-Type: application/json' -d'
{
"type": "fs",
"settings": {
"location": "/mount/backups/my_backup"
}
}
'
# 스냅샷 생성
curl -X PUT "localhost:9200/_snapshot/my_backup/snapshot_1?wait_for_completion=true&pretty"
# 스냅샷 복원
curl -X POST "localhost:9200/_snapshot/my_backup/snapshot_1/_restore?pretty"
# 스냅샷 목록 보기
curl -X GET "localhost:9200/_snapshot/my_backup/_all?pretty"
# 스냅샷 삭제
curl -X DELETE "localhost:9200/_snapshot/my_backup/snapshot_1?pretty"
성능 최적화
인덱스 설정
# 대량 인덱싱 중 refresh 비활성화
curl -X PUT "localhost:9200/products/_settings?pretty" -H 'Content-Type: application/json' -d'
{
"index": {
"refresh_interval": "-1"
}
}
'
# 대량 인덱싱 후 refresh 다시 활성화
curl -X PUT "localhost:9200/products/_settings?pretty" -H 'Content-Type: application/json' -d'
{
"index": {
"refresh_interval": "1s"
}
}
'
# 강제 병합 (최적화)
curl -X POST "localhost:9200/products/_forcemerge?max_num_segments=1&pretty"
캐시 정리
# 모든 캐시 정리
curl -X POST "localhost:9200/_cache/clear?pretty"
# 특정 캐시 정리
curl -X POST "localhost:9200/products/_cache/clear?query=true&pretty"
모니터링 및 문제 해결
# 대기 중인 작업
curl -X GET "localhost:9200/_cat/pending_tasks?v"
# 스레드 풀 통계
curl -X GET "localhost:9200/_cat/thread_pool?v"
# 세그먼트 정보
curl -X GET "localhost:9200/_cat/segments?v"
# 복구 정보
curl -X GET "localhost:9200/_cat/recovery?v&h=index,stage,time"
# 작업 API
curl -X GET "localhost:9200/_tasks?detailed=true&pretty"
Python 클라이언트 예제
from elasticsearch import Elasticsearch
# Elasticsearch에 연결
es = Elasticsearch(['http://localhost:9200'])
# 문서 인덱싱
doc = {
'name': 'Laptop',
'price': 999.99,
'tags': ['electronics']
}
es.index(index='products', id=1, document=doc)
# 검색
resp = es.search(index='products', query={'match': {'name': 'laptop'}})
for hit in resp['hits']['hits']:
print(hit['_source'])
# 대량 인덱싱
from elasticsearch.helpers import bulk
actions = [
{
'_index': 'products',
'_id': i,
'_source': {'name': f'Product {i}', 'price': i * 10}
}
for i in range(1000)
]
bulk(es, actions)
JavaScript/Node.js 클라이언트 예제
Elasticsearch JavaScript 클라이언트는 클러스터와 상호작용하는 데 안전한 타입을 제공합니다. 프로덕션 애플리케이션에서는 타입 안전성과 자동 완성 기능을 위해 TypeScript를 사용하는 것이 좋습니다. TypeScript 체크리스트에서 타입 정의 및 인터페이스에 대한 최선의 실천 방법을 확인해 보세요.
const { Client } = require('@elastic/elasticsearch');
const client = new Client({ node: 'http://localhost:9200' });
// 문서 인덱싱
async function indexDoc() {
await client.index({
index: 'products',
id: 1,
document: {
name: 'Laptop',
price: 999.99
}
});
}
// 검색
async function search() {
const result = await client.search({
index: 'products',
query: {
match: { name: 'laptop' }
}
});
console.log(result.hits.hits);
}
// 대량 인덱싱
async function bulkIndex() {
const operations = [];
for (let i = 0; i < 1000; i++) {
operations.push({ index: { _index: 'products', _id: i } });
operations.push({ name: `Product ${i}`, price: i * 10 });
}
await client.bulk({ operations });
}
강력한 타이핑을 위한 TypeScript 예제
import { Client } from '@elastic/elasticsearch';
interface Product {
name: string;
price: number;
tags?: string[];
created_at?: Date;
}
const client = new Client({ node: 'http://localhost:9200' });
async function indexProduct(product: Product, id: number): Promise<void> {
await client.index<Product>({
index: 'products',
id: id.toString(),
document: product
});
}
async function searchProducts(query: string): Promise<Product[]> {
const result = await client.search<Product>({
index: 'products',
query: {
match: { name: query }
}
});
return result.hits.hits.map(hit => hit._source as Product);
}
최선의 실천 방법
인덱스 설계
- 최적의 성능을 위해 샤드 크기를 20~50GB 사이로 유지하세요.
- 시계열 데이터에 대해 인덱스 라이프사이클 관리(ILM)를 사용하세요.
- 데이터 인덱싱 전에 매핑을 신중하게 설계하세요.
- 적절한 필드 타입을 사용하세요 (keyword vs text, 날짜 형식 등).
- 필요하지 않다면 대규모 문서에 대해
_source를 비활성화하세요.
쿼리 최적화
- 점수 계산이 필요하지 않다면 필터 대신 쿼리를 사용하세요.
- 구조화된 데이터에 대해 텀 레벨 쿼리를 선호하세요.
bool쿼리를 사용하여 여러 조건을 효율적으로 결합하세요.- 깊은 페이지네이션을 위해
search_after를 사용하세요. - 자주 사용되는 필터를 캐시하세요.
인덱싱 성능
- 배치 인덱싱을 위해 bulk API를 사용하세요 (요청당 1000~5000 문서).
- 대량 인덱싱 중 refresh를 비활성화하세요.
- 대량 인덱싱 중
index.refresh_interval을 증가시켜 주세요. - 병렬 인덱싱을 위해 여러 스레드/워커를 사용하세요.
- 샤드 분배를 위해 라우팅을 고려하세요.
클러스터 관리
- 클러스터 상태를 정기적으로 모니터링하세요.
- 적절한 복제 구성 설정하세요.
- 대규모 클러스터에 대해 전용 마스터 노드를 사용하세요.
- 스냅샷을 사용하여 적절한 백업 전략을 구현하세요.
- JVM 힙 사용량을 모니터링하세요 (75% 미만 유지).
보안
- 인증 및 권한 부여(X-Pack 보안)를 활성화하세요.
- 프로덕션 배포에 HTTPS를 사용하세요 (cURL에
--cacert,--cert,--key옵션으로 SSL/TLS 구성). - 적절한 역할 기반 접근 제어를 구현하세요.
- 정기적인 보안 업데이트 및 패치를 수행하세요.
- 데이터를 저장 및 전송 중에 암호화하세요.
일반적인 사용 사례
전체 텍스트 검색
Elasticsearch는 다음과 같은 기능으로 전체 텍스트 검색에 탁월합니다:
- 관련성 점수
- 퍼지 매칭
- 문장 매칭
- 동의어 처리
- 다국어 지원
로그 분석 (ELK 스택)
- 로그스태시/파일비트로 로그 수집
- Elasticsearch에 로그 인덱싱 및 검색
- Kibana 대시보드로 시각화
- 이상 징후에 대한 경고 설정
전자상거래 검색
- 제품 카탈로그 검색
- 집계를 통한 편리한 탐색
- 자동 완성 및 제안
- 개인화된 검색 결과
애플리케이션 성능 모니터링
- 애플리케이션 메트릭 인덱싱
- 실시간 모니터링 대시보드
- 이상 탐지
- 성능 추세 분석
유용한 링크
공식 Elasticsearch 자료
- 공식 Elasticsearch 문서
- Elasticsearch API 참조
- 쿼리 DSL 가이드
- Elasticsearch Python 클라이언트
- Elasticsearch JavaScript 클라이언트
- Elastic Stack 개요
- Elasticsearch 성능 최적화
- 인덱스 라이프사이클 관리
관련 체크리스트 및 가이드
- cURL 체크리스트 - Elasticsearch REST API에 대한 HTTP 요청을 마스터하는 데 필수적인 자료
- TypeScript 체크리스트: 핵심 개념 및 최선의 실천 방법 - 타입 안전한 Elasticsearch 클라이언트 애플리케이션을 구축하세요