Milvus 실무 스터디 가이드

데이터 엔지니어 · AI 엔지니어를 위한 핵심 요약

벡터 데이터베이스 분산 시스템 오픈소스 AI 인프라 2026.03 작성

목차

  1. Milvus란?
  2. 왜 써야 하는가?
  3. 핵심 개념
  4. 퀵스타트
  5. 핵심 설정 레퍼런스
  6. 실무 팁 & 트러블슈팅
  7. 참고 자료

1. Milvus란?

Milvus는 대규모 벡터 데이터를 저장, 관리, 검색하기 위해 설계된 오픈소스 벡터 데이터베이스입니다. AI 애플리케이션(유사성 검색, 추천 시스템, 멀티모델 검색 등)의 핵심 인프라 역할을 합니다.

대규모 벡터 검색

억(10^9) 단위의 고차원 벡터에서도 밀리초 수준의 Nearest Neighbor Search(NNS)를 지원합니다. 분산 아키텍처로 스케일 아웃이 가능합니다.

다양한 인덱스 지원

IVF_FLAT, HNSW, DISKANN, SCANN 등 상황별 최적의 인덱스 알고리즘을 제공하여 정확도/속도/메모리 trade-off를 조정할 수 있습니다.

하이브리드 검색

벡터 검색과 메타데이터 필터링(속성 검색)을 결합한 강력한 하이브리드 쿼리를 지원합니다. 실무에서 필수적인 기능입니다.

2. 왜 써야 하는가?

AI 애플리케이션에서 벡터 검색을 구현할 때 고려할 수 있는 대안들과 Milvus의 비교입니다.

솔루션 유형 장점 단점 / Milvus 차별점 적합한 경우
Milvus 전용 벡터 DB 대규모, 고성능, 분산, 다양한 인덱스, 하이브리드 검색 운영 복잡성(클러스터), 전문성 요구 프로덕션 대규모 시스템, 실시간 검색
PostgreSQL + pgvector DB 확장 SQL 통합, 운영 간편, 트랜잭션 지원 스케일 제한, 인덱스 옵션 부족, 전문 검색 성능 낮음 소규모, 벡터+메타데이터 통합 관리가 주요 요구
Elasticsearch 검색 엔진 풍부한 텍스트 검색, 강력한 집계, 운영 도구 많음 벡터 검색 기능 제한적(8.0+ 지원), 전문 벡터 인덱스 부재 텍스트 검색이 주이고 벡터 검색이 보조인 경우
메모리/파일 기반 (FAISS, Annoy) 라이브러리 단순함, 빠른 프로토타이핑, 연구용 지속성 없음, 분산 불가, 운영 기능(백업/모니터링) 없음 연구, 소규모 프로토타입, 임시 검색
결론: 프로덕션 환경에서 억 단위 벡터를 실시간으로 검색해야 하고, 하이브리드 쿼리와 높은 성능이 요구될 때 Milvus가 최적의 선택입니다.

3. 핵심 개념

아키텍처 다이어그램 (Standalone 모드)

+-------------------+ +-------------------+ +-------------------+ | Access Layer | | Coordinator | | Worker Node | | (Milvus Proxy) |<----->| (Query Coord) |<----->| (Query Node) | | | | (Data Coord) | | (Data Node) | +-------------------+ +-------------------+ +-------------------+ | | | v v v +-------------------+ +-------------------+ +-------------------+ | Object Storage | | Meta Storage | | Index Storage | | (MinIO/S3) | | (MySQL/Etcd) | | (Local Disk) | +-------------------+ +-------------------+ +-------------------+

4. 퀵스타트

Standalone 모드로 빠르게 시작하는 단계별 가이드입니다.

  1. 설치 (Docker)

    # Milvus Standalone Docker 이미지 pull 및 실행
    docker pull milvusdb/milvus:latest
    docker run -d \
      --name milvus-standalone \
      -p 19530:19530 \
      -p 9091:9091 \
      milvusdb/milvus:latest

    포트 19530(GRPC)과 9091(HTTP)이 열립니다.

  2. Python 클라이언트 설치 및 연결

    # pymilvus 설치
    pip install pymilvus
    
    # Python 연결 코드
    from pymilvus import connections, Collection, FieldSchema, CollectionSchema, DataType
    
    # Milvus 서버 연결
    connections.connect(
      alias="default",
      host='localhost',
      port='19530'
    )
    print("Connected to Milvus.")
  3. 첫 Collection 생성 및 데이터 삽입

    # 1. 필드 정의 (ID, 벡터, 속성)
    fields = [
      FieldSchema(name="id", dtype=DataType.INT64, is_primary=True),
      FieldSchema(name="embedding", dtype=DataType.FLOAT_VECTOR, dim=128),
      FieldSchema(name="category", dtype=DataType.VARCHAR, max_length=100)
    ]
    
    # 2. Collection Schema 생성
    schema = CollectionSchema(fields=fields, description="첫 번째 예제 컬렉션")
    
    # 3. Collection 생성
    collection_name = "demo_collection"
    collection = Collection(name=collection_name, schema=schema)
    
    # 4. 데이터 삽입 (벡터 + 메타데이터)
    import random
    data = [
      [i for i in range(10)],  # id 리스트
      [[random.random() for _ in range(128)] for _ in range(10)],  # 10개의 128차원 벡터
      ["cat", "dog", "bird", "cat", "dog", "bird", "cat", "dog", "bird", "cat"]  # 속성
    ]
    collection.insert(data)
    print(f"Inserted {len(data[0])} entities.")
    
    # 5. 인덱스 생성 (HNSW 사용)
    index_params = {
      "index_type": "HNSW",
      "metric_type": "L2",
      "params": {"M": 16, "efConstruction": 200}
    }
    collection.create_index("embedding", index_params)
    print("Index created.")
  4. 검색 실행 (하이브리드 쿼리)

    # Collection 로드 (인덱싱 후 필수)
    collection.load()
    
    # 검색 벡터 준비
    search_vector = [[random.random() for _ in range(128)]]
    
    # 검색 파라미터 설정
    search_params = {"metric_type": "L2", "params": {"ef": 50}}
    
    # 하이브리드 쿼리: 벡터 검색 + 속성 필터링
    results = collection.search(
      data=search_vector,
      anns_field="embedding",
      param=search_params,
      limit=5,
      expr="category == 'cat'",  # 메타데이터 필터링 표현식
      output_fields=["id", "category"]  # 반환 필드 지정
    )
    
    for hits in results:
        for hit in hits:
            print(f"id: {hit.entity.id}, category: {hit.entity.category}, distance: {hit.distance}")

