매년 봄에는 스프링 프레임워크와 스프링 부트 소식을 듣기 위해 전 세계 개발자들이 Spring I/O에 모입니다. 올해는 특히 Spring Framework 7.0과 Spring Boot 4.0이라는 주요 업데이트가 예정되어 있어서 더 관심을 받고 있습니다.
약 3년 만에 찾아오는 이번 메이저 버전업은 플랫폼 전반에 걸친 대대적인 변화와 성능 향상, 그리고 개발 경험의 혁신을 약속하고 있습니다. 핵심적인 변경 사항과 기대되는 개선점들을 자세히 살펴보겠습니다.
현재 Spring Framework 6.x는 JDK 17을 기본으로 하고 있으며, Spring Framework 7.0 또한 JDK 17을 최소 지원 버전으로 유지합니다. 아직 실무에서 사용하는 JDK 버전이 많이 낮아서 고려했다고 합니다. 하지만 키노트에서는 JDK 25로의 업그레이드를 강력히 권장했습니다. 왜 그럴까요?
JDK 17 이후로 출시된 JDK 21과 특히 JDK 24에는 수많은 개선 사항이 포함되어 있습니다. JDK 21의 주요 기능들을 간단히 살펴보면:
이 모든 "좋은 점들(goodness)"은 애플리케이션 코드 변경 없이 버전업을 통해서 제공됩니다.
하지만 키노트에서는 "만약 현재 JDK 17을 사용 중이고 약 6개월 후에 메이저 업그레이드를 고려한다면, JDK 21을 건너뛰고 바로 JDK 25로 갈 것을 강력히 추천한다"고 언급했습니다.
JDK 24에 포함된 Project Leiden은 자바 성능 최적화의 새로운 패러다임입니다. JDK 17 사용자에게는 생소하지만, 이는 다음과 같은 혁신적 개선을 제공합니다:
JDK 25는 이러한 개선 사항을 포함한 LTS가 될 것이므로, 최신 자바 플랫폼의 이점을 최대한 활용하기 위해 JDK 25로의 업그레이드는 필수적입니다.
핵심은 "코드 변경 없는 성능 향상"입니다. JDK 17에서 JDK 25로 업그레이드만 해도 애플리케이션이 더 빠르고 효율적으로 작동합니다.
Project Leiden은 자바 애플리케이션의 시작 시간(startup time)과 최고 성능 도달 시간(warm-up time)을 획기적으로 개선하기 위한 JVM 수준의 프로젝트입니다.
전통적으로 자바의 HotSpot JVM은 런타임에 바이트코드를 동적으로 컴파일하며 뛰어난 최고 성능(peak performance)을 제공했지만, 이 과정에서 발생하는 프로파일링 및 컴파일 시간이 시작 시간과 워밍업 시간을 지연시키는 요인이었습니다.
Leiden 프로젝트의 핵심 아이디어는 성능 계산(computation) 작업을 애플리케이션 실행 전(빌드 타임)이나 실행 후(런타임 이후)로 옮기거나 아예 제거하는 것입니다.
현재는 주로 훈련 실행(training runs)을 통한 동적 관찰에 초점을 맞추고 있습니다.
⠀이러한 접근 방식은 기존의 클래스 데이터 공유(CDS, Class Data Sharing) 개념의 발전된 형태입니다.
Leiden 프로젝트는 시작 시간뿐만 아니라 최고 성능 도달 시간도 단축시킵니다.
이러한 개선은 마치 출발선에서 곧바로 전력 질주하는 스포츠카처럼, 애플리케이션이 시작하자마자 최고의 성능을 발휘하도록 돕습니다.
Jackson은 Java 애플리케이션에서 JSON 데이터를 자바 객체로 변환하거나 그 반대로 변환해주는 라이브러리입니다.
Spring Framework에서 Jackson은 핵심 역할을 담당합니다:
오랜 기간 Jackson 2.x 버전을 사용해왔지만, 이제 Jackson 3.0 릴리스를 앞두고 있으며, Spring Framework 7.0 마일스톤에 이미 포함되어 있습니다.
Jackson 3.0은 단순한 업데이트가 아닌 메이저 버전 업그레이드입니다. 이는 다음과 같은 의미 있는 개선을 제공합니다:
Spring Framework 7에서는 Jackson 3를 채택할 예정이며, 사용자들에게도 가능한 한 빨리 Jackson 3으로 마이그레이션할 것을 강력히 권장하고 있습니다.
이는 Jackson 3 라인의 지속적인 발전과 최신 기능 활용을 위해 필수적입니다. 더 중요한 것은 Spring Framework 7과의 완벽한 호환성과 성능 최적화를 위해서는 Jackson 3 업그레이드가 필요하다는 점입니다. 핵심은 "더 빠르고 안전한 JSON 처리"입니다. Jackson 3로 업그레이드하면 기존 애플리케이션의 API 성능이 자연스럽게 향상됩니다.
자바 개발을 하다 보면 누구나 한 번쯤 마주치는 NullPointerException입니다. 객체가 null인 상태에서 메서드를 호출하거나 필드에 접근할 때 발생하는 런타임 에러로, 자바 개발자들의 오랜 골칫거리였습니다.
Spring Framework는 이미 null 값을 기본적으로 허용하지 않는(non-null by default) 자체적인 널 안정성 체계를 가지고 있었지만, 이제 J-Specify로 널 안정성 체계를 전환합니다.
J-Specify는 API 시그니처에서 널 가능성을 선언하기 위한 어노테이션 세트입니다. 쉽게 말해, 메서드의 파라미터나 리턴값이 null이 될 수 있는지 아닌지를 코드로 명확하게 표시하는 도구입니다.
// 기존 방식 - null 가능성이 불분명 public String getName(User user) { ... } // J-Specify 방식 - 명확한 null 가능성 표시 public @Nullable String getName(@NonNull User user) { ... }
기존에도 @NonNull, @Nullable 같은 어노테이션이 있었지만, J-Specify의 큰 장점은 타입 사용 어노테이션(type-use annotations)을 지원한다는 점입니다.
이를 통해 제네릭(Generics)이나 중첩 타입(nested types) 같은 복잡한 구조에서도 널 가능성을 정확하게 선언할 수 있습니다.
// 리스트는 null이 아니지만, 내부 String은 null 가능 List<@Nullable String> names; // 리스트 자체가 null 가능하고, 내부 String도 null 가능 @Nullable List<@Nullable String> optionalNames;
이런 정밀한 표현을 통해 컴파일러가 널 관련 버그를 더욱 확실하게 잡아낼 수 있게 됩니다.
Spring Data JPA는 JPA를 사용하는 개발자에게 혁신적인 편의성을 제공했지만, 성능 최적화는 언제나 중요한 과제였습니다. Spring Framework 7.0과 Spring Data 4.0에서는 이 부분에서 두 가지 주요 혁신을 선보입니다.
Spring Data JPA의 파생 쿼리(Derived Queries)는 메서드 이름만으로 JPA 쿼리를 생성해주는 편리한 기능입니다.
public interface UserRepository extends JpaRepository<User, Long> { // Derived Query 예시 List<User> findByUsername(String username); }
내부적으로 Spring Data는 이러한 파생 쿼리를 구현하기 위해 JPA Criteria API를 많이 활용해왔습니다. 개발자들은 Criteria API가 프로그래밍 방식이므로 가장 효율적일 것이라고 생각하는 경향이 있었습니다.
그러나 벤치마크 결과는 달랐습니다.
Spring Data 팀은 약 15년간 Criteria API를 사용해온 방식에서 벗어나, 파생 쿼리를 Criteria API 대신 문자열 기반 JPQL 쿼리로 렌더링하는 방법을 연구했습니다.
그 결과 다음 Spring 릴리즈 이후에, Spring Data 4.0으로 업그레이드하기만 하면, 기존 파생 쿼리들이 @Query 어노테이션으로 작성된 쿼리와 동일한 성능을 자동으로 얻게 됩니다.
기존 방식에는 한 가지 큰 불편함이 있었습니다. 코드에 문제가 생겼을 때 원인을 찾기가 매우 어려웠다는 점입니다.
개발자가 디버깅(오류 찾기)을 하려고 하면, 실제 데이터베이스 쿼리(명령어)가 어떻게 실행되는지 보기 위해 복잡한 프레임워크 내부 코드들을 하나씩 거쳐야 했습니다. 마치 미로 같은 코드들을 헤매다 보면 정작 중요한 부분을 찾기가 거의 불가능했죠.
AOT 리포지토리의 혁신: Spring Framework 7.0과 Spring Data 4.0에 새로 도입되는 AOT 리포지토리(Ahead of Time Repositories)가 이 문제를 해결해줍니다.
Spring Framework 6에서 도입된 HTTP Exchange 인터페이스는 원격 HTTP 서비스와의 상호작용을 선언적으로 만들어주어 개발의 편의성을 크게 향상시켰습니다.
기존에는 여러 HTTP 서비스 인터페이스를 사용할 경우, 각각에 대해 클라이언트를 구성하고 프록시 팩토리를 통해 빈을 수동으로 등록해야 하는 반복적인 보일러플레이트 코드가 발생했습니다.
예를 들어 GitHub REST API에 접근하기 위해 이슈, 리포지토리, 마일스톤 등 여러 인터페이스를 만들어야 했다면, 각 인터페이스마다 설정이 반복되어 코드가 길어지고 유지보수가 어려워지는 문제가 있었습니다.
Spring Framework 7에서는 이러한 불편함을 해소하기 위해 자동 설정을 도입합니다.
⠀
Spring I/O 2025 키노트에서 가장 흥미로운 소식 중 하나는 바로 Spring AI 1.0 General Availability 릴리스 소식이었습니다.
2년 반의 개발 끝에 마침내 정식 출시된 Spring AI는 자바 개발자들이 생성형 AI 애플리케이션을 쉽게 구축할 수 있도록 돕는 기반 빌딩 블록을 제공합니다.
Spring Framework 7.0과 Spring Boot 4.0의 발표를 보면서 캡슐화와 추상화라는 스프링의 핵심 설계 철학이 얼마나 강력한지 다시 한번 깨달았습니다.
단순히 버전업만 해도 JDK 25의 Project Leiden, Spring Data 4.0의 쿼리 성능 향상, Jackson 3의 최적화 등 모든 혜택을 자동으로 누릴 수 있다는 점이 정말 인상적이었습니다.
개발자는 JVM 최적화나 AOT 컴파일, Criteria API에서 JPQL로의 전환 같은 복잡한 내부 구현을 전혀 알 필요 없이, 프레임워크가 제공하는 단순한 인터페이스만으로도 최신 기술의 모든 이점을 누릴 수 있다는 점이 Spring의 장점이라고 생각합니다.