SelfCheck_AI Troubleshooting_4 (26.02.01)

Meustar·2026년 1월 31일

Project

목록 보기
13/15

주제: Spring AI 버전 호환성, Docker DB 연결, 그리고 Multi-LLM Bean 충돌 해결


1. PostgreSQL pgvector 확장 모듈 부재 (Local vs Docker)

🔴 문제 상황 (Symptoms)

프로젝트 실행 시 UnsatisfiedDependencyException과 함께 아래와 같은 에러 로그가 발생하며 서버가 시작되지 않음.

Error creating bean with name 'vectorStore' ...
StatementCallback; uncategorized SQLException for SQL [CREATE EXTENSION IF NOT EXISTS vector];
오류: "vector" 이름의 확장 모듈을 사용할 수 없습니다
Detail: "C:/Program Files/PostgreSQL/16/share/extension/vector.control" ... No such file or directory.

🔍 원인 (Cause)

RAG(검색 증강 생성) 구현을 위해 pgvector 확장이 필요한데, 로컬 윈도우 환경에 설치된 기본 PostgreSQL에는 해당 확장 모듈이 설치되어 있지 않음. (윈도우에서 직접 빌드 및 설치가 까다로움)

🟢 해결 (Solution)

Docker를 도입하여 pgvector가 이미 설치된 이미지를 사용하는 방식으로 환경을 전환함.

  1. 기존 로컬 DB(5432 포트)와 충돌을 피하기 위해 Docker 컨테이너 포트를 5433으로 매핑.
  2. pgvector/pgvector:pg16 이미지 사용.
docker run -d --name selfcheck-db -p 5433:5432 \
  -e POSTGRES_USER=... -e POSTGRES_DB=... \
  pgvector/pgvector:pg16
  1. application.yml의 Datasource URL을 jdbc:postgresql://localhost:5433/...으로 변경.


2. Spring AI 버전 불일치 및 API 변경 (Breaking Changes)

🔴 문제 상황 (Symptoms)

Gradle 빌드 시 수많은 cannot find symbol 에러 발생.

  • cannot find symbol method getContent()
  • cannot find symbol method query(String)

🔍 원인 (Cause)

프로젝트 초기 설정은 Spring AI 1.0.0-M1이었으나, 적용하려는 코드는 최신 기능이 포함된 1.0.0-M6 기준이었음. 버전 업그레이드 과정에서 Document.getContent()Document.getText()로 변경되는 등 API 파괴적 변경(Breaking Changes)이 있었음.

🟢 해결 (Solution)

  1. build.gradle의 버전을 M6로 상향 조정.
ext { set('springAiVersion', "1.0.0-M6") }
  1. 컴파일 에러가 나는 메서드들을 신규 API 명세에 맞춰 리팩토링.
  • .getContent() -> .getText()
  • SearchRequest.query(...) -> SearchRequest.builder().query(...).build()

3. 복수 AI 모델 사용 시 Bean 주입 충돌 (NoUniqueBeanDefinitionException)

🔴 문제 상황 (Symptoms)

OpenAI와 Gemini를 동시에 사용하기 위해 의존성을 추가했더니, 서버 시작 시 에러 발생.

Parameter 0 of constructor in AiClient required a single bean, but 2 were found:
- openAiChatModel
- vertexAiGeminiChat

🔍 원인 (Cause)

Spring AI의 자동 설정(Auto Configuration)에 의해 ChatModel 인터페이스의 구현체가 2개(OpenAI, Gemini) 생성됨. 스프링 컨테이너가 AiClient 생성자에 어떤 빈을 주입해야 할지 판단하지 못해 발생한 모호성(Ambiguity) 문제.

🟢 해결 (Solution)

@Qualifier 어노테이션을 사용하여 각 컴포넌트가 사용할 모델을 명시적으로 지정함.

// AiClient (Writer 역할) -> OpenAI 사용
public AiClient(@Qualifier("openAiChatModel") ChatModel chatModel, ...) { ... }

// AiValidator (Validator 역할) -> Gemini 사용
public AiValidator(@Qualifier("geminiChatModel") ChatModel chatModel, ...) { ... }

4. Vertex AI vs Google AI Studio (인증 방식 차이)

🔴 문제 상황 (Symptoms)

Gemini를 사용하기 위해 spring-ai-vertex-ai-gemini 의존성을 추가했으나, API Key만으로는 인증이 되지 않고 GCP Project ID 및 Credentials 에러가 발생.

🔍 원인 (Cause)

spring-ai-vertex-ai-gemini 라이브러리는 기업용 Google Cloud Vertex AI를 위한 것으로, 복잡한 GCP 인증 절차가 필요함. 반면 현재 보유한 키는 개발자용 Google AI Studio API Key였음.

🟢 해결 (Solution)

  1. Vertex AI 의존성을 제거하고, OpenAI 호환 모드(OpenAI Compatibility) 방식을 채택.
  2. spring-ai-openai 라이브러리를 재사용하되, Base URL만 Google Gemini의 엔드포인트로 변경하여 커스텀 빈(geminiChatModel)을 등록함.
// GeminiConfig.java
String baseUrl = "https://generativelanguage.googleapis.com/v1beta/openai/";
OpenAiApi geminiApi = new OpenAiApi(baseUrl, geminiApiKey);
// ... ChatModel 생성 후 Bean 등록

이로써 별도의 복잡한 라이브러리 추가 없이 API Key 하나만으로 Gemini를 연동하는 데 성공함.


profile
유튜브 기술 영상을 보면서 잘 이해하기 위해... Lilys AI를 활용해 배경지식, 영상 전체 요약 및 핵심 내용 설명들을 블로깅 합니다. 작성한 내용들에 대해서 언제고 다시 "내가" 찾아 볼 수 있도록 기록으로 남깁니다!

0개의 댓글