Spring AI - 모델, 메세지, 프롬프트

김소희·2025년 11월 14일

AI 애플리케이션을 개발할 때,
어떤 방식으로 모델에 입력 데이터를 전달하고, 생성된 결과를 사용자에게 보여줄 것인지는 많은 개발자들이 공통으로 고민하는 부분이다.

파이썬 기반의 AI 애플리케이션에서는 보통 LangChain(랭체인) 같은 프레임워크를 사용한다.
LangChain은 프롬프트 구성 → 모델 호출 → 후처리 과정이 하나의 흐름(Chain)으로 자연스럽게 이어지도록 설계되어 있어, 복잡한 로직을 단계적으로 연결할 수 있다는 장점이 있다.

스프링 AI(SPRING AI) 역시 내부 구현 언어나 실행 환경은 다르지만,
제공하는 기능의 방향성과 개발 경험은 LangChain과 거의 유사하다.

스프링 AI는 OpenAI, HuggingFace 등 다양한 LLM 모델을 자동으로 연결해주고,
엔터프라이즈 환경에서 자주 사용하는 벡터 스토어(Vector Store) 와의 연동을 기본 지원한다.
또한 대화 기억 관리 방식 선택, RAG 구현, 도구 호출, MCP 서버 개발 등
AI 서비스를 구축할 때 필요한 기능들을 폭넓게 제공한다.

파이썬이 익숙한 개발자라면 굳이 기존 파이썬 애플리케이션을 스프링으로 옮길 필요는 없다.
하지만 자바·스프링 생태계에서 개발해 온 사람들에게는
스프링 AI의 등장이 매우 반가운 변화
임은 분명하다.


Spring AI - Model API

AI 모델의 종류는 지금 이 순간에도 빠르게 늘어나고 있다.
우리는 ChatGPT를 사용할 수도 있고, Google Gemini나 Anthropic Claude 를 선택할 수도 있다.

하지만 문제는 각 AI 제공업체마다 API 호출 방식과 설정 코드가 모두 다르다는 것이다.
서비스를 만들 때 여러 모델을 함께 쓰거나 다른 모델로 갈아타야 한다면,
매번 새로운 SDK 문서를 다시 읽고 코드 구조를 수정해야 하는 불편이 생긴다.

Spring AI는 이러한 문제를 해결하기 위해
같은 종류의 모델들은 동일한 방식으로 사용할 수 있도록 통합된 API를 제공한다.

또한 Spring의 철학답게,
모델 호출을 대부분 인터페이스 기반으로 설계해 두어
AI 공급자를 변경하더라도 코드 전체를 고칠 필요는 없다.
최소한의 구성만 수정하면 다른 모델로 자연스럽게 교체가 가능하다.


Spring AI가 제공하는 주요 Model API

API기능
ChatModel텍스트·이미지 입력 → 텍스트 생성
ImageModel텍스트 → 이미지 생성
SpeechModel텍스트 ↔ 음성 변환
EmbeddingModel텍스트 → 벡터 변환

ChatModel 인터페이스

ChatModel은 StreamChatModel을 상속받는 인터페이스다.
텍스트나 이미지를 입력받아 텍스트를 생성한다.
ChatModel은 메시지를 처리하는 추상화된 대화 엔진 이다.

  • call() 은 매개변수로 주어진 문자열, 메세지, 프롬프트를 이용하여 LLM에게 동기로 요청을 보낸다. 응답을 받으면 String이나 ChatResponse로 변환하여 반환한다.
  • stream()은 LLM에게 비동기로 요청을 보낼 때 쓰인다.

메시지 API 구조 정리

Message API는 ChatModel이 대화를 표준화된 방식으로 처리할 수 있도록 제공되는
통합 메시지 데이터 구조이다.

메세지란 LLM에게 전달할 대화 단위 객체로
단순한 문자열이 아닌 “역할(role) + 내용(content)” 구조로 메시지를 정의하는 방식을 말한다.

ChatModel은 입력으로 List<Message> 를 받으며
(SystemMessage, UserMessage, AssistantMessage, ToolMessage …)
이 메시지들을 하나의 대화 컨텍스트로 조합한 뒤 LLM에 요청을 전송한다.
모델의 응답은 AssistantMessage 또는 메시지 스트림(Streaming Response) 형태로 반환된다.

LLM과 주고받는 모든 메시지는 공통적으로
Message 인터페이스를 구현해 일관된 형태로 구성되며,
이미지·음성·파일 등의 멀티모달 입력이 필요할 경우
추가적으로 MediaContext 를 함께 구현하여 전달할 수 있다.


메시지 타입별 역할

클래스역할(role)설명
SystemMessagesystem모델에게 행동 지침, 규칙, 컨텍스트를 제공하는 설정 메시지.
UserMessageuser사용자 입력. 질문, 요청, 명령 등 사람이 작성한 모든 내용.
AssistantMessageassistant모델이 생성한 응답. 텍스트, 코드, 설명 등.
FunctionMessagefunction함수 호출 기능 사용 시, 함수 실행 결과를 모델에게 다시 전달하는 용도.
ToolMessagetool외부 도구 실행 결과를 전달하는 메시지.

예제 코드로 살펴보기

package com.example.demo.controller;

import java.text.MessageFormat;
import java.util.List;

import org.springframework.ai.chat.messages.AssistantMessage;
import org.springframework.ai.chat.messages.SystemMessage;
import org.springframework.ai.chat.messages.UserMessage;
import org.springframework.ai.chat.prompt.ChatOptions;
import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.ai.openai.OpenAiChatModel;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;

import com.example.demo.model.Product;

@Controller
public class MarketingController {

    @Autowired
    private OpenAiChatModel chatModel;

    @GetMapping("/marketing")
    public String getMarketing() {
        return "marketing_request";
    }

    @PostMapping("/marketing")
    public String postMarketing(@ModelAttribute Product product, Model model) {

        // ===== 시스템 메세지 =====
        var systemMessage = new SystemMessage("""
                너는 전문 마케팅 카피라이터야.
                입력된 제품 정보를 기반으로 매력적인 광고 문구를 만들어줘.
                표현은 자연스럽고 구매욕을 높이는 방식으로 작성해줘.
                """);

        // ===== 사용자 메세지 =====
        var userMessage = new UserMessage(MessageFormat.format("""
                아래 제품 정보를 기반으로 마케팅 카피를 생성해줘.

                - 제품명 : {0}
                - 가격 : {1}
                - 구매링크 : {2}
                - 제품의 특징 : {3}
                """,
            product.getName(),
            product.getPrice(),
            product.getLink(),
            product.getFeatures()
        ));

        // ===== 옵션 설정 (2000토큰, temperature 0.7) =====
        ChatOptions options = ChatOptions.builder()
                .maxTokens(2000)
                .temperature(0.7)
                .build();

        // ===== Prompt 생성 =====
        Prompt prompt = new Prompt(
                List.of(systemMessage, userMessage),
                options
        );

        // ===== 모델 호출 =====
        AssistantMessage result = chatModel.call(prompt).getResult().getOutput();

        model.addAttribute("marketingResult", result);

        return "marketing_response";
    }
}


Spring AI 프롬프트(Prompt)

Spring AI에서 프롬프트는 LLM에 사용자가 원하는 작업을 구체적으로 지시하는 명령문으로
이를 구조화한 객체가 Prompt 클래스다.

프롬프트 안에는 모델의 행동을 조절하는 대화 옵션(ChatOptions)이 포함되어 있고, 필요하면 프롬프트 템플릿을 통해 매개 변수를 동적으로 넣거나 이전 대화 내용을 함께 전달해 더 자연스러운 응답을 만들 수도 있다.

프롬프트를 설계할 때는 모델에게 맡길 역할을 명확히 정해주고, 요청의 목적이 한눈에 들어오도록 직관적인 문장으로 지시하는 것이 핵심이다. 이렇게 잘 다듬어진 프롬프트는 Prompt → ChatModel → 모델 응답의 흐름을 거치며 처리되고, 그 결과 모델은 사용자의 의도에 훨씬 더 가까운 답변을 만들 것이다.


프롬프트 종류

종류설명대표 사용 예
Prompt모델에 전달되는 기본 요청 객체. 단일 텍스트 또는 메시지 리스트 입력"Hello?"
PromptTemplate프롬프트 내부에 변수를 바인딩하는 템플릿"오늘 {city}의 날씨는?"
SystemPrompt시스템(Role=system) 지침을 템플릿 형태로 구성"너는 여행 가이드야"
UserPrompt사용자(User) 메시지를 템플릿으로 구성"서울 맛집 추천해줘"
ChatPrompt여러 Role(System/User/Assistant) 기반의 대화형 프롬프트AI 대화 히스토리 포함
PromptTemplateResource.st외부 템플릿 파일을 불러와 사용하는 프롬프트classpath:/prompts/summary.st

대화 옵션 (ChatOptions)

Prompt와 함께 사용되는 옵션 객체는,
모델 종류(OpenAI, Gemini, Claude 등)에 관계없이 적용할 수 있는 공통 규격의 표준 옵션을 제공한다.
물론 각 업체 모델마다 지원하는 추가 옵션들이 더 있지만,
이 표준 옵션만으로도 출력 길이 조절, 창의성 제어, 모델 선택 등 대부분의 핵심 기능을 충분히 다룰 수 있다.

package org.springframework.ai.model;

public interface ChatOptions extends ModelOptions {

    // 응답 최대 길이 (토큰)
    Integer getMaxTokens();

    // 출력 창의 다양성(창의성). 0.0 ~ 1.0
    Double getTemperature();

    // Top-p nucleus sampling
    Double getTopP();

    // 사용할 모델 (gpt-4o, gemini-pro 등)
    String getModel();

    // 스트리밍 여부
    Boolean getStream();

    // stop sequences
    List<String> getStopSequences();

    // 반복 방지(repetition penalty)
    Double getRepetitionPenalty();
}

주요 옵션 설명

옵션설명
maxTokens모델이 생성할 최대 토큰 수 (출력 길이 제한)
temperature창의성·랜덤성 조절 (0은 결정적, 1은 창의적)
topPnucleus sampling. 상위 확률 p% 안에서만 샘플링
model사용할 LLM 모델 ID. ex) "gpt-4o", "gemini-pro"
stream스트리밍 응답 사용 여부
stopSequences생성 중단할 문자열 패턴들
repetitionPenalty반복 생성 억제

프롬프트 전체 구조 요약

[SystemMessage]    ┐
[UserMessage]      │  ==(List<Message>)==>  Prompt + ChatOptions -> ChatModel
[AssistantMessage] │
[ToolMessage]      ┘

Prompt:
  - messages
  - chatOptions (maxTokens, temperature, model ...)

참고자료

기본 프로젝트 세팅 : spring AI 연동 & 세팅 방법
도서 - 이것이 스프링AI다
공식문서 - 스프링 AI

profile
개발자 소희의 노트

0개의 댓글