Spring Boot 4.0 핵심 변경점 정리 — Java 25 지원부터 API 버저닝까지
2025년 11월, Spring Boot 4.0이 정식 출시됐다. 단순한 마이너 업데이트가 아니라 Spring Boot의 다음 세대를 여는 메이저 릴리즈다. Spring Framework 7과 Jakarta EE 11 위에 새로 올라섰고, 코드베이스 자체가 재구성됐다. 3.x를 잘 쓰고 있다면 굳이 지금 올려야 하나 고민될 수도 있는데, 결론부터 말하면 지금 당장 옮길 필요는 없지만, 신규 프로젝트라면 4.x로 시작하는 게 합리적이다.
이 글에서는 실무 관점에서 가장 중요한 변경점만 추려서 정리한다.
한눈에 보는 핵심 변경점
- Spring Framework 7 / Jakarta EE 11 기반으로 전환
- Java 25에 대한 1급 지원, 단 Java 17 호환은 유지
- 거대한 auto-configure JAR을 작은 단위 모듈로 분해
- JSpecify 기반 null 안전성을 표준으로 채택
- API 버저닝 내장 지원 (
@GetMapping(version = "1.0")) - 인터페이스로 HTTP 클라이언트를 만드는 HTTP Service Clients
- Jackson 3 기본 채택 (패키지 경로 변경)
- Gradle 9 빌드 지원
- GraalVM 25+ 네이티브 이미지 요구사항 상향
출시 배경 — 왜 4.0인가
Spring Boot 3.x는 2022년 말 출시된 이후 약 3년 동안 안정적인 LTS 라인으로 쓰였다. 그동안 Java는 17 → 21 → 25로 두 번의 LTS를 거쳤고, Jakarta EE도 10에서 11로 올라갔다. 무엇보다 Spring Framework 7이 등장하면서, Boot 쪽도 그에 맞게 베이스라인을 끌어올릴 시점이 됐다.
Spring 팀이 이번 릴리즈에서 강조하는 키워드는 두 개다. 모듈화와 null 안전성. 둘 다 *"이미 동작하는 앱"* 보다는 *"앞으로 만들어질 앱"* 을 위한 변화에 가깝다. 즉, 4.0은 화려한 신기능이라기보다 앞으로 5년치 토대를 다시 까는 작업이라고 보는 편이 정확하다.
1. 코드베이스 모듈화 — 거대한 가방을 여러 개의 작은 가방으로
3.x 시절에는 spring-boot-autoconfigure라는 거대한 JAR 하나가 거의 모든 자동 설정을 들고 있었다. WebMVC만 쓰는 프로젝트에서도 LDAP, Neo4j, Quartz 같은 자동 설정 클래스가 클래스패스에 함께 끌려왔다.
Spring Boot 4.0은 이 구조를 깨고, 각 기술별로 작고 집중된 JAR로 쪼갰다. 예를 들어 spring-boot-starter-webmvc를 추가하면 WebMVC 관련 자동 설정만 따라온다. 그 결과 다음과 같은 효과가 있다.
- 시작 시간 단축: 클래스패스 스캔 대상이 줄어든다
- 메모리 사용 감소: 불필요한 자동 설정이 안 올라온다
- 디버깅 편의성: 어디서 어떤 자동 설정이 들어왔는지 추적이 쉬워진다
다만 모듈이 잘게 쪼개진 만큼, starter POM을 쓰지 않고 직접 의존성을 관리하던 프로젝트는 의존성 누락 이슈가 발생할 수 있다. 마이그레이션 가이드에서도 이 부분을 가장 먼저 강조한다.
2. Java 25 1급 지원, Java 17 호환 유지
Spring Boot 4.0의 최소 요구 Java 버전은 여전히 Java 17이다. 다만 권장은 Java 25 LTS다.
Spring Boot 4.0 requires Java 17 or newer, with first-class support for Java 25.
여기서 "1급 지원(first-class support)"이 의미하는 바는, 단순히 Java 25에서 동작한다는 게 아니라 Virtual Threads, Pattern Matching, Sequenced Collections, 향상된 GC 같은 최신 JVM 기능을 프레임워크 차원에서 적극 활용한다는 뜻이다.
네이티브 이미지를 쓰려면 이야기가 좀 다르다. GraalVM 25 이상이 필요하다. 이전 GraalVM 23/24에서 빌드되던 네이티브 이미지가 그대로 빌드되지 않을 수 있으니, 네이티브를 쓰는 팀은 빌드 파이프라인을 먼저 점검해야 한다.
3. JSpecify로 표준화된 null 안전성
이번 릴리즈에서 가장 조용하지만 가장 영향력이 큰 변화다.
기존 Spring 코드에서 null 처리는 사실상 컨벤션에 의존했다. @Nullable 같은 애노테이션이 있긴 했지만, 어디 패키지의 어떤 애노테이션을 쓰느냐가 라이브러리마다 달랐다(Spring, JetBrains, Checker Framework, FindBugs…). IDE는 이걸 어찌어찌 통합해서 표시해줬지만, 일관성은 부족했다.
Spring Boot 4.0은 JSpecify를 표준 null 안전성 라이브러리로 채택했다. JSpecify는 Google, JetBrains, Spring 팀이 함께 합의한 일종의 표준 신호 체계다. 핵심 애노테이션은 다음과 같다.
@Nullable— 이 값은 null일 수 있다@NonNull— 이 값은 절대 null이 아니다@NullMarked— 이 패키지/클래스의 모든 참조는 기본 non-null이다
package-info.java에 @NullMarked를 한 번만 붙이면 패키지 안의 모든 참조 타입이 기본 non-null로 간주되고, null이 들어올 수 있는 곳만 @Nullable로 표시하면 된다. 코드 가독성이 명확해지고, IntelliJ나 NullAway 같은 정적 분석 도구가 빌드 단계에서 더 잘 잡아낸다.
// package-info.java
@NullMarked
package com.kraft.member;
import org.jspecify.annotations.NullMarked;
public Member findById(Long id) { ... } // 절대 null 아님
public @Nullable Member findByEmail(String email) { ... } // null 가능
기존 코드에 즉시 영향을 주진 않지만, 새로 작성하는 코드에는 처음부터 적용하는 게 좋다.
4. API 버저닝 — 이제 컨트롤러 한 줄로 처리
API 버저닝은 그동안 모든 팀이 각자의 방식으로 고생하던 영역이었다. URL 경로(/v1/...)에 박아 넣거나, 커스텀 헤더로 분기하거나, 미디어 타입으로 분기하거나. 어느 방식을 택하든 컨트롤러를 직접 갈라야 했고, 전략을 바꾸면 모든 컨트롤러를 다시 손대야 했다.
Spring Boot 4.0에서는 @RequestMapping 계열 애노테이션에 version 속성이 추가됐다.
@RestController
@RequestMapping("/api/posts")
public class PostController {
@GetMapping(version = "1.0")
public PostV1Response getPostsV1() { ... }
@GetMapping(version = "2.0")
public PostV2Response getPostsV2() { ... }
}
버전 분기 전략(URL, 헤더, 미디어 타입)은 설정에서 한 번만 정의하면 되고, 컨트롤러는 버전 번호만 신경 쓰면 된다. 전략을 나중에 바꿔도 컨트롤러 코드는 그대로 둘 수 있다는 점이 핵심이다.
5. HTTP Service Clients — 인터페이스만 선언하면 끝
외부 API를 호출할 때 RestTemplate이나 WebClient로 매번 코드를 짜는 대신, 인터페이스만 선언하고 구현체를 자동 생성하는 방식이 정식 자동 설정으로 들어왔다.
@HttpExchange(url = "https://api.example.com")
public interface WeatherClient {
@GetExchange("/weather/{city}")
WeatherResponse getWeather(@PathVariable String city);
@PostExchange("/alerts")
AlertResponse createAlert(@RequestBody AlertRequest request);
}
Feign이나 Retrofit을 써 본 사람이라면 친숙할 것이다. 차이는 Spring 자체에 통합됐다는 점이다. 별도 라이브러리 없이 @HttpExchange만 붙이면 Spring Boot가 알아서 구현체를 만들어 빈으로 등록한다. 4.x의 Spring Cloud Commons 5.0에서는 여기에 Circuit Breaker, 로드밸런싱(lb:// 스킴) 같은 기능까지 선언적으로 얹을 수 있다.
마이크로서비스 환경이 아니더라도, 외부 API를 호출하는 곳이 많은 프로젝트라면 코드량이 눈에 띄게 줄어든다.
6. Jackson 3 — 패키지 경로가 바뀐다
Spring Boot 4.0은 Jackson 3을 기본 JSON 라이브러리로 채택했다. 가장 눈에 띄는 변경은 패키지/그룹 ID다.
com.fasterxml.jackson.*→tools.jackson.*로 이동- 단,
jackson-annotations모듈은 호환성 때문에com.fasterxml.jackson.core그룹 ID와com.fasterxml.jackson.annotation패키지를 유지
직접 ObjectMapper를 import해서 쓰는 코드가 있다면 패키지 경로를 바꿔야 한다. 다만 Jackson 2를 요구하는 외부 라이브러리도 여전히 많기 때문에, Jackson 2와 3을 한 프로젝트에서 공존시킬 수 있도록 의존성 관리는 계속 제공된다.
그 외 주목할 변화
위에 적은 6가지 외에도 실무에서 한 번씩 만나게 되는 변경이 많다.
- OpenTelemetry Starter 신설:
spring-boot-starter-opentelemetry추가만으로 OTLP 메트릭/트레이스를 내보낼 수 있다 - Gradle 9 지원: Gradle 8.14 이상이면 둘 다 지원
- Kotlin 2.2+ 요구: Kotlin 프로젝트는 빌드 환경부터 점검 필요
- 클래식 uber-jar 로더 제거: 빌드 스크립트에서 관련 설정을 떼야 한다
- Spring Retry 의존성 제거: 재시도 로직은 spring-core의 새 retry API로 이동
- Testcontainers 모듈 prefix 정리: 모든 모듈이
testcontainers-접두어로 통일 - SSL 인증서 만료 모니터링 강화:
expiringChains항목 추가로 만료 임박 인증서를 health 응답에서 분리해 보여줌
3.x → 4.x 업그레이드, 무엇을 점검해야 하나
기존 프로젝트를 올리려면 다음 순서로 접근하는 게 안전하다.
- 3.5로 먼저 올린다: 3.x 안에서 deprecated 된 API를 모두 정리한 뒤 4.x로 점프
- Java 17 이상인지 확인: 11이나 8을 쓰고 있다면 자바 마이그레이션이 선행
- starter POM 사용 여부 점검: 직접 의존성 관리를 하고 있다면 누락 모듈 식별이 가장 먼저
- Jackson 사용처 점검:
com.fasterxml.jackson.*직접 import 여부, 커스텀 직렬화 코드 확인 - 네이티브 이미지 쓰는 경우 GraalVM 25로 업그레이드
- JSpecify 기반 정적 분석 도입 검토: 즉시 적용은 부담스러우면 신규 패키지부터
운영 중인 서비스를 무조건 빨리 올릴 이유는 없다. 3.x도 한동안 유지보수가 계속될 예정이고, 4.0의 진가는 신규 코드를 쓸 때 더 잘 드러난다.
마무리 — 4.0을 어떻게 받아들여야 할까
Spring Boot 4.0은 눈에 확 띄는 신기능 보다는 앞으로 5년의 토대를 다시 까는 릴리즈에 가깝다. 모듈화로 슬림해진 런타임, JSpecify로 표준화된 null 안전성, 인터페이스 기반 HTTP 클라이언트, 내장 API 버저닝 — 이 네 가지만으로도 신규 프로젝트라면 4.x로 시작할 명분이 충분하다.
반면 운영 중인 3.x 서비스는 서두를 필요가 없다. 3.5에서 deprecated 정리부터 차근차근 하면서, 분기점이 잡힐 때 옮기면 된다. 진짜로 챙겨야 할 건 새로 짜는 코드부터 4.x 스타일로 쓰는 것이다. JSpecify 애노테이션, 인터페이스 기반 HTTP 클라이언트, API 버저닝 attribute 같은 건 지금 손에 익혀두면 마이그레이션 시점에 부담이 훨씬 줄어든다.
Spring Boot 4.0은 이미 동작하는 앱을 깨러 온 게 아니라, 앞으로 만들 앱을 더 잘 만들게 하러 온 릴리즈다. 그 관점으로 보면 어디서부터 손을 댈지 답이 보인다.
참고 자료
- Spring Boot 4.0 Release Notes (spring-projects/spring-boot Wiki)
- Spring Boot 4.0 Migration Guide
- Spring 공식 블로그 — Spring Boot 4.0.0 available now (2025.11.20)
- JetBrains Blog — Spring Boot 4: Leaner, Safer Apps and a New Kotlin Baseline
#SpringBoot4 #SpringBoot #Java25 #JSpecify #APIVersioning #HTTPInterface #Jackson3 #SpringFramework7 #JakartaEE11 #백엔드 #Spring업그레이드 #자바개발
'Programming > Spring Boot' 카테고리의 다른 글
| ☕ Maven vs Gradle, 자바 개발자를 위한 빌드툴 완전 정리! (0) | 2022.10.29 |
|---|---|
| ☕ JAR vs WAR vs EAR 차이점 완벽 정리! (Spring Boot 기준) (0) | 2022.10.29 |
