요즘 AI나 LLM 관련 개발 이야기를 보면 대부분 Python + LangChain 조합을 많이 사용한다. 실제로 관련 라이브러리나 예제들도 대부분 Python 중심으로 만들어져 있다.
하지만 나는 조금 다른 선택을 했다.
이전에는 C#과 .NET 환경에서 약 2년 동안 시스템을 개발했고, 현재는 Java와 Spring Boot 기반 백엔드 개발자 취업을 준비하며 Spring 생태계를 중심으로 공부하고 있다.
그래서 단순히 유행하는 스택을 따라가기보다, 내가 가장 익숙한 환경에서 LLM 기능을 어떻게 서비스에 녹일 수 있는지 직접 구현해보고 싶었다.
마침 Spring 진영에서도 Spring AI 프로젝트가 등장하면서 Java 환경에서도 LLM을 비교적 자연스럽게 사용할 수 있는 기반이 마련되었다.
그래서 이번 프로젝트에서는 Spring Boot + Spring AI 기반으로 로컬 RAG 시스템을 직접 구축해보기로 했다.
RAG 시스템을 만들 때 가장 먼저 고민했던 것은 LLM을 어디에서 실행할 것인가였다.
일반적으로는 OpenAI API 같은 클라우드 기반 모델을 사용하는 경우가 많지만, RAG는 회사 내부 문서나 민감한 데이터를 다루는 경우가 많기 때문에 몇 가지 고민이 있었다.
대표적으로 다음과 같은 문제다.
그래서 테스트 단계에서는 로컬에서 직접 LLM을 실행하는 방식을 선택했다.
이때 선택한 도구가 바로 Ollama다.
Ollama는 로컬 환경에서 LLM을 비교적 간단하게 실행할 수 있는 도구로, Docker처럼 모델을 내려받아 바로 실행할 수 있다는 장점이 있다.
이번 프로젝트에서는 다음 모델을 사용했다.
Llama 3
로컬 환경에서도 비교적 안정적인 성능을 보여주는 오픈소스 모델이고, Spring AI에서도 기본적으로 Ollama 연동을 지원하기 때문에 선택했다.

프로젝트는 Spring Boot 기반 Gradle 프로젝트로 시작했다.
개발 환경은 다음과 같다.
Java 17 + Spring Boot 4.0.3
Spring AI 2.0.0-M2
Redis Stack Server
Ollama (로컬 LLM: llama3, bge-m3 임베딩)
Gradle + Lombok
Spring AI에서 Ollama를 사용하려면 다음 의존성을 추가하면 된다.
dependencies {
implementation 'org.springframework.ai:spring-ai-ollama-spring-boot-starter'
}
그리고 application.yml에서 Ollama 서버 주소를 설정한다.
Ollama는 기본적으로 다음 포트에서 실행된다.
localhost:11434
예시 설정은 다음과 같다.
spring:
ai:
ollama:
base-url: http://localhost:11434
chat:
model: llama3 # 사용하고자 하는 모델명
RAG를 구현하기 전에 가장 먼저 확인해야 할 것은 단순하다.
Spring Boot → Ollama → LLM 응답
이 흐름이 정상적으로 동작하는지 확인하는 것이다.
그래서 가장 먼저 한 일은 간단한 프롬프트를 LLM에 보내고 응답을 받는 테스트 코드를 작성하는 것이었다.
Spring AI에서 제공하는 OllamaApi 또는 ChatClient를 이용해 간단한 질문을 보내고, 정상적으로 응답이 돌아오는 것까지 확인했다.
이 단계까지는 생각보다 어렵지 않았다. 하지만 이때까지만 해도 몰랐다.
단순히
질문 → LLM → 답변
을 만드는 것과
질문 → 문서 검색 → 관련 내용 추출 → LLM → 답변
을 만드는 것 사이에 생각보다 큰 기술적 간극이 있다는 것을.
이제 로컬 환경에서 동작하는 LLM 엔진 자체는 준비되었다.
하지만 RAG 시스템에서 중요한 것은 단순히 LLM이 아니라 외부 데이터를 어떻게 연결하느냐다.
예를 들어 다음과 같은 질문이 있다고 가정해보자.
우리 회사 API 인증 방식은 어떻게 동작해?
기본 LLM은 이 질문에 제대로 답할 수 없다.
왜냐하면 회사 내부 문서를 학습하지 않았기 때문이다.
그래서 필요한 것이 바로 RAG(Retrieval Augmented Generation) 구조다.