Elasticsearch 치트시트: 필수 명령어 및 팁
검색, 인덱싱 및 분석을 위한 Elasticsearch 명령어
Page content
Elasticsearch 은 Apache Lucene 를 기반으로 구축된 강력한 분산 검색 및 분석 엔진입니다. 이 종합적인 치트시트는 Elasticsearch 클러스터 작업을 위한 필수 명령어, 모범 사례 및 빠른 참고 자료를 다룹니다.

참고: 이 가이드의 대부분의 예시는 HTTP 요청에 cURL 을 사용합니다. cURL 을 처음 사용하거나 고급 옵션에 대한 빠른 참조가 필요하시다면, 자세한 명령줄 HTTP 요청 기법을 위한 cURL 치트시트 를 확인하세요.
클러스터 관리
클러스터 상태 확인
이 섹션의 모든 명령어는 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
}
'
# 대량 인덱싱 (Bulk indexing)
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
}
}
}
'
# Upsert (업데이트 또는 삽입)
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": {}
}
}
'
# 일치 (Match) 쿼리
curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d'
{
"query": {
"match": {
"name": "laptop"
}
}
}
'
# 멀티 일치 (Multi-match) 쿼리
curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d'
{
"query": {
"multi_match": {
"query": "laptop gaming",
"fields": ["name", "description"]
}
}
}
'
단어 수준 (Term-Level) 쿼리
# Term 쿼리 (정확한 일치)
curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d'
{
"query": {
"term": {
"tags": "electronics"
}
}
}
'
# Terms 쿼리 (여러 값)
curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d'
{
"query": {
"terms": {
"tags": ["electronics", "computers"]
}
}
}
'
# 범위 (Range) 쿼리
curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d'
{
"query": {
"range": {
"price": {
"gte": 100,
"lte": 1000
}
}
}
}
'
# Exists 쿼리
curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d'
{
"query": {
"exists": {
"field": "description"
}
}
}
'
불리언 (Boolean) 쿼리
# Bool 쿼리 (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" }}
]
}
}
}
'
고급 검색
# 와일드카드 (Wildcard) 쿼리
curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d'
{
"query": {
"wildcard": {
"name": "lap*"
}
}
}
'
# 퍼지 (Fuzzy) 쿼리 (오타 허용)
curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d'
{
"query": {
"fuzzy": {
"name": {
"value": "laptpo",
"fuzziness": "AUTO"
}
}
}
}
'
# 접두사 (Prefix) 쿼리
curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d'
{
"query": {
"prefix": {
"name": "lap"
}
}
}
'
집계 (Aggregations)
메트릭 집계
# 평균, 합계, 최소, 최대
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" }}
}
}
'
# Stats 집계
curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d'
{
"size": 0,
"aggs": {
"price_stats": {
"stats": { "field": "price" }
}
}
}
'
버킷 집계
# Terms 집계 (그룹화)
curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d'
{
"size": 0,
"aggs": {
"popular_tags": {
"terms": {
"field": "tags",
"size": 10
}
}
}
}
'
# Range 집계
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"
}
}
}
}
'
중첩 집계 (Nested Aggregations)
# 중첩 집계
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": {}
}
}
}
'
인덱스 별칭 (Aliases)
# 별칭 생성
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"
재인덱싱 (Reindex)
# 한 인덱스부터 다른 인덱스로 재인덱싱
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"
성능 최적화
인덱스 설정
# 대량 인덱싱 중 리프레시 비활성화
curl -X PUT "localhost:9200/products/_settings?pretty" -H 'Content-Type: application/json' -d'
{
"index": {
"refresh_interval": "-1"
}
}
'
# 대량 인덱싱 후 재활성화
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"
# Tasks 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를 비활성화하세요
쿼리 최적화
- 점수가 필요하지 않을 경우 쿼리 대신 필터를 사용하세요
- 구조화된 데이터에는 단어 수준 (term-level) 쿼리를 선호하세요
- 여러 조건을 효율적으로 결합하기 위해
bool쿼리를 사용하세요 - 심층 페이지네이션을 위해
search_after를 사용하여 페이지네이션을 구현하세요 - 자주 사용되는 필터를 캐시하세요
인덱싱 성능
- 배치 인덱싱에는 대량 API 를 사용하세요 (요청당 1000-5000 개 문서)
- 대량 작업 중에는 리프레시를 비활성화하세요
- 무거운 인덱싱 도중
index.refresh_interval을 늘리세요 - 병렬 인덱싱을 위해 여러 스레드/워커를 사용하세요
- 더 나은 샤드 분포를 위해 라우팅 사용을 고려하세요
클러스터 관리
- 클러스터 상태를 정기적으로 모니터링하세요
- 적절한 복제본 구성을 설정하세요
- 대규모 클러스터에는 전용 마스터 노드를 사용하세요
- 스냅샷을 사용하여 적절한 백업 전략을 구현하세요
- JVM 힙 사용량을 모니터링하세요 (75% 미만 유지)
보안
- 인증 및 권한 부여를 활성화하세요 (X-Pack Security)
- 프로덕션 배포에는 HTTPS 를 사용하세요 (SSL/TLS 를 위해 cURL 에
--cacert,--cert,--key옵션을 구성) - 적절한 역할 기반 접근 제어 (RBAC) 를 구현하세요
- 정기적인 보안 업데이트 및 패치 적용
- 저장 및 전송 중 데이터 암호화
일반적인 사용 사례
전체 텍스트 검색
Elasticsearch 는 다음과 같은 기능을 갖춘 전체 텍스트 검색에 탁월합니다:
- 관련성 점수 (Relevance scoring)
- 퍼지 매칭 (Fuzzy matching)
- 구문 매칭 (Phrase matching)
- 동의어 처리
- 다국어 지원 검색을 Postgres 내부에 유지할지 전용 검색 엔진으로 이동할지 평가 중이라면, 이 PostgreSQL 전체 텍스트 검색 vs Elasticsearch 비교 에서 실용적인 트레이드오프를 확인할 수 있습니다.
로그 분석 (ELK Stack)
- Logstash/Filebeat 로 로그 수집
- Elasticsearch 에서 로그 인덱싱 및 검색
- Kibana 대시보드에서 시각화
- 이상 징후를 위한 알림 설정
이커머스 검색
- 제품 카탈로그 검색
- 집계를 활용한 Faceted 네비게이션
- 자동 완성 및 제안 기능
- 개인화된 검색 결과
애플리케이션 성능 모니터링
- 애플리케이션 메트릭 인덱싱
- 실시간 모니터링 대시보드
- 이상 징후 탐지
- 성능 추이 분석
유용한 링크
공식 Elasticsearch 리소스
- 공식 Elasticsearch 문서
- Elasticsearch API 참조
- 쿼리 DSL 가이드
- Elasticsearch Python 클라이언트
- Elasticsearch JavaScript 클라이언트
- Elastic Stack 개요
- Elasticsearch 성능 튜닝
- 인덱스 수명 주기 관리
관련 치트시트 및 가이드
- cURL 치트시트 - Elasticsearch REST API 에 대한 HTTP 요청 마스터링에 필수
- TypeScript 치트시트: 핵심 개념 및 모범 사례 - 타입 안전한 Elasticsearch 클라이언트 애플리케이션 구축