기술과 산업/언어 및 프레임워크

Spring AI 시리즈 10화 – OpenSearch Vector Search 연동 전략

B컷개발자 2025. 7. 29. 09:57
728x90

기존 Elasticsearch/OpenSearch 인프라를 기반으로 RAG 시스템을 구축하려면 벡터 검색 기능과 LLM 연동 전략이 필요합니다. 본 글에서는 Spring AI 환경에서 OpenSearch를 활용한 Vector Search 통합 방법과 설계 전략을 정리합니다.

 


 

왜 OpenSearch 벡터 검색인가?

 

많은 기업에서 이미 Elasticsearch 또는 OpenSearch를 로그, 검색, 운영 데이터 저장소로 사용하고 있습니다.

이런 환경에 새로 LLM 기반 RAG 시스템을 도입할 때 가장 이상적인 방법은 기존 인프라를 그대로 활용하는 것입니다.

 

OpenSearch는 최근 버전부터 Dense Vector Field와 k-NN 검색 기능을 공식 지원하고 있으며,

Spring 애플리케이션에서 바로 연동할 수 있습니다.

 

Spring AI는 공식적으로 OpenSearch VectorStore를 아직 제공하지 않지만,

OpenSearch의 벡터 검색 API를 직접 연동하는 전략으로 충분히 실전 적용이 가능합니다.

 


 

OpenSearch에서 벡터 검색을 가능하게 하는 구성

 

 

1. Dense Vector Field 정의

 

OpenSearch의 인덱스 스키마(mapping)에서 dense_vector 타입을 정의합니다.

{
  "mappings": {
    "properties": {
      "text": { "type": "text" },
      "embedding": {
        "type": "dense_vector",
        "dims": 1536,
        "index": true,
        "similarity": "cosine"
      }
    }
  }
}

 

  • dims: 사용 중인 임베딩 모델 차원 수 (예: OpenAI는 1536)
  • similarity: cosine, l2_norm 등 설정 가능

 


 

2. 데이터 삽입 (벡터 포함)

 

Spring 애플리케이션에서 문서 내용을 임베딩한 뒤, OpenSearch에 벡터와 함께 저장합니다.

Map<String, Object> json = new HashMap<>();
json.put("text", "문서 내용...");
json.put("embedding", embeddingClient.embed("문서 내용..."));

IndexRequest request = new IndexRequest("my-docs")
        .id(UUID.randomUUID().toString())
        .source(json);
client.index(request, RequestOptions.DEFAULT);

 

  • embeddingClient는 Spring AI에서 제공하는 임베딩 추상화
  • OpenAI, HuggingFace, Cohere 등으로 교체 가능

 


 

3. 벡터 기반 유사도 검색 쿼리

 

OpenSearch는 knn_vector 검색 API를 제공합니다.

{
  "size": 3,
  "query": {
    "knn": {
      "embedding": {
        "vector": [/* 쿼리 임베딩 */],
        "k": 3
      }
    }
  }
}

Java에서 호출 시:

SearchSourceBuilder builder = new SearchSourceBuilder();
builder.query(QueryBuilders
    .knnQuery("embedding", queryEmbedding)
    .k(3));

SearchRequest searchRequest = new SearchRequest("my-docs");
searchRequest.source(builder);
SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);

 


 

Spring AI 기반 RAG 구조와 OpenSearch 통합

 

아래는 OpenSearch를 VectorStore로 활용할 때의 전체 흐름입니다:

 

  1. 문서 등록 시
    • 텍스트 → 임베딩 → OpenSearch 인덱싱 (text + embedding)
  2. 사용자 질문 처리 시
    • 질문 → 임베딩
    • OpenSearch에서 유사 문서 검색 (knnQuery)
    • 검색 결과 → Prompt 구성 → ChatClient.call(prompt)

 

이 구조는 Spring AI가 제공하는 EmbeddingClient, ChatClient는 그대로 사용하면서,

VectorStore만 OpenSearch로 커스텀 구성하는 방식입니다.

 


 

왜 이 전략이 유리한가?

항목설명

기존 인프라 활용 Elastic/OpenSearch를 이미 사용 중이라면 별도 벡터 DB 도입 없이 통합 가능
대규모 문서 처리 Shard/Replica 구조로 수십만~수백만 문서까지 확장 가능
메타 쿼리 통합 벡터 유사도 + 속성 기반 필터 쿼리 혼합 가능
운영 용이성 모니터링, 보안, 백업 등 기존 툴 그대로 활용 가능

 


 

실전 시 고려할 전략

전략설명

hybrid score 구성 벡터 유사도 점수 + keyword 점수 혼합
chunk 단위 저장 문서를 청크로 분할해 개별 벡터 저장 후 검색 시 병합
필터 쿼리와 결합 예: 특정 날짜, 카테고리 필터 후 벡터 검색 적용
multi-index 검색 컬렉션/도메인별 인덱스를 분리하여 다중 조회 구현

 


 

확장 방향

 

  • Kibana와 통합하여 벡터 검색 시각화
  • vector field별 boosting 설정
  • 검색 결과에 출처 메타데이터 삽입 (→ 사용자 신뢰도 증가)
  • Spring Data Elasticsearch와 연동하여 도메인 엔티티 기반 접근

 


 

요약

구성 요소Spring AI + OpenSearch 역할

EmbeddingClient 텍스트 → 벡터 변환
OpenSearch 벡터 저장 + 유사도 검색
ChatClient 검색 문서를 프롬프트에 삽입 후 응답 생성
이점 기존 인프라 유지, 유연한 필터링, 높은 운영 안정성

 

 

728x90