~/khan

Spring Framework 7 / Spring Boot 4 정리 — 베이스라인부터 RestClient, Observability, Virtual Thread 까지

· 12 min read · by Khan
#Spring#Spring Boot#Java#Virtual Thread#Observability

Spring Framework 7 (Spring Boot 4) 의 릴리즈 노트를 처음 펼쳐 봤을 때, 굵직한 변화가 너무 많아서 어디부터 봐야 할지 한참 헤맸습니다. 이번 글은 그 변화들을 베이스라인 → API 정리 → 호환성 → 신규 기본값 순서로 한 번에 펼쳐 정리한 메모입니다. 이 글만 봐도 "내 프로젝트에서 무엇이 깨지고, 무엇이 바뀌고, 무엇이 새로 들어오는지" 가 한눈에 잡히는 걸 목표로 적었습니다.

1. 베이스라인 업그레이드

가장 먼저 흔들리는 건 JDK 최소 버전입니다.

항목버전
최소 버전JDK 17
권장 버전JDK 25 (LTS)

JDK 25 자체도 굵직한 개선이 같이 들어와 있습니다.

  • 객체 헤더 컴팩팅 (JEP 519)
  • GC 성능 향상
  • String Key 기반 Map 성능 개선
  • GraalVM 25 기반 Native 환경 개선

JDK 17 만 맞춰도 동작은 하지만, "성능 개선 흐름은 25 에 있다" 로 정리해 두면 마음이 편합니다.

2. Jakarta EE 와 생태계 최소 버전

javax.* 시대가 끝난 건 이미 6.x 에서였지만, 7.x 는 그 위에서 한 발 더 올라갑니다.

기능최소 버전
Jakarta EE11
Servlet6.1
WebSocket2.2
JPA3.2
Bean Validation3.1
Netty4.2
Kotlin2.2
JUnit6
GraalVM25

이 표에서 제일 신경 쓰이는 건 보통 JPA 3.2 / JUnit 6 입니다. 둘 다 의존성을 폭넓게 쓰기 때문에 업그레이드 영향이 큽니다.

3. Deprecated / 삭제된 API

다음 API 들은 7.x 에서 제거되거나 비권장 상태로 들어갑니다.

  • RestTemplateRestClient / WebClient 권장
  • Spring MVC XML namespace
  • JUnit 4
  • Jackson 2.x
  • PathMatcherPathPatternParser 권장
  • <lang:*> XML
  • HttpStatus 일부 코드 (RFC 9110 기반 정리)
  • org.springframework.web.servlet.view.document (XLS/PDF/RSS)

RestTemplate 은 이번에 사실상 마침표를 찍는 분위기입니다. 새 코드에서는 RestClient 로 가는 게 안전합니다.

4. Breaking Changes — HttpHeadersMultiValueMap 상속을 끊었습니다

7.x 의 가장 흔히 부딪히는 깨짐 중 하나입니다. 기존에는 MultiValueMap 을 상속받았기 때문에 put 같은 호출이 가능했지만, 이제는 그렇지 않습니다.

기존 (6.x)

HttpHeaders headers = new HttpHeaders();
headers.put("X-Test", List.of("v1", "v2"));

변경 후 (7.x)

HttpHeaders headers = new HttpHeaders();
headers.add("X-Test", "v1");
headers.add("X-Test", "v2");
headers.set("Content-Type", MediaType.APPLICATION_JSON_VALUE);

add / set 이라는 의미 있는 메서드만 남기는 방향입니다. 헤더가 "Map 의 일종" 이 아니라 "헤더라는 별도 자료구조" 로 격상된 셈입니다.

5. Null Safety — JSR 305 → JSpecify

Spring 의 nullness 애노테이션이 JSpecify 로 교체됩니다. 이 부분은 코드 호환성보다는 IDE / 정적 분석 / Kotlin 상호 운용 에서의 개선이 큽니다. Kotlin 의 nullable 처리와 더 자연스럽게 맞물리는 방향입니다.

6. JPA 3.2 & Hibernate ORM 7.x

