Spring AI
Updated:
Spring AI는 OpenAI, Hugging Face 등 주요 LLM 모델을 지원하고 다양한 벡터 저장소 및 대화 기억 저장 옵션을 지원한다. 또한 RAG, 도구 호출은 물론 MCP(Model Context Protocol) 서버 개발 기능까지 포함한다.
프롬프트는 AI 모델이 이용자의 의도를 정확히 파악하여 답변하도록 돕는 구체적인 명령문으로, LLM은 프롬프트를 입력받아 학습된 패턴과 지식을 기반으로 최적의 결과물을 생성한다. 프롬프트의 3대 구성 요소는 다음과 같다.
- 상황(Context): 어떤 배경이나 환경에서 작업해야 하는가?
- 내용(Task): 구체적으로 무엇을 수행해야 하는가?
- 형식(Format): 어떤 구조나 스타일로 응답해야 하는가?
개발환경 구축
OpenAI API를 이용하기 위해 크레딧을 충전하고 발급받은 API KEY를 환경 변수로 등록해야 한다.
변수 이름: OPENAI_API_KEY
변수 값: sk-XXXXXXXXXXXXXXXXXX
Spring 프로젝트를 생성한다.
- Java 25
- Spring Boot 버전: 3.5.11
- Dependencies: Spring Web, Spring ReactiveWeb, OpenAI, Thymeleaf, Lombok
다음과 같이 코드를 작성한다.
public interface ChatbotService {
// 사용자 UI를 만들 때는 Flux를 사용하는게 좋음
Flux<String> chat(String question);
}
@Slf4j
@Service
// @RequiredArgsConstructor
public class ChatBotServiceImpl implements ChatbotService {
private final ChatModel chatModel;
public ChatBotServiceImpl(ChatModel chatModel) {
this.chatModel = chatModel;
}
@Override
public Flux<String> chat(String question) {
// UserMessage userMessage = new UserMessage(question);
// Prompt prompt = new Prompt(userMessage);
// String answer = chatModel.call(question);
Flux<String> answer = chatModel.stream(question);
return answer;
}
}
@Controller
@RequestMapping("/chatbot")
public class ChatbotController {
private final ChatbotService chatbotService;
public ChatbotController(ChatbotService chatbotService) {
this.chatbotService = chatbotService;
}
@GetMapping
public String index() {
return "chatbot/index";
}
@ResponseBody
@PostMapping(
consumes = MediaType.APPLICATION_JSON_VALUE,
produces = MediaType.APPLICATION_NDJSON_VALUE // Flux를 안쓸 때, TEXT_PLAIN_VALUE
)
public Flux<String> message(@RequestBody String question) {
return chatbotService.chat(question);
}
}
이제 실행을 해보면 다음과 같이 정상적으로 작동되는 것을 확인할 수 있다.

텍스트 대화
Message 인터페이스
애플리케이션의 메시지는 크게 사전 생성(입력)과 사후 생성(출력 / 결과) 단계로 나뉘며, 모든 메시지는 기본적으로 Message 인터페이스를 상속한다. 메시지 종류는 다음과 같다.
- SystemMessage
- 생성 시점: LLM 요청 전
- AI의 역할, 말투, 제약 사항 등 기본 지침 설정
- 추가 구현 인터페이스: Message
- UserMessage
- 생성 시점: LLM 요청 전
- 사용자가 입력한 질문이나 명령 (멀티모달 지원)
- 추가 구현 인터페이스: Message, MediaContent
- AssistantMessage
- 생성 시점: LLM 요청 후
- 사용자의 요청에 대한 AI의 응답, 대화 기억유지에도 사용되어 일관되고 맥락에 맞는 대화에 도움을 줌(멀티모달 지원)
- 추가 구현 인터페이스: Message, MediaContent
- ToolResponseMessage
- 생성 시점: LLM 요청 후
- 사용자가 입력한 질문이나 명령 (멀티모달 지원)
- 추가 구현 인터페이스: Message
모든 메시지는 Message 라는 공통 구격을 따르며, 이는 시스템 내에서 메시지를 일관되게 처리할 수 있도록 한다. Message 인터페이스는 다음과 같다.
- text: 메시지의 실제 텍스트 내용
- metadata: 추가 정보를 담는 Map 객체 (Map<String, Object>)
- messageType: 메시지 유형 (SYSTEM, USER, ASSISTANT, TOOL)
텍스트 외에 이미지, 오디오 등 다양한 데이터릴 처리해야 하는 UserMessage와 AssistantMessage는 별도의 MediaContent 인터페이스를 구현하여 확장성을 확보한다(멀티모달 지원).
데이터 흐름은 다음과 같다.
- 입력: 시스템 지침(System)과 사용자 질문(User)이 먼저 구성
- 처리: LLM이 이를 해석하여 답변(Assistant)을 내놓거나 필요시 도구를 호출
- 피드백: 도구 호출 결과(ToolResponse)가 발생하면 이를 바탕으로 최종 응답이 완성
댓글남기기