5. 핵심 설정 레퍼런스

Standalone 및 Cluster 모드의 주요 구성 옵션입니다.

설정 항목 기본값/예시 설명 실무 영향
인덱스 타입 (index_type) "HNSW", "IVF_FLAT", "DISKANN" 벡터 검색 알고리즘 선택 HNSW: 정확도 높음, 메모리 많이 사용. IVF_FLAT: 밸런스 좋음. DISKANN: 디스크 기반 대규모.
인덱스 파라미터 (params) HNSW: {"M": 16, "efConstruction": 200} 인덱스 품질/성능/메모리 Trade-off 조정 M, efConstruction 높으면 정확도 ↑, 빌드 시간 ↑, 메모리 ↑.
검색 파라미터 (search_params) HNSW: {"ef": 50}, IVF: {"nprobe": 10} 검색 시 정확도/속도 조정 ef, nprobe 높으면 정확도 ↑, 검색 시간 ↑.
쓰루풋/병렬처리 (queryNode.replica) Cluster: 2 Query Node 복제본 수 높으면 쿼리 처리량 ↑, 리소스 사용 ↑.
메타 저장소 (meta.store) etcd (Cluster), MySQL (Standalone) Collection, Index, Partition 메타정보 저장 etcd: 분산 환경 강건성. MySQL: 단순성.
오브젝트 저장소 (minio.address) localhost:9000 (Standalone) 실제 벡터 데이터 저장 (S3 호환) 성능 및 확장성의 핵심. 프로덕션에서는 외부 S3 사용 권장.

6. 실무 팁 & 트러블슈팅

팁 1: 인덱스 선택 가이드

  • 정확도 최우선 + 메모리 충분: HNSW 사용.
  • 메모리 제한 + 대규모 데이터: IVF_FLAT 또는 DISKANN.
  • 실험적 결정: 소규모 데이터 샘플로 각 인덱스 타입의 성능/정확도를 측정 후 선택.

팁 2: 하이브리드 검색 최적화
  • 메타데이터 필터링(expr)은 벡터 검색 후 적용됩니다. 필터링 조건이 너무 강하면 결과가 적어질 수 있습니다.
  • 자주 사용하는 필터 조건에 대해 파티션을 사용하면 성능이 크게 향상될 수 있습니다.

문제 1: 검색 결과가 비정상적으로 적음

원인: 인덱스 빌드 파라미터(efConstruction, nlist)가 너무 낮거나, 검색 파라미터(ef, nprobe)가 너무 낮음.

해결: 인덱스 재생성 시 파라미터 증가. 또는 검색 시 ef/nprobe 값을 점진적으로 증가시켜 테스트.

문제 2: 삽입 속도가 매우 느림

원인: 단일 삽입 작업을 반복 호출, 또는 인덱스가 생성된 상태에서 삽입.

해결: 벡터를 배치로 삽입 (최소 100~1000개 단위). 인덱스 생성 전에 모든 데이터 삽입 완료 후 인덱싱.

문제 3: Collection 로드 시 메모리 부족 오류

원인: 인덱스(특히 HNSW)가 너무 많은 메모리를 요구.

해결: 인덱스 타입을 IVF_FLAT 또는 DISKANN으로 변경. 또는 Worker Node 메모리 증가, 데이터를 여러 파티션으로 분산.

팁 3: 모니터링 필수 항목
  • 쿼리 latency: 검색 성능 기준.
  • 메모리 사용량: 인덱스 로드 상태 확인.
  • 디스크 사용량: 오브젝트 저장소(MinIO/S3) 용량 관리.
  • 연결 수: 동시 클라이언트 부하 모니터링.

7. 참고 자료