Spring Boot 통합
Spring Boot 통합
Spring Boot는 자바 진영에서 가장 널리 쓰이는 프레임워크 중 하나라서, LangChain4j도 여기에 맞춰 전용 스타터(starter)를 제공해요. properties 몇 줄이면 언어 모델·임베딩 모델·임베딩 저장소 같은 컴포넌트가 자동으로 만들어지고, 선언적 AI 서비스까지 지원돼요.
LangChain4j는 다음을 위한 Spring Boot 스타터를 제공해요.
- 인기 통합
- 선언적 AI Services
Spring Boot 스타터
Spring Boot 스타터는 properties를 통해 언어 모델, 임베딩 모델, 임베딩 저장소 및 기타 핵심 LangChain4j 컴포넌트를 만들고 구성하는 데 도움을 줘요.
Spring Boot 스타터 중 하나를 쓰려면 해당 의존성을 가져오면 돼요.
Spring Boot 스타터 의존성의 이름 규칙은 다음과 같아요.
langchain4j-{integration-name}-spring-boot4-starter— Spring Boot 4용langchain4j-{integration-name}-spring-boot-starter— Spring Boot 3용
예를 들어 OpenAI(langchain4j-open-ai)의 경우:
Spring Boot 4:
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-open-ai-spring-boot4-starter</artifactId>
<version>1.20.0-beta30</version>
</dependency>
Spring Boot 3:
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-open-ai-spring-boot-starter</artifactId>
<version>1.20.0-beta30</version>
</dependency>
그런 다음 application.properties 파일에서 모델 파라미터를 이렇게 설정할 수 있어요.
langchain4j.open-ai.chat-model.api-key=${OPENAI_API_KEY}
langchain4j.open-ai.chat-model.model-name=gpt-4o
langchain4j.open-ai.chat-model.log-requests=true
langchain4j.open-ai.chat-model.log-responses=true
...
이 경우 OpenAiChatModel(ChatModel의 구현) 인스턴스가 자동으로 생성되고, 필요한 곳에 오토와이어할 수 있어요.
@RestController
public class ChatController {
ChatModel chatModel;
public ChatController(ChatModel chatModel) {
this.chatModel = chatModel;
}
@GetMapping("/chat")
public String model(@RequestParam(value = "message", defaultValue = "Hello") String message) {
return chatModel.chat(message);
}
}
StreamingChatModel 인스턴스가 필요하다면 chat-model 대신 streaming-chat-model properties를 쓰면 돼요.
langchain4j.open-ai.streaming-chat-model.api-key=${OPENAI_API_KEY}
...
선언적 AI Services용 Spring Boot 스타터
LangChain4j는 AI Services, RAG, Tools 등을 자동 구성하는 Spring Boot 스타터도 제공해요.
통합 스타터 중 하나를 이미 가져왔다고 가정하고(위 참고), langchain4j-spring-boot4-starter(Spring Boot 4) 또는 langchain4j-spring-boot-starter(Spring Boot 3)를 가져와요.
Spring Boot 4:
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-spring-boot4-starter</artifactId>
<version>1.20.0-beta30</version>
</dependency>
Spring Boot 3:
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-spring-boot-starter</artifactId>
<version>1.20.0-beta30</version>
</dependency>
이제 AI 서비스 인터페이스를 정의하고 @AiService로 어노테이션하면 돼요.
@AiService
interface Assistant {
@SystemMessage("You are a polite assistant")
String chat(String userMessage);
}
흔한 Spring Boot @Service라고 생각하되, AI 능력이 더해진 버전이라고 보면 돼요.
애플리케이션이 시작되면 LangChain4j 스타터가 클래스패스를 스캔해 @AiService로 어노테이션된 모든 인터페이스를 찾아요. 찾은 AI 서비스 각각에 대해 애플리케이션 컨텍스트에서 사용할 수 있는 모든 LangChain4j 컴포넌트를 사용해 그 인터페이스의 구현을 만들고 빈(bean)으로 등록하므로, 필요한 곳에 오토와이어할 수 있어요.
@RestController
class AssistantController {
@Autowired
Assistant assistant;
@GetMapping("/chat")
public String chat(String message) {
return assistant.chat(message);
}
}
자동 컴포넌트 와이어링
애플리케이션 컨텍스트에 있다면 다음 컴포넌트들이 AI 서비스에 자동으로 와이어링돼요.
ChatModelStreamingChatModelChatMemoryChatMemoryProviderContentRetrieverRetrievalAugmentorToolProvider@Tool로 어노테이션된 모든@Component또는@Service클래스의 모든 메서드
예시:
@Component
public class BookingTools {
private final BookingService bookingService;
public BookingTools(BookingService bookingService) {
this.bookingService = bookingService;
}
@Tool
public Booking getBookingDetails(String bookingNumber, String customerName, String customerSurname) {
return bookingService.getBookingDetails(bookingNumber, customerName, customerSurname);
}
@Tool
public void cancelBooking(String bookingNumber, String customerName, String customerSurname) {
bookingService.cancelBooking(bookingNumber, customerName, customerSurname);
}
}
:::note 애플리케이션 컨텍스트에 같은 타입의 컴포넌트가 여러 개 있으면 앱이 시작에 실패해요. 이때는 아래 설명하는 명시적 와이어링 모드를 쓰면 돼요. :::
명시적 컴포넌트 와이어링
AI 서비스가 여러 개이고 각각에 서로 다른 LangChain4j 컴포넌트를 와이어링하고 싶다면, 명시적 와이어링 모드(@AiService(wiringMode = EXPLICIT))로 사용할 컴포넌트를 지정할 수 있어요.
두 개의 ChatModel을 구성했다고 가정해 볼게요.
# OpenAI
langchain4j.open-ai.chat-model.api-key=${OPENAI_API_KEY}
langchain4j.open-ai.chat-model.model-name=gpt-4o-mini
# Ollama
langchain4j.ollama.chat-model.base-url=http://localhost:11434
langchain4j.ollama.chat-model.model-name=llama3.1
@AiService(wiringMode = EXPLICIT, chatModel = "openAiChatModel")
interface OpenAiAssistant {
@SystemMessage("You are a polite assistant")
String chat(String userMessage);
}
@AiService(wiringMode = EXPLICIT, chatModel = "ollamaChatModel")
interface OllamaAssistant {
@SystemMessage("You are a polite assistant")
String chat(String userMessage);
}
:::note 이 경우 모든 컴포넌트를 명시적으로 지정해야 해요. :::
더 자세한 내용은 여기에서 볼 수 있어요(Spring Boot 4 변형도 동일한 API).
AI 서비스 등록 이벤트 리슨
선언적 방식으로 AI 서비스 개발을 마친 뒤 ApplicationListener<AiServiceRegisteredEvent> 인터페이스를 구현해 AiServiceRegisteredEvent를 리슨할 수 있어요. 이 이벤트는 AI 서비스가 Spring 컨텍스트에 등록될 때 트리거되며, 런타임에 등록된 모든 AI 서비스와 그 도구에 대한 정보를 얻을 수 있게 해줘요. 예시는 다음과 같아요.
@Component
class AiServiceRegisteredEventListener implements ApplicationListener<AiServiceRegisteredEvent> {
@Override
public void onApplicationEvent(AiServiceRegisteredEvent event) {
Class<?> aiServiceClass = event.aiServiceClass();
List<ToolSpecification> toolSpecifications = event.toolSpecifications();
for (int i = 0; i < toolSpecifications.size(); i++) {
System.out.printf("[%s]: [Tool-%s]: %s%n", aiServiceClass.getSimpleName(), i + 1, toolSpecifications.get(i));
}
}
}
Flux
스트리밍할 때 AI 서비스의 반환 타입으로 Flux<String>을 쓸 수 있어요.
@AiService
interface Assistant {
@SystemMessage("You are a polite assistant")
Flux<String> chat(String userMessage);
}
이를 위해 langchain4j-reactor 모듈을 가져와야 해요. 더 자세한 내용은 여기에서 볼 수 있어요.
그 모듈은 논블로킹 모드용 Mono<T>와 Flux<AiServiceStreamingEvent>도 제공하고, starter는 langchain4j.executor.use-spring-task-executor=true로 LangChain4j의 오프로드 작업을 Spring의 자체 task executor를 통해 라우팅할 수 있어서 tracing·MDC·보안 컨텍스트가 비동기 호출을 따라가요.
Observability
ChatModel 또는 StreamingChatModel 빈에 대한 관측성을 활성화하려면 하나 이상의 ChatModelListener 빈을 선언해야 해요.
@Configuration
class MyConfiguration {
@Bean
ChatModelListener chatModelListener() {
return new ChatModelListener() {
private static final Logger log = LoggerFactory.getLogger(ChatModelListener.class);
@Override
public void onRequest(ChatModelRequestContext requestContext) {
log.info("onRequest(): {}", requestContext.chatRequest());
}
@Override
public void onResponse(ChatModelResponseContext responseContext) {
log.info("onResponse(): {}", responseContext.chatResponse());
}
@Override
public void onError(ChatModelErrorContext errorContext) {
log.info("onError(): {}", errorContext.error().getMessage());
}
};
}
}
애플리케이션 컨텍스트의 모든 ChatModelListener 빈은 우리 Spring Boot 스타터 중 하나가 만든 모든 ChatModel·StreamingChatModel 빈에 자동 주입돼요.
Micrometer 메트릭
langchain4j-micrometer-metrics 의존성을 프로젝트에 추가해요.
Maven:
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-micrometer-metrics</artifactId>
<version>1.20.0-beta30</version>
</dependency>
Gradle:
implementation 'dev.langchain4j:langchain4j-micrometer-metrics:1.20.0-beta30'
Micrometer (Actuator) 구성
프로젝트에 필요한 Actuator 의존성도 있어야 해요. 예를 들어 Spring Boot를 쓴다면 pom.xml에 다음 의존성을 추가할 수 있어요.
Maven:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
Gradle:
implementation 'org.springframework.boot:spring-boot-starter-actuator'
properties에서 /metrics Actuator 엔드포인트를 활성화해요.
application.properties:
management.endpoints.web.exposure.include=metrics
application.yaml:
management:
endpoints:
web:
exposure:
include: metrics
MicrometerMetricsChatModelListener 빈 구성
Spring Boot 애플리케이션에서 listener를 빈으로 정의하고 MeterRegistry를 주입할 수 있어요.
import dev.langchain4j.micrometer.metrics.listeners.MicrometerMetricsChatModelListener;
import io.micrometer.core.instrument.MeterRegistry;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MetricsConfig {
@Bean
public MicrometerMetricsChatModelListener listener(MeterRegistry meterRegistry) {
return new MicrometerMetricsChatModelListener(meterRegistry);
}
}
메트릭 보기
애플리케이션의 /actuator/metrics 엔드포인트를 방문해 메트릭을 볼 수 있어요. 예를 들어 localhost:8080에서 애플리케이션을 실행 중이라면 http://localhost:8080/actuator/metrics 를 방문하면 돼요.
토큰 사용 메트릭
토큰 사용 메트릭은 다음에서 볼 수 있어요.
http://localhost:8080/actuator/metrics/gen_ai.client.token.usage
토큰 유형으로 필터링
gen_ai.token.type 태그는 토큰이 입력에 사용됐는지 출력에 사용됐는지 나타내요.
| Token Type | Endpoint |
|---|---|
| Input tokens | /actuator/metrics/gen_ai.client.token.usage?tag=gen_ai.token.type:input |
| Output tokens | /actuator/metrics/gen_ai.client.token.usage?tag=gen_ai.token.type:output |
Note:
gen_ai.client.token.usage메트릭은 히스토그램(DistributionSummary)이에요. 태그 없는 엔드포인트는 모든 토큰 유형·모델·제공자에 걸친 집계 통계(count, total, max)를 보여줘요.
Micrometer Observation API
이는 Micrometer Observation API를 사용해 ChatModelListener를 구현한 것으로, 다음 의존성을 추가하면 Metrics와 Traces를 투명하게 생성할 수 있어요.
Maven:
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-observation</artifactId>
</dependency>
Gradle:
implementation 'dev.langchain4j:langchain4j-observation'
Observation listener는 다음과 같이 인스턴스화해야 해요.
ObservationChatModelListener 빈 구성
@Configuration
public class ObservationConfig {
@Bean
public ObservationChatModelListener listener(ObservationRegistry observationRegistry, MeterRegistry meterRegistry) {
return new ObservationChatModelListener(observationRegistry, meterRegistry);
}
}
이 의존성은 위에서 설명한 SpringBoot Actuator 구성이 필요해요.
SpringBoot 애플리케이션에서 추가 관측성 요구사항은 다음을 따르세요. Building Your First Observed Application
langchain4j-observation 라이브러리에 대한 자세한 내용은 Observability 문서를 확인하세요.
테스팅 (Testing)
지원 버전
LangChain4j Spring Boot 통합은 Java 17을 요구하며 다음을 모두 지원해요.
- Spring Boot 4 (4.0+) —
-spring-boot4-starter접미사 스타터 사용 - Spring Boot 3 (3.5+) —
-spring-boot-starter접미사 스타터 사용, Spring Boot OSS 지원 정책과 일치
두 계열은 함께 릴리스되고 같은 버전 번호를 공유해요. 프로젝트의 Spring Boot 버전과 맞는 스타터 세트를 고르면 돼요.
예제 (Examples)
- ChatModel API를 쓰는 저수준 Spring Boot 예제
- AI Services를 쓰는 고수준 Spring Boot 예제
- Spring Boot를 쓰는 customer support agent 예제
더 알아보기
- 모델 파라미터 — properties에서 파라미터 설정
- 로깅 — Spring Boot 로깅 설정
- 시작하기 (Maven/설정)