JPA 쪽 변화는 다음과 같습니다.

  • SharedEntityManagerBean 이 더 이상 필요하지 않게 됩니다.
  • 패키지가 이동합니다.
    • 기존: org.springframework.orm.hibernate5
    • 변경: org.springframework.orm.jpa.hibernate

업그레이드 시 import 만 손보면 되는 경우가 많지만, 커스텀 @Configuration 으로 EntityManagerFactory 를 직접 만들어 둔 프로젝트라면 그쪽도 같이 점검이 필요합니다.

7. Jackson 3.x 지원

기존변경
com.fasterxml.jacksontools.jackson

패키지 자체가 이동했기 때문에 import 와 BOM 둘 다 손이 갑니다.

var mapper = JsonMapper.builder().build();

Jackson2ObjectMapperBuilderdeprecated 입니다. 신규 코드에서는 JsonMapper.builder() 쪽이 권장 경로입니다.

8. WebFlux — Gson 지원 추가

Jackson 없이도 Gson 으로 JSON 직렬화·역직렬화를 할 수 있는 경로가 정식으로 들어옵니다. Jackson 3 마이그레이션을 미루고 싶을 때 가져갈 수 있는 선택지가 하나 더 생긴 셈입니다.

9. CORS Preflight 정책 변경

CORS 설정이 비어 있어도 기본적으로 preflight 요청을 거부하지 않습니다. 즉 기본 허용 으로 바뀝니다. 운영 환경 보안 정책에 따라 명시적으로 조이는 설정이 필요한 케이스가 생길 수 있습니다.

10. 메서드 단일 Bean → 다중 Bean 등록 가능

한 메서드가 여러 빈을 반환할 수 있게 됩니다.

@Bean
List<Object> createBeans(BeanFactory factory) {
    return List.of(new A(), new B(), new C());
}

빈 묶음을 동적으로 만들어야 하는 자리에서 자주 쓰는 패턴이 한 단계 더 자연스러워집니다.

11. Spring Retry 기본화

Resilience4j 같은 외부 라이브러리 없이도 Spring 자체에 재시도 기능이 포함 됩니다. 작은 재시도 패턴 하나 때문에 의존성을 끌어다 쓰던 코드들이 정리될 여지가 생깁니다.

12. Spring Boot 4 와의 연계 변화

Spring Framework 7 위에서 Spring Boot 4 는 다음과 같은 큰 변화를 같이 가져옵니다.

  • 새로운 Property Binding 구조
  • Observability (메트릭/로그/트레이싱) 완전 개편 — Micrometer 2 기반
  • RestClient 기본화
  • Actuator / Health 구조 개선
  • Bean overriding 제한

RestClient 자동 구성 예시는 이렇게 들어옵니다.

@Bean
RestClient restClient(RestClient.Builder builder) {
    return builder.baseUrl("https://api.example.com").build();
}

13. Virtual Threads (JDK 21) 의 공식 지원

Virtual Thread 는 이미 JDK 21 에서 정식 도입된 기능입니다. Spring 7 / Boot 4 는 이를 공식 지원 대상으로 끌어올려서, MVC / @Async / 스케줄러 등 실행 모델 전반에서 안정적으로 쓸 수 있도록 다듬었습니다.

13.1 지원 포인트

  • Spring MVC 요청 처리와 Virtual Thread 안정 통합 — Blocking I/O 기반 MVC 에서도 고동시성 가능
  • @Async / Executor 설정에 Virtual Thread 완전 지원
  • Transaction / JDBC 환경에서의 사용 안정화
  • Scheduler / Batch 같은 대량 작업 적용 가능
@Bean
Executor asyncExecutor() {
    return Executors.newVirtualThreadPerTaskExecutor();
}

여기서 한 가지 짚어두고 싶은 점이 있습니다. Virtual Thread 가 "공식 지원" 된다는 말이, "어느 잡에 끼워도 빨라진다" 는 뜻은 아니라는 것입니다. DB 커넥션 풀 같은 하부 자원이 같이 늘어나야 진짜 효과가 납니다. 이 부분은 별도 글에서 더 길게 정리해 두고 있습니다.

14. Observability / Micrometer 2 / OpenTelemetry

Spring 7 & Boot 4 는 내부 로깅 / 트레이싱 구조가 OpenTelemetry 기반으로 통일 됩니다.

특징

  • Meter / Log / Trace 를 하나의 Observability API 로 통합
  • Sleuth 완전 제거
  • OTLP Exporter 기본화
  • Prometheus / Grafana / Tempo 연동 표준화

application.yml 예시:

management:
  tracing:
    enabled: true
  metrics:
    export:
      prometheus:
        enabled: true

Sleuth 가 빠지는 게 의외로 영향이 큽니다. 트레이싱 컨텍스트 전파 코드를 손수 깔아둔 프로젝트라면 점검이 필요합니다.

15. RestTemplate → RestClient 전환

가장 자주 만지게 될 부분입니다.

기본 사용

RestClient client = RestClient.builder()
    .baseUrl("https://api.server.com")
    .build();
 
String result = client.get()
    .uri("/data")
    .retrieve()
    .body(String.class);

예외 처리

상태 코드별 분기 처리는 onStatus 로 깔끔하게 들어옵니다.

client.get()
    .uri("/data")
    .retrieve()
    .onStatus(HttpStatusCode::is4xxClientError, (req, res) -> {
        throw new IllegalArgumentException("잘못된 요청");
    })
    .onStatus(HttpStatusCode::is5xxServerError, (req, res) -> {
        throw new IllegalStateException("서버 오류");
    })
    .body(String.class);

RestTemplateResponseErrorHandler 보다 호출 위치에서 바로 읽히는 형태입니다.

16. PathPatternParser — 경로 매칭 성능 향상

PathMatcher 는 deprecated 가 됩니다.

PathPatternParser parser = new PathPatternParser();
PathPattern pattern = parser.parse("/user/{id}");
 
PathPattern.PathMatchInfo info = pattern.matchAndExtract("/user/123");
String userId = info.getUriVariables().get("id");

장점:

  • 성능 향상 (4~20배)
  • 파싱 비용 감소
  • WebFlux, Security 모두 통일된 방식

URL 매칭이 핫패스인 게이트웨이성 코드라면 체감 차이가 큽니다.

17. Hibernate ORM 7.x 성능 개선

Hibernate 7.x 는 다음 영역에서 성능이 개선됩니다.

  • Batch Fetch 알고리즘 개선
  • Dirty Checking 최적화
  • Proxy 성능 향상
  • Query Plan 캐싱 강화
  • Immutable Entity 지원 강화
@Entity
@BatchSize(size = 50)
public class User { /* ... */ }

18. JSON 생태계 전반

마지막으로 JSON 쪽 흐름을 한 번에 정리해 두면 이렇게 됩니다.

  • Jackson 3 패키지 이동 (com.fasterxml.jacksontools.jackson)
  • WebFlux 에서 Gson 지원
  • CBOR, Smile 같은 바이너리 JSON 포맷 강화
  • Jackson2ObjectMapperBuilder deprecated

마무리

큼지막한 변화들만 모아 두고 보니, Spring Framework 7 / Spring Boot 4 의 방향은 대략 이 세 줄로 요약될 것 같습니다.

  1. 레거시 API 정리RestTemplate, PathMatcher, Sleuth, javax.* 잔재.
  2. JDK / Jakarta 베이스라인 한 칸 올리기 — JDK 17 최소, JDK 25 권장.
  3. 신규 기본값 표준화RestClient, OpenTelemetry, Virtual Thread, JSpecify.

업그레이드를 한 번에 다 끌고 가려고 하면 마이그레이션이 거대해집니다. 보통 다음 순서로 자르면 위험이 작았던 것 같습니다.

  1. JDK / Jakarta 베이스라인 맞추기
  2. Deprecated 호출 정리 (RestTemplate, PathMatcher, Sleuth)
  3. Jackson 3 / JPA 3.2 이전
  4. Observability / Virtual Thread 같은 신규 기능 도입

다음번에 비슷한 메이저 업그레이드를 또 하게 되면, 이 글을 출발 메모로 다시 펴 보려고 합니다.