Elasticsearch를 Docker로 구축하고, **Python (FastAPI)**을 사용하여 CRUD API를 만드는 전체 과정

1. Elasticsearch Docker 구축 (docker-compose)

개발 및 테스트 편의를 위해 보안 설정(HTTPS, 인증)을 끄고 단일 노드(Single Node)로 구성하겠습니다.

폴더 구조:

Text

es-crud-project/
├── docker-compose.yml
└── main.py

docker-compose.yml 작성:

Yaml

version: '3.8'

services:
  elasticsearch:
    image: docker.elastic.co/elasticsearch/elasticsearch:8.12.0
    container_name: es-container
    environment:
      - discovery.type=single-node
      - xpack.security.enabled=false  # 개발용: 보안 비활성화 (HTTPS/ID/PW 없이 접속)
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m" # 메모리 제한 (로컬 환경 부담 줄임)
    ports:
      - "9200:9200"
    networks:
      - es-net

  # (선택사항) 데이터 시각화를 위한 Kibana
  kibana:
    image: docker.elastic.co/kibana/kibana:8.12.0
    container_name: kibana-container
    environment:
      - ELASTICSEARCH_HOSTS=http://elasticsearch:9200
    ports:
      - "5601:5601"
    depends_on:
      - elasticsearch
    networks:
      - es-net

networks:
  es-net:
    driver: bridge

실행 명령어:
터미널에서 해당 폴더로 이동 후 아래 명령어를 실행합니다.

Bash

docker-compose up -d

확인: 브라우저에서 http://localhost:9200에 접속했을 때 JSON 응답이 오면 성공입니다.


2. Python API 프로그램 작성 (FastAPI)

빠르고 현대적인 웹 프레임워크인 FastAPI와 공식 Elasticsearch Python 클라이언트를 사용합니다.

라이브러리 설치:

Bash

pip install fastapi uvicorn elasticsearch

main.py 작성:

Python

from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
from elasticsearch import Elasticsearch, NotFoundError

app = FastAPI()

# 1. Elasticsearch 연결 설정
# Docker에서 보안을 껐으므로 http://localhost:9200으로 접속합니다.
es = Elasticsearch("http://localhost:9200")

# 인덱스 이름 (RDBMS의 Table과 유사)
INDEX_NAME = "my_products"

# 데이터 모델 정의 (Request Body 검증용)
class Product(BaseModel):
    name: str
    price: int
    category: str = None

# --- CRUD API 구현 ---

# 1. CREATE (데이터 생성)
@app.post("/products/")
def create_product(product: Product):
    # document를 인덱스에 저장
    resp = es.index(index=INDEX_NAME, document=product.dict())
    return {"status": "success", "id": resp["_id"], "data": product}

# 2. READ (데이터 조회 - ID로 조회)
@app.get("/products/{item_id}")
def read_product(item_id: str):
    try:
        resp = es.get(index=INDEX_NAME, id=item_id)
        return {"id": resp["_id"], "data": resp["_source"]}
    except NotFoundError:
        raise HTTPException(status_code=404, detail="Item not found")

# 2-1. READ ALL (검색 - 모든 데이터 조회)
@app.get("/products/")
def search_products(keyword: str = None):
    if keyword:
        # 키워드가 있으면 이름에서 검색
        query = {
            "match": {
                "name": keyword
            }
        }
    else:
        # 키워드가 없으면 전체 조회 (match_all)
        query = {"match_all": {}}

    resp = es.search(index=INDEX_NAME, query=query)
    
    # 검색 결과 가공
    results = []
    for hit in resp['hits']['hits']:
        results.append({"id": hit["_id"], "data": hit["_source"]})
        
    return {"count": len(results), "results": results}

# 3. UPDATE (데이터 수정)
@app.put("/products/{item_id}")
def update_product(item_id: str, product: Product):
    try:
        # doc: 부분 업데이트할 내용
        es.update(index=INDEX_NAME, id=item_id, doc=product.dict())
        return {"status": "updated", "id": item_id, "data": product}
    except NotFoundError:
        raise HTTPException(status_code=404, detail="Item not found")

# 4. DELETE (데이터 삭제)
@app.delete("/products/{item_id}")
def delete_product(item_id: str):
    try:
        es.delete(index=INDEX_NAME, id=item_id)
        return {"status": "deleted", "id": item_id}
    except NotFoundError:
        raise HTTPException(status_code=404, detail="Item not found")

3. API 실행 및 테스트 방법

Elasticsearch를 Docker로 구축하고, **Python (FastAPI)**을 사용하여 CRUD API를 만드는 전체 과정

API 서버 실행:
터미널에서 다음 명령어를 입력합니다.

Bash

uvicorn main:app --reload

테스트 방법 (Swagger UI 사용):
FastAPI는 자동으로 문서 페이지를 생성해줍니다. 브라우저를 열고 아래 주소로 접속하세요.

👉 http://localhost:8000/docs

여기서 버튼을 클릭하여 바로 테스트할 수 있습니다.

수동 테스트 예시 (CRUD 흐름)

  1. Create (생성):

    • POST /products/

    • Body: {“name”: “MacBook Pro”, “price”: 3000000, “category”: “Electronics”}

    • 결과: 생성된 id를 복사해 둡니다 (예: AbC123…).

  2. Read (ID 조회):

    • GET /products/{item_id}

    • item_id에 위에서 복사한 ID 입력.

  3. Search (검색):

    • GET /products/?keyword=MacBook

    • Elasticsearch의 검색 엔진 기능을 통해 “MacBook”이 포함된 데이터를 찾습니다.

  4. Update (수정):

    • PUT /products/{item_id}

    • Body: {“name”: “MacBook Pro M3”, “price”: 3500000, “category”: “Electronics”}

  5. Delete (삭제):

    • DELETE /products/{item_id}

요약

  1. Docker Compose를 이용해 보안 설정을 끈 ES 8.x 버전을 실행했습니다.

  2. Python Elasticsearch Client를 이용해 localhost:9200에 연결했습니다.

  3. FastAPI로 RESTful API를 만들어 index(생성), get/search(조회), update(수정), delete(삭제) 기능을 구현했습니다.