2) Elasticsearch 시작

2-1) Docker로 실행

# Elasticsearch + Kibana
docker-compose up -d

docker-compose.yml:

version: '3.8'

services:
  elasticsearch:
    image: docker.elastic.co/elasticsearch/elasticsearch:8.11.0
    environment:
      - discovery.type=single-node
      - xpack.security.enabled=false
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
    ports:
      - "9200:9200"
    volumes:
      - es-data:/usr/share/elasticsearch/data

  kibana:
    image: docker.elastic.co/kibana/kibana:8.11.0
    ports:
      - "5601:5601"
    environment:
      - ELASTICSEARCH_HOSTS=http://elasticsearch:9200
    depends_on:
      - elasticsearch

volumes:
  es-data:

확인:

curl http://localhost:9200
# {
#   "name" : "...",
#   "cluster_name" : "docker-cluster",
#   "version" : { "number" : "8.11.0" }
# }

2-2) Analyzer Pipeline (분석 과정)

“안녕하세요!“라는 문장이 저장될 때, Analyzer를 통해 검색 가능한 Term으로 변환됩니다.

flowchart LR
    Input["text: '<b>Hello</b> World!'"] --> CharFilter[Char Filter<br/>(HTML Strip)]
    CharFilter -->|'Hello World!'| Tokenizer[Tokenizer<br/>(Standard)]
    Tokenizer -->|'[Hello, World]'| TokenFilter[Token Filter<br/>(Lowercase)]
    TokenFilter -->|'[hello, world]'| Output["Inverted Index"]

    style Input fill:#eceff1,stroke:#455a64
    style Output fill:#fff3e0,stroke:#e65100
    style Tokenizer fill:#ffe0b2,stroke:#f57c00
  • Character Filter: 문장 전처리 (HTML 태그 제거 등)
  • Tokenizer: 단어 분리 (공백 기준 등)
  • Token Filter: 후처리 (소문자 변환, 불용어 제거)

2-3) 인덱스 생성

# 인덱스 생성
PUT /products
{
  "mappings": {
    "properties": {
      "name": {
        "type": "text",
        "analyzer": "standard"
      },
      "price": {
        "type": "integer"
      },
      "category": {
        "type": "keyword"
      },
      "tags": {
        "type": "keyword"
      },
      "created_at": {
        "type": "date"
      }
    }
  }
}

필드 타입:

text: 전문 검색 (분석됨)
keyword: 정확히 일치 (분석 안 됨)
integer, long: 숫자
date: 날짜
boolean: true/false

3) CRUD 작업

3-1) 문서 추가

# 단일 문서
POST /products/_doc/1
{
  "name": "맥북 프로 M3",
  "price": 2500000,
  "category": "노트북",
  "tags": ["Apple", "고성능"],
  "created_at": "2025-12-16"
}

# ID 자동 생성
POST /products/_doc
{
  "name": "아이패드 프로",
  "price": 1200000,
  "category": "태블릿"
}

# 벌크 삽입
POST /_bulk
{ "index": { "_index": "products", "_id": "2" } }
{ "name": "맥북 에어 M2", "price": 1500000, "category": "노트북" }
{ "index": { "_index": "products", "_id": "3" } }
{ "name": "아이맥 M3", "price": 2000000, "category": "데스크톱" }

3-2) 문서 조회

# ID로 조회
GET /products/_doc/1

# 전체 조회
GET /products/_search

# 조건 검색
GET /products/_search
{
  "query": {
    "match": {
      "name": "맥북"
    }
  }
}

3-3) 문서 수정

# 전체 교체
PUT /products/_doc/1
{
  "name": "맥북 프로 M3 Max",
  "price": 3000000
}

# 부분 수정
POST /products/_update/1
{
  "doc": {
    "price": 2800000
  }
}

3-4) 문서 삭제

# 단일 삭제
DELETE /products/_doc/1

# 조건부 삭제
POST /products/_delete_by_query
{
  "query": {
    "range": {
      "price": {
        "lt": 1000000
      }
    }
  }
}

📚 다음 편: 준비 중입니다.


👈 이전 편: Elasticsearch (Part 1: 개념과 구조)