Sherlog 구축기: RAG, Spring AI, Groq 및 pgvector를 활용한 AI 로그 분석기
요약
Spring AI, Groq, pgvector를 활용하여 애플리케이션 로그의 근본 원인을 분석하고 해결책을 제시하는 AI 로그 분석기 'Sherlog' 구축 과정을 소개합니다. RAG 기술을 적용하여 과거 장애 사례를 기반으로 정확한 답변을 생성하는 파이프라인을 구현했습니다.
핵심 포인트
- Spring AI의 ChatClient를 활용한 구조화된 JSON 출력 구현
- RAG를 통한 과거 장애 사례 기반의 맥락 있는 로그 분석
- Groq의 빠른 추론 성능과 pgvector를 이용한 벡터 검색 활용
- Local ONNX 임베딩 모델을 통한 효율적인 텍스트 벡터화
모든 개발자는 그 기분을 알고 있습니다. 운영 환경(production)에서 에러가 발생하고, 중요한 단 한 줄을 찾기 위해 스택 트레이스(stack-trace) 텍스트 벽을 뚫어지게 쳐다보고 있는 상황 말이죠. 그래서 저는 Sherlog를 만들었습니다. 애플리케이션 로그를 읽고, 근본 원인을 파악하며, 깔끔한 JSON 형식으로 단계별 해결책을 제공하는 AI "로그 탐정"입니다. 반전은 단순히 LLM에 맹목적으로 질문하는 것이 아니라는 점입니다. **RAG (Retrieval-Augmented Generation, 검색 증강 생성)**를 사용하여 모든 답변을 과거 장애 사례 지식 베이스에 근거하도록 합니다.
이 포스트에서는 이것이 어떻게 작동하는지, 그리고 이를 구축하며 배운 실제 교훈들을 살펴보겠습니다.
🔗 Repo: github.com/pallavimudkhede21/Sherlog
기술 스택 (The stack)
- Java 21 + Spring Boot 4.1 — 백엔드
- Spring AI 2.0 — LLM 프레임워크 (ChatClient, 구조화된 출력, RAG 어드바이저)
- Groq (
llama-3.1-8b-instant) — 빠르고 OpenAI와 호환되는 LLM 추론 - Local ONNX 임베딩 (embeddings) (
all-MiniLM-L6-v2) — 텍스트 → 벡터 변환, 프로세스 내 실행, 무료 - PostgreSQL + pgvector — 벡터 데이터베이스 (Docker 환경)
아이디어: 챗봇에서 RAG 시스템으로
A 단순한 버전은 로그를 LLM에 보내고 답변을 출력할 뿐입니다. 작동은 하지만, 조언이 일반적입니다. 모델은 오직 학습 데이터와 당신이 붙여넣은 단 하나의 로그만을 알고 있기 때문입니다.
RAG는 이를 변화시킵니다. LLM에 질문하기 전에, 당신이 보유한 관련 지식(과거의 장애 사례 및 검증된 해결책)을 _검색(retrieve)_하고, 이를 프롬프트에 _증강(augment)_합니다. 이제 모델은 당신의 현실에 근거하여 답변합니다.
전체 파이프라인은 다음과 같습니다:
로그 → 임베딩 (local MiniLM) → pgvector 검색 (상위 3개 장애 사례)
→ 프롬프트에 주입 → Groq (JSON 모드) → 타입이 지정된 응답
파트 1 — Spring AI를 이용한 구조화된 출력 (Structured output)
첫 번째 성과는 자유 형식의 텍스트를 파싱하는 대신 LLM으로부터 타입이 지정된 JSON을 반환받는 것입니다. Spring AI의 ChatClient는 .entity()를 통해 이를 수행합니다:
return chat.prompt()
.system(SYSTEM_PROMPT)
.user(u -> u.text("Analyze these logs:\n\n{logs}").param("logs", request.getLogs()))
...
.entity(LogAnalysisResponse.class)는 POJO로부터 JSON 스키마를 생성하여 모델이 이를 준수하도록 지시하고, 응답을 객체에 즉시 매핑합니다. Groq의 JSON 모드 (response_format: json_object)는 유효한 JSON을 강제하므로, 산문(prose) 형태의 응답 때문에 매핑이 실패하는 일이 발생하지 않습니다.
파트 2 — 임베딩 (Embeddings) + pgvector
"유사한 과거 장애 사례"를 찾기 위해 키워드 매칭을 하는 것이 아니라, **의미 (meaning)**를 비교합니다. 임베딩 (Embedding) 모델은 텍스트를 벡터 (vector, 숫자 리스트)로 변환하며, 의미가 유사하면 벡터 간의 거리도 가까워집니다.
저는 Spring AI의 Transformers starter(ONNX all-MiniLM-L6-v2, 384 차원)를 사용하여 임베딩 모델을 **로컬 (locally)**에서 실행합니다. 별도의 임베딩 API나 비용이 들지 않습니다. 벡터는 Postgres 확장 기능인 pgvector에 저장됩니다:
docker run -d --name pgvector-db \
-e POSTGRES_PASSWORD=postgres -e POSTGRES_DB=lograg \
-p 5432:5432 pgvector/pgvector:pg17
Spring AI는 시작 시 vector_store 테이블(HNSW 코사인 인덱스 포함)을 자동으로 생성하며, 로더(loader)가 작은 incidents.json 파일로부터 데이터를 채웁니다:
vectorStore.add(documents); // 각 텍스트를 임베딩하고 벡터를 저장합니다
파트 3 — 한 줄로 RAG 연결하기
이것이 핵심입니다. Spring AI에는 검색 및 증강 (retrieve-and-augment) 단계를 자동으로 수행하는 전용 QuestionAnswerAdvisor가 있습니다:
.advisors(QuestionAnswerAdvisor.builder(vectorStore)
.searchRequest(SearchRequest.builder().topK(3).build())
.build())
이를 ChatClient 호출에 추가하면, 이제 모든 요청은 가장 유사한 과거 장애 사례 3개를 검색하여 Groq가 답변하기 전에 프롬프트 (prompt)에 주입합니다. 이것이 RAG의
동일한 모델, 동일한 로그입니다. 유일한 차이점은 검색 (retrieval)이며, 그 결과로 도출된 근거 있는 답변 (grounded answer)은 측정 가능한 수준으로 더 실행 가능한 정보를 제공합니다.
고난 끝에 얻은 교훈
튜토리얼에서는 모든 과정이 매끄러워 보일 수 있지만, 실제로는 그렇지 않았습니다. 진짜 교훈은 다음과 같습니다:
- 도입 전 라이브러리 ↔ 프레임워크 버전을 확인하세요. Spring Boot 4는 Jackson 2가 아닌 Jackson 3 (
tools.jackson)를 사용하며, Spring AI 2.0이 필요합니다. 버전을 혼용하느라 몇 시간을 허비했습니다. - 에러 메시지를 문자 그대로 읽으세요.
404 Unknown request URL에러는 단순히 기본 URL (base URL)에서/v1이 누락된 문제였습니다. Spring AI 2.0은 1.x 문서의 컨벤션 (convention)을 변경했습니다. - 구조화된 출력 (Structured output)은 마법이 아닙니다. 작은 모델은 JSON 모드를 _강제_하지 않으면 산문 (prose) 형태로 답변을 반환합니다.
- 블로그가 아닌 jar 파일을 믿으세요. 임포트 (import)에 실패했을 때, 실제 jar 파일에 대해
javap를 실행해 보니 클래스가 마일스톤 (milestone)과 GA (General Availability) 사이에서 중첩된 타입 (nested type)으로 이동했음을 확인할 수 있었습니다. 바이트코드 (bytecode)를 읽는 것이 추측하는 것보다 훨씬 낫습니다.
직접 시도해 보세요
전체 소스 코드는 GitHub에 공개되어 있으며, 설정 방법을 안내하는 README가 포함되어 있습니다:
🔗 github.com/pallavimudkhede21/Sherlog
Spring AI, RAG, 또는 pgvector를 배우고 있다면, 저장소를 클론 (clone)하여 이것저것 시도해 보세요. ?rag=true|false 토글 스위치를 사용하면 검색 (retrieval)이 실제로 어떤 이점을 주는지 _확인_할 수 있는 재미있는 방법이 될 것입니다.
Spring Boot 4, Spring AI 2.0, Groq, 그리고 pgvector로 구축되었습니다. 질문은 댓글로 환영합니다!
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기