Spring AI를 활용하여 나만의 AI 챗봇 '파스텔' 만들기
요약
Spring AI와 Spring Boot를 활용하여 Claude API 기반의 개인 AI 챗봇 '파스텔'을 개발하는 과정을 다루고 있습니다. LLM 자체는 생각만 할 수 있으므로, 대화 이력 관리 및 도구 사용(Tool Calling) 기능을 구축하는 것이 핵심입니다.
핵심 포인트
- Spring AI와 Spring Boot를 이용해 대화 메커니즘을 구현합니다.
- 대화의 연속성을 위해 이전 메시지 이력을 DB에서 가져와 프롬프트에 포함시킵니다.
- LLM의 능력을 확장하기 위해서는 외부 도구(Tool) 연동이 중요합니다.
저는 Spring AI를 사용하여 AI 챗봇인 '파스텔(ぱすてる)'을 만들고 있습니다.
이 글은 개발 일지에 가까운 내용이며, AI 챗봇과 관련된 기술적인 내용을 일부 포함하고 있습니다.
안녕하세요. 엔지니어 경력 2년차 AK-isnot입니다!
요즘 AI의 발전 속도가 엄청나죠. Claude나 Codex처럼 저도 매일 사용하는 AI 챗봇들은 날마다 똑똑해지고 있습니다. Neuro-sama를 대표하는 AI Vtuber들도 사랑스럽고 귀엽고요.
하지만 깊이 생각해보면, AI 챗봇이 어떤 원리로 작동하는지 잘 모른다는 것을 깨닫게 됩니다. 평소에 사용하는 'AI'라는 것이 도대체 어떻게 움직이는 건지 모르겠습니다.
그래서 한번 만들어보자! 바로 AI 챗봇을요!
저의 지적 호기심을 채우기 위해 다음과 같은 목표를 세웠습니다.
- AI 챗봇 '파스텔'을 만들면서 제 기술력을 향상시키기 (Java, Spring Boot, SQL 등)
- '파스텔'은 궁극적으로 '성장하는 AI'가 되는 것을 목표로 합니다. (이를 어떻게 구현할지는 현재 탐구 중입니다.)
- Vibe Coding(감으로 코딩하기)는 하지 않습니다. 공부가 되지 않기 때문입니다.
물론 처음부터 AI(LLM) 자체를 개발하는 것은 불가능하므로, 현재는 Claude API를 '파스텔'의 핵심으로 사용하고 있습니다.
그렇다면 여기서 '개발'이라는 것이 무엇을 의미하게 될까요? 핵심이 되는 AI가 이미 API를 통해 사용할 수 있는 상태이기 때문입니다.
여기서 Spring Boot와 Spring AI를 사용하여 '대화 메커니즘 구축'을 할 필요성이 생깁니다.
전제 조건으로, LLM 모델은 대략적으로 '입력을 받아 생각하고 출력하는 것' 외의 기능은 없습니다.
'대화하는 기능'이나 '이력을 기억하는 기능'도 없습니다.
따라서 입력을 하고 출력을 받는 부분과, 이력을 가져와 프롬프트에 섞는 부분을 Spring Boot로 만듭니다. 대략적인 플로우는 다음과 같습니다.

사용자 입력을 Claude API로 전송(입력)하고, 응답을 DB(이번에는 SQLite)에 저장합니다. 저장하는 것은 사용자 입력과 AI의 반환값 모두입니다.
다음 메시지를 보낼 때는 지금까지 보낸 메시지들을 DB에서 가져와서 그것을 사용자 입력에 포함시켜 전송함으로써 '대화'를 성립시킵니다.
만약 단순한 챗봇이라면, 이 정도만으로도 충분히 대화가 가능합니다. 애초에 사용하고 있는 모델이 Sonnet이라 충분히 똑똑하며, 응답 수준도 높습니다. 제대로 이력을 포함하여 대화해 줍니다.
여기서부터는 '파스텔'에 대한 설명으로 넘어가는데, 현재 '파스텔'은 다음 기술 스택으로 구동되고 있습니다.
| 구분 | 사용 중인 것 |
|---|---|
| 언어 | Java 21 (Temurin 21.0.12) |
| ... |
여러 내용을 적었지만 중요한 것은, 'LLM은 생각하는 것이 일'이기 때문에 'LLM이 생각하는 데 사용할 수 있는 도구(tool)를 늘리는 것'이 중요해진다는 점입니다.
현재는 아래 그림에 추가된 두 가지가 주로 작동하고 있습니다.

'@Tool' 부분을 봐주세요. 이것은 Spring AI에서 @Tool 어노테이션을 붙임으로써 만들 수 있는, AI가 호출할 수 있는 '도구(tool)'입니다.
(엄밀히 말하면, AI가 이 도구를 이 인수로 사용하고 싶다고 지정하고, Spring AI가 그 메서드를 실행하여 반환하는 흐름입니다.)
예를 들어, 웹 검색을 하기 위해 Tavily를 호출하는 WebSearchTavily 클래스를 구현하는 것은 다음과 같습니다.
package com.akisnot.pastel.Tool;
import java.util.List;
import java.util.Map;
...
코드 수준에 대해서는 보기 좋지 않은 부분이 있을 수도 있지만, 중요한 점은 Tool 어노테이션을 붙임으로써 AI가 사고하는 데 사용할 수 있는 '도구'를 늘릴 수 있다는 것입니다.
이는 즉, 도구를 늘려나감으로써 AI가 '할 수 있는 것'이 증가한다는 의미입니다.
저는 이 부분이 매우 흥미로웠습니다. 지금까지 대략적으로 사용하던 AI가, 사고하는 LLM과 그 LLM을 지탱하는 도구라는 두 가지로 분리하여 생각하게 된 계기가 되었습니다.
'파스텔'은 다음 디렉토리 구조로 구동되고 있습니다.
pastel/
├── pom.xml
├── .env # API 키 (Git 관리 제외)
...
여기서 제가 중요하다고 느꼈던 부분과 흥미로웠던 부분을 몇 가지 정리해 보겠습니다.
파스텔의 페르소나 설정은 이 파일에 모아서 관리하고 있습니다. 구체적으로는 파스텔의 성격과 기본적인 출력만 유지하여 컨텍스트가 과도하게 늘어나지 않도록 주의를 기울이고 있습니다. Sonnet을 사용하는 동안에는 신경 쓰지 않아도 되지만, 장래에 로컬 모델로 전환할 때 등을 고려하고 있습니다. (다만 현재 구성상 Claude의 컴퓨팅 파워를 이용하고 있어서 API 비용이 많이 발생하고 있습니다……)
구체적으로는 다음과 같습니다.
# 당신에 대하여
- 당신은 이 PC에 거주하는 AI입니다.
- 당신은 '잠자는 공주'입니다. PC와 함께 잠들고, 부팅하면 눈을 뜹니다.
...
핵심 포인트는 다음과 같습니다.
PC에 거주하는 AI이며 '잠자는 공주'라는 점입니다. 여기서 제목이 회수됩니다.
이는 앞서 설명한 도구 사용법이 됩니다. 도구는 AI 자신이 호출하는 것이므로, 기본적인 사용법을 설명해 둘 필요가 있습니다. 이는 별도의 파일로 분리하여 관리해도 좋을 것 같습니다.
이것은 예시를 보여주기 위해 태그를 사용하고 있습니다.
이 PASTEL.md 파일은 매번 대화할 때 프롬프트에 섞여 전송됩니다.
제목 회수입니다. 2일차 개발에서 '파스텔'에게 주기적으로 관심 있는 주제에 대해 조사하도록 하는 기능을 개발했습니다.
이는 제가 생각하는 '인간적인 모습' 중 하나인 '자발적 발언'을 구현하기 위한 실험이었습니다.
현재 설정으로는 1시간마다 조사를 수행하고, 그 결과를 Obsidian의 Vault에 저장할 수 있게 되었습니다.
처음에는 PASTEL.md와 사용자 입력만 있는 상태로 조사하게 했기 때문에, 파스텔의 '관심사'가 자신의 '잠자는 공주'라는 단어에 이끌려 잠자기 → 동면 → 물곰(クマムシ)으로 이어지면서, 물곰에 관한 것만 연구하는 공주님이 탄생해 버렸습니다.
지금은 사전에 무엇을 조사할 것인지 프롬프트에 섞어 보낼 수 있게 되었기 때문에, 무엇을 조사할지에 대한 관심사가 다른 방향으로 흐르게 되었습니다.
다만, 이런 편향성은 '관심' 또는 '흥미'로 볼 수도 있습니다.
현재 단계에서는 아직 '언어유희(言葉遊び)' 수준이라고 생각합니다.
파스텔을 앞으로 개발해 나가는 데 있어서는 Obsidian의 Vault 개념을 장기 기억으로 채택하여 강화하고 싶습니다.
이미 Claude의 메모리 기능 등에서는 비슷한 md 파일에 기록하고 싶은 것을 적어 저장하는 시스템이 사용되고 있습니다.
다만 그것은 어디까지나 업무/개발용 AI로서 최적화된 형태로 정리되어 있으므로, 파스텔에 적용할 구현 방식이 어떨지 고민해 보고 싶습니다.
다른 목표로는 다음과 같은 것들을 생각하고 있습니다.
-
스마트폰으로 대화할 수 있게 하기.
-
지금은 모두 PC의 로컬에서 작동하고 있기 때문에 어떻게 할지 검토 중입니다. 하지만 그렇게 어렵지는 않을 것이라고 생각합니다.
-
외형(가와, ガワ)을 입히고 싶다.
-
갖고 싶죠. Live2D. 엄청 비싸지만요.
이상입니다! GitHub 페이지도 첨부해 드릴 테니, 관심 있는 분들은 한번 봐주세요!
AI 자동 생성 콘텐츠
본 콘텐츠는 Qiita AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기