Foundry Local Spring Boot 튜토리얼
April 15, 2026 · View on GitHub
목차
사전 준비 사항
이 튜토리얼을 시작하기 전에 다음이 준비되어 있는지 확인하세요:
- 시스템에 Java 21 이상이 설치되어 있어야 합니다.
- 프로젝트 빌드를 위한 Maven 3.6+
- Foundry Local이 설치되고 실행 중이어야 합니다.
Foundry Local 설치:
참고: Foundry Local CLI는 Windows와 macOS에서만 사용할 수 있습니다. Linux는 Foundry Local SDKs (Python, JavaScript, C#, Rust)를 통해 지원됩니다.
# 윈도우
winget install Microsoft.FoundryLocal
# 맥OS
brew tap microsoft/foundrylocal
brew install foundrylocal
설치 확인:
foundry --version
프로젝트 개요
이 프로젝트는 네 가지 주요 구성요소로 이루어져 있습니다:
- Application.java - 주요 Spring Boot 애플리케이션 진입점
- FoundryLocalService.java - AI 통신을 처리하는 서비스 계층
- application.properties - Foundry Local 연결 구성
- pom.xml - Maven 의존성과 프로젝트 설정
코드 이해하기
1. 애플리케이션 설정 (application.properties)
파일: src/main/resources/application.properties
foundry.local.base-url=http://localhost:5273/v1
# foundry.local.model is auto-detected from Foundry Local. Set it here to override:
# foundry.local.model=Phi-4-mini-instruct-cuda-gpu:5
역할:
- base-url: Foundry Local이 실행 중인 위치를 지정하며, OpenAI API 호환성을 위해
/v1경로를 포함합니다. 기본 포트는5273입니다. 포트가 다르면foundry service status명령으로 확인하세요. - model (선택 사항): 텍스트 생성을 위한 AI 모델 이름을 지정합니다. 기본적으로 애플리케이션이 Foundry Local의
/v1/models엔드포인트를 시작 시 쿼리하여 모델을 자동 감지하므로 설정할 필요가 없습니다. 필요 시 명시적으로 지정할 수 있습니다.
핵심 개념: Spring Boot는 이 속성들을 자동으로 로드하여 @Value 어노테이션을 통해 애플리케이션에서 사용할 수 있게 합니다.
2. 메인 애플리케이션 클래스 (Application.java)
파일: src/main/java/com/example/Application.java
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication app = new SpringApplication(Application.class);
app.setWebApplicationType(WebApplicationType.NONE); // 웹 서버 불필요
app.run(args);
}
역할:
@SpringBootApplication은 Spring Boot 자동 구성을 활성화합니다.WebApplicationType.NONE은 이 애플리케이션이 웹 서버가 아닌 커맨드라인 앱임을 Spring에 알려줍니다.- main 메서드는 Spring 애플리케이션을 시작합니다.
데모 실행자:
@Bean
public CommandLineRunner foundryLocalRunner(FoundryLocalService foundryLocalService) {
return args -> {
System.out.println("=== Foundry Local Demo ===");
System.out.println("Calling Foundry Local service...");
String testMessage = "Hello! Can you tell me what you are and what model you're running?";
System.out.println("Sending message: " + testMessage);
String response = foundryLocalService.chat(testMessage);
System.out.println("Response from Foundry Local:");
System.out.println(response);
System.out.println("=========================");
};
}
역할:
@Bean은 Spring이 관리하는 컴포넌트를 생성합니다.CommandLineRunner는 Spring Boot 시작 후 코드를 실행합니다.foundryLocalService는 Spring에 의해 자동 주입(의존성 주입)됩니다.- AI에 테스트 메시지를 보내고 그 응답을 출력합니다.
3. AI 서비스 계층 (FoundryLocalService.java)
파일: src/main/java/com/example/FoundryLocalService.java
구성 주입:
@Service
public class FoundryLocalService {
@Value("${foundry.local.base-url:http://localhost:5273/v1}")
private String baseUrl;
@Value("${foundry.local.model:}")
private String model; // 비어 있으면 자동 감지됨
역할:
@Service는 이 클래스가 비즈니스 로직 제공자임을 Spring에 알립니다.@Value는 application.properties에서 설정 값을 주입합니다.- 모델은 기본값이 비어 있으며, 이는 Foundry Local에서 시작 시 자동 감지를 트리거합니다. 즉, Foundry Local에 로드된 어떤 모델이라도 별도 설정 없이 작동합니다.
클라이언트 초기화:
@PostConstruct
public void init() {
// 명시적으로 구성되지 않은 경우 Foundry Local에서 모델을 자동 감지합니다
if (model == null || model.isBlank()) {
model = detectModel();
}
this.openAIClient = OpenAIOkHttpClient.builder()
.baseUrl(baseUrl) // 기본 URL에 구성에서 /v1이 이미 포함되어 있습니다
.apiKey("not-needed") // 로컬 서버는 실제 API 키가 필요하지 않습니다
.build();
}
역할:
@PostConstruct는 Spring이 서비스를 생성한 후 이 메서드를 실행합니다.- 모델이 설정되지 않으면 Foundry Local의
/v1/models엔드포인트를 쿼리하여 첫 번째 로드된 모델을 선택합니다. - 로컬 Foundry Local 인스턴스를 가리키는 OpenAI 클라이언트를 만듭니다.
application.properties의 base URL은 이미 OpenAI API 호환을 위해/v1을 포함합니다.- 인증이 필요 없는 로컬 개발 환경이므로 API 키는 "not-needed"로 설정합니다.
채팅 메서드:
public String chat(String message) {
try {
ChatCompletionCreateParams params = ChatCompletionCreateParams.builder()
.model(model) // 사용할 AI 모델
.addUserMessage(message) // 당신의 질문/프롬프트
.maxCompletionTokens(150) // 응답 길이 제한
.temperature(0.7) // 창의성 조절 (0.0-1.0)
.build();
ChatCompletion chatCompletion = openAIClient.chat().completions().create(params);
// API 결과에서 AI의 응답 추출
if (chatCompletion.choices() != null && !chatCompletion.choices().isEmpty()) {
return chatCompletion.choices().get(0).message().content().orElse("No response found");
}
return "No response content found";
} catch (Exception e) {
throw new RuntimeException("Error calling chat completion: " + e.getMessage(), e);
}
}
역할:
- ChatCompletionCreateParams: AI 요청을 설정합니다.
model: 사용할 AI 모델 지정 (반드시foundry model list에서 정확한 ID와 일치해야 함)addUserMessage: 대화에 사용자 메시지를 추가maxCompletionTokens: 응답 길이 제한 (리소스 절약용)temperature: 생성의 무작위성 제어 (0.0 = 결정적, 1.0 = 창의적)
- API 호출: 요청을 Foundry Local에 전송
- 응답 처리: AI의 텍스트 응답을 안전하게 추출
- 예외 처리: 에러 발생 시 도움말 메시지와 함께 예외 래핑
4. 프로젝트 의존성 (pom.xml)
주요 의존성:
<!-- Spring Boot - Application framework -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>${spring-boot.version}</version>
</dependency>
<!-- OpenAI Java SDK - For AI API calls -->
<dependency>
<groupId>com.openai</groupId>
<artifactId>openai-java</artifactId>
<version>2.12.0</version>
</dependency>
<!-- Jackson - JSON processing -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.17.0</version>
</dependency>
역할:
- spring-boot-starter: 기본 Spring Boot 기능 제공
- openai-java: OpenAI 공식 Java SDK로 API 통신 지원
- jackson-databind: API 호출 시 JSON 직렬화/역직렬화 처리
전체 작동 방식
애플리케이션을 실행할 때 동작 흐름은 다음과 같습니다:
- 시작: Spring Boot가 시작되며
application.properties를 읽음 - 서비스 생성: Spring이
FoundryLocalService를 생성하고 설정 값을 주입 - 모델 감지: 설정된 모델이 없으면 Foundry Local의
/v1/models엔드포인트를 쿼리하여 자동으로 첫 번째 모델을 선택 - 클라이언트 설정:
@PostConstruct가 OpenAI 클라이언트를 초기화하여 Foundry Local에 연결 - 데모 실행:
CommandLineRunner가 시작 후 실행됨 - AI 호출: 데모가
foundryLocalService.chat()메서드를 테스트 메시지로 호출 - API 요청: 서비스가 OpenAI 호환 요청을 만들어 Foundry Local에 전송
- 응답 처리: 서비스가 AI 응답을 추출하여 반환
- 출력: 애플리케이션이 응답을 출력하고 종료
Foundry Local 설정
-
사전 준비 사항 절의 안내를 참조하여 Foundry Local을 설치하세요.
-
서비스 시작 (실행 중이 아니면):
foundry service start -
서비스 상태 확인 및 포트 확인:
foundry service status -
모델 다운로드 및 실행 (첫 실행 시 다운로드 후 캐시):
foundry model run phi-4-mini인터랙티브 채팅 세션이 열립니다.
Ctrl+C로 종료할 수 있으며, 모델은 서비스에 계속 로드됩니다.팁:
foundry model list로 사용 가능한 모든 모델을 확인하세요.phi-4-mini대신 카탈로그의 다른 별칭(예: 작은/빠른 모델인qwen2.5-0.5b)을 사용할 수 있습니다. -
모델이 로드됐는지 확인:
foundry service ps -
필요 시
application.properties업데이트:- 기본
base-url(http://localhost:5273/v1)은 CLI 기본 포트와 일치합니다.foundry service status에서 다른 포트를 확인하면 업데이트하세요. - 모델은 시작 시 자동 감지되므로 별도의 설정이 필요 없습니다.
foundry.local.base-url=http://localhost:5273/v1 # Model is auto-detected. Uncomment below to override: # foundry.local.model=Phi-4-mini-instruct-cuda-gpu:5 - 기본
애플리케이션 실행
1단계: Foundry Local에 모델이 로드되어 있는지 확인
foundry service ps
모델이 없으면 로드:
foundry model run phi-4-mini
2단계: 애플리케이션 빌드 및 실행
다른 터미널에서:
cd 04-PracticalSamples/foundrylocal
mvn spring-boot:run
또는 JAR로 빌드 및 실행:
mvn clean package
java -jar target/foundry-local-spring-boot-0.0.1-SNAPSHOT.jar
예상 출력
=== Foundry Local Demo ===
Calling Foundry Local service...
Sending message: Hello! Can you tell me what you are and what model you're running?
Response from Foundry Local:
Hello! I'm Phi, an AI developed by Microsoft. I can assist with a wide variety of
tasks including answering questions, helping with analysis, creative writing, coding,
and general conversation. How can I help you today?
=========================
다음 단계
추가 예제는 Chapter 04: Practical samples를 참고하세요.
문제 해결
일반 문제
"Connection refused" 또는 "Service unavailable" 에러
- 서비스 상태 확인:
foundry service status - 필요 시 재시작:
foundry service restart application.properties의 포트가foundry service status출력과 일치하는지 확인- URL이
/v1로 끝나는지 확인:http://localhost:5273/v1
시작 시 "모델을 찾을 수 없음"
- 애플리케이션이 자동으로 모델을 감지합니다. 모델이 적어도 하나 로드됐는지 확인:
foundry service ps - 모델이 없다면:
foundry model run phi-4-mini실행 application.properties에서 모델명을 오버라이드했다면,foundry model list와 일치하는지 확인
"400 Bad Request" 에러
- 기본 URL에
/v1이 포함되었는지 확인:http://localhost:5273/v1 - 코드에서
maxCompletionTokens()를 사용했는지 확인 (더 이상 쓰이지 않는maxTokens()사용하지 말 것)
Maven 컴파일 에러
- Java 21 이상 버전인지 확인:
java -version - 클린 빌드 수행:
mvn clean compile - 의존성 다운로드를 위한 인터넷 연결 상태 확인
서비스 연결 문제
Request to local service failed에러 시:foundry service restart실행- 로드된 모델 확인:
foundry service ps - 서비스 로그 보기:
foundry service diag
면책 조항:
이 문서는 AI 번역 서비스 Co-op Translator를 이용하여 번역되었습니다. 정확성을 위해 노력하였으나, 자동 번역에는 오류나 부정확성이 포함될 수 있음을 양지하시기 바랍니다. 원문은 해당 언어로 된 원본 문서를 권위 있는 출처로 간주해야 합니다. 중요한 정보의 경우 전문적인 인간 번역을 권장합니다. 본 번역 사용으로 인해 발생하는 오해나 오해의 소지에 대해 당사는 책임을 지지 않습니다.