Java 26, 업그레이드 전 공식 문서에서 직접 확인한 5가지

Published on

in

Java 26, 업그레이드 전 공식 문서에서 직접 확인한 5가지

2026.03.17 GA 기준
JDK 26 (Build 26+35)
Non-LTS

Java 26, 업그레이드 전 공식 문서에서 직접 확인한 5가지

Java 26이 2026년 3월 17일 정식 출시됐습니다. 10개의 JEP가 포함됐는데, 직접 공식 문서를 뜯어보니까 “쓰면 좋다”는 얘기보다 “이걸 모르면 나중에 터진다”는 내용이 더 눈에 들어왔습니다. 특히 프로덕션 팀이라면 지금 당장 CI 파이프라인에서 확인해야 할 변경사항이 있습니다.

10개
총 JEP 수
5개
정식 확정 JEP
~6개월
지원 기간 (2026.09 종료)
2,535개
수정된 JIRA 이슈

G1 GC가 빨라졌는데, 코드를 바꿀 필요가 없습니다

Java 26에서 가장 즉각적인 이득은 JEP 522, G1 가비지 컬렉터의 처리량 개선입니다. 그런데 특이한 점이 있습니다. 이 변화를 얻기 위해 코드를 단 한 줄도 바꿀 필요가 없습니다. JDK를 올리기만 하면 됩니다.

기존 G1은 애플리케이션 스레드와 GC 스레드가 단일 카드 테이블(card table)을 공유했습니다. 객체 참조가 바뀔 때마다 둘 다 이 테이블에 접근해야 했고, 그 과정에서 동기화 비용이 발생했습니다. JEP 522는 카드 테이블을 두 개로 나눠서 각자 분리된 공간에 쓰게 했습니다. G1이 pause 시간 초과를 감지하면 두 테이블을 원자적으로 교체하는 방식입니다.

💡 공식 벤치마크 결과와 wikidocs 분석을 함께 놓고 보니 수치의 범위가 좀 더 분명해졌습니다.

객체 참조를 자주 수정하는 애플리케이션(Spring Boot의 HTTP 요청 처리, JPA 엔티티 로딩 등 대부분의 서버 사이드 코드)에서 처리량이 5~15% 향상됩니다. (출처: JEP 522 공식 문서, wikidocs Java 26 기술 분석, 2026.03.18)

참조 변경이 적은 애플리케이션에서도 write barrier 단순화 덕분에 x64 아키텍처 기준 최대 5% 추가 개선이 보고됐습니다.

두 번째 카드 테이블이 추가되지만 메모리 비용은 힙 1GB당 약 2MB로, Java 20 이전 G1이 같은 용도로 쓰던 메모리의 8분의 1 수준입니다. 메모리를 덜 쓰면서 더 빨라진 셈입니다.

G1은 Java 9부터 기본 GC입니다. 따로 GC를 바꾼 적 없다면 지금도 G1을 쓰고 있다는 뜻이고, JDK 26으로 올리는 것만으로 이 개선이 자동으로 적용됩니다.

함께 알아두면 좋은 맥락이 있습니다. Java 25(LTS)에서 이미 Compact Object Headers가 도입돼 객체 헤더 크기가 12~16바이트에서 8바이트로 줄었고, 이로 인해 힙 사용량이 약 22% 감소했습니다. (출처: Spring Boot 개발자를 위한 Java 26 분석, dev.to, 2026.03.17) Java 25→26 마이그레이션이라면 GC 개선 + 힙 절감이 동시에 적용됩니다.

▲ 목차로 돌아가기

Java 26을 프로덕션에 올리면 안 되는 이유

솔직히 말하면, 이 부분이 이 글에서 제일 중요합니다. Java 26은 LTS(장기 지원) 버전이 아닙니다. 직전 버전인 Java 25가 LTS를 담당합니다.

오라클 공식 기술 블로그에 분명하게 나와 있습니다. Java 26의 Premier Support는 2026년 9월까지로, 6개월에 불과합니다. (출처: Oracle Java 26 Arrival 공식 블로그, 2026.03.17) 6개월이 지나면 Oracle JDK 27이 나오고 Java 26 지원은 종료됩니다. 보안 패치가 중단된 JDK를 프로덕션에서 계속 쓰는 건 다른 문제입니다.

⚠️ 버전 전략 요약
— 프로덕션 배포: Java 25 LTS 유지
— CI/CD 파이프라인: Java 26 추가해서 호환성 테스트
— 다음 LTS 마이그레이션 계획: Java 29(2027.09 예정)

Spring Boot 4.0.x는 Java 25까지 공식 지원합니다. Java 26은 “best effort” 수준으로, 대부분 작동하지만 공식 보장은 없습니다. (출처: dev.to Java 26 분석, 2026.03.17)

오해하기 쉬운 부분이 있습니다. 6개월 주기 릴리스 정책으로 Java는 매우 빠르게 기능을 출시하고 있습니다. Java 26은 이 정책으로 정시에 나온 17번째 Feature Release입니다. (출처: Oracle 공식 블로그) 빠른 출시가 곧 프로덕션 권장을 의미하지는 않습니다. 기능을 미리 써보고, 라이브러리 호환성을 검증하는 용도가 비LTS 릴리스의 주된 역할입니다.

▲ 목차로 돌아가기

final이 드디어 진짜 final이 되기 시작합니다

JEP 500은 이름이 조용하지만, 라이브러리 의존성을 많이 가진 프로젝트라면 CI 로그에서 바로 영향을 느낄 수 있습니다. Java 26부터 리플렉션으로 final 필드를 변경하면 경고가 출력됩니다.

💡 기존 블로그들이 “final 필드 변경 경고”를 단순 기능 추가로 설명하는 경우가 많은데, 실제 흐름은 다릅니다. 이 변화는 Project Valhalla(value type 도입)를 위한 사전 작업입니다.

Valhalla의 value type이 제대로 작동하려면 JVM이 객체의 불변성을 신뢰할 수 있어야 합니다. final 필드가 리플렉션으로 언제든 바뀔 수 있는 현재 구조에서는 그 신뢰가 성립하지 않습니다. JEP 500은 Valhalla의 토대를 다지는 작업입니다. (출처: Oracle JDK 26 릴리스 노트, 2026.03.17; wikidocs Java 26 기술 분석)

지금 당장 에러가 나는 건 아닙니다. Java 26에서는 경고만 발생하고, 미래 버전에서 기본 에러로 바뀔 예정입니다(타임라인은 아직 공개되지 않았습니다). 하지만 Hibernate 7.x 이전 버전, 일부 Mockito 설정, Lombok이 이 패턴을 쓰고 있습니다. Spring Framework 7.0은 이미 관련 리플렉션 사용을 정리했습니다.

실행 가능한 점검 방법이 있습니다. Java 26을 CI 매트릭스에 추가하고 로그에서 has been mutated reflectively 문자열을 검색합니다. 직접 작성한 코드의 경고는 즉시 수정하고, 라이브러리에서 오는 경고는 Java 26 호환 버전 여부를 확인합니다. 임시로 억제가 필요하다면 --enable-final-field-mutation=ALL-UNNAMED 플래그를 씁니다. (출처: dev.to Java 26 Spring Boot 분석, 2026.03.17)

▲ 목차로 돌아가기

Applet과 Thread.stop()이 완전히 사라졌습니다

코드베이스에 오래된 코드가 섞여 있다면 이 부분을 먼저 점검해야 합니다. Java 26에서 두 가지 API가 완전히 제거됐습니다.

Applet API (JEP 504): java.applet 패키지 전체가 삭제됐습니다. JDK 9(2017년)에 deprecated, JDK 17(2021년)에 removal deprecated로 지정된 후 5년 만에 실제 제거가 이뤄진 겁니다. (출처: Oracle JDK 26 릴리스 노트; Inside.java Applet 제거 문서, 2025.12.03) 실무에서 applet을 직접 쓰는 경우는 드물지만, 레거시 엔터프라이즈 프로젝트에서 간접 의존성으로 남아 있는 경우가 있습니다.

Thread.stop() 제거: JDK 1.2(1998년)에 deprecated 됐던 java.lang.Thread.stop()이 완전히 삭제됐습니다. (출처: Oracle JDK 26 릴리스 노트, JDK-8368226) Java 26 이상에서 컴파일하면 컴파일 에러가 납니다. 이미 컴파일된 구버전 코드는 런타임에서 NoSuchMethodError를 던집니다.

⚠️ 추가로 제거된 항목들 (JDK 26 릴리스 노트 기준)
jrunscript 툴 완전 제거
jdk.jsobject 모듈 제거 (JavaFX 24+에 포함됨)
— InfiniBand SDP 지원 제거
MulticastSocket.setTTL()/getTTL() 제거
— DESede 및 PKCS1Padding 알고리즘 요구사항 제거 (레거시 암호화)
— AffirmTrust 루트 인증서 4개 삭제

마이그레이션 전에 jdeps 도구로 제거된 API 의존성을 미리 확인하는 걸 권장합니다. jdeps --jdk-internals your-app.jar로 내부 API 사용 여부를 먼저 파악할 수 있습니다.

▲ 목차로 돌아가기

JEP에 없는 변경사항인데 DB 성능에 직접 닿습니다

이 부분이 기존 Java 26 정리 글에 거의 없는 내용입니다. 공식 릴리스 노트 비JEP 항목에 조용히 들어가 있는데, 실제로 DB와 연동되는 서비스에서 의미 있는 차이를 만들 수 있습니다.

💡 공식 발표문과 릴리스 노트를 교차해서 보면, JEP 목록에 없는 변경사항 중 실무 영향이 큰 항목이 보입니다.

UUID v7 메서드 추가: JEP가 아닌 일반 라이브러리 개선으로 UUID.ofEpochMillis(long timestamp)가 추가됐습니다. (출처: JDK 26 릴리스 노트 New Features, Oracle) 기존 UUID.randomUUID()가 생성하는 v4 UUID는 완전 무작위라서 DB의 B-tree 인덱스에 삽입할 때 항상 랜덤 위치에 들어갑니다. 행을 추가할수록 인덱스가 조각나고, 페이지 분할이 발생합니다.

새 메서드로 생성하는 v7 UUID는 앞부분에 밀리초 단위 타임스탬프가 담겨 있어서, 새 행은 항상 인덱스 끝에 삽입됩니다. 페이지 분할 없이 인덱스가 순서대로 쌓입니다. 외부 라이브러리 없이 메서드 하나 바꾸는 것만으로 높은 삽입 빈도의 테이블 성능이 개선됩니다.

구분 UUID v4 (기존) UUID v7 (Java 26~)
메서드 UUID.randomUUID() UUID.ofEpochMillis(ms)
구조 완전 무작위 앞 48비트: 타임스탬프
DB 인덱스 삽입 랜덤 위치 (페이지 분할 발생) 항상 끝에 추가 (순차 삽입)
외부 라이브러리 불필요 불필요

가상 스레드 언마운트 개선: JDK-8369238에서 클래스 초기화를 기다리는 가상 스레드가 이제 carrier 스레드에서 언마운트됩니다. 이전에는 대기 중에도 carrier 스레드를 점유(pin)했습니다. (출처: JDK 26 릴리스 노트, Oracle) 고동시성 서비스에서 virtual thread 고갈로 인한 데드락 가능성이 줄어드는 변화입니다.

▲ 목차로 돌아가기

HTTP/3과 ZGC AOT 캐시, 언제 쓰면 실제로 차이가 납니까

JEP 517(HTTP/3)과 JEP 516(ZGC AOT 캐시)은 많이 언급되는 기능인데, 막상 언제 쓰면 실제 차이가 나는지 명확히 설명하는 글이 없습니다. 조건을 먼저 보는 게 맞습니다.

HTTP/3: 이 조건에서만 체감이 납니다

JEP 517로 JDK의 HttpClient가 HTTP/3(QUIC 기반)을 지원합니다. 한 줄 변경으로 활성화됩니다. 서버가 HTTP/3을 지원하지 않으면 HTTP/2로 자동 폴백하니 즉각 도입이 가능합니다. (출처: JEP 517 공식 문서, Oracle)

실제로 차이가 나는 시나리오는 두 가지입니다. 첫째, AI 추론 엔드포인트, 결제 게이트웨이처럼 지연에 민감하면서 동시 요청이 많은 외부 API 호출. HTTP/3은 head-of-line blocking이 없어서 하나의 느린 요청이 뒤 요청을 막지 않습니다. 둘째, 패킷 손실이 있는 네트워크 환경. QUIC은 TCP와 달리 스트림 단위로 재전송하기 때문에 불안정한 네트워크에서 유리합니다.

중요한 제약이 있습니다. Spring WebFlux의 기본 HTTP 클라이언트인 Reactor Netty는 JDK HttpClient를 쓰지 않습니다. JDK의 HTTP/3 지원은 Netty 기반 스택에는 해당되지 않습니다. (출처: dev.to Java 26 Spring Boot 분석) RestClient를 JDK HttpClient로 백엔드로 설정한 경우에만 적용됩니다.

ZGC + AOT 캐시: Java 26 이전에는 불가능했습니다

JEP 516은 AOT 캐시를 ZGC에서도 쓸 수 있게 합니다. Java 24에서 도입된 AOT 클래스 로딩 캐시가 ZGC의 메모리 레이아웃과 충돌해서 ZGC 사용자는 AOT 캐시의 혜택을 받지 못했습니다. Java 26에서 논리적 인덱스 기반으로 GC 중립적 포맷을 만들어 이 제약을 해소했습니다. (출처: JEP 516 공식 문서, wikidocs Java 26 분석)

tail latency(P99, P999 응답 시간)가 중요한 서비스에서 ZGC를 쓰면서 빠른 시작 시간도 원했다면, Java 26이 처음으로 두 가지를 동시에 선택할 수 있게 해줍니다. 반드시 ZGC를 명시적으로 지정해야 하고, AOT 캐시를 별도로 생성해야 합니다.

▲ 목차로 돌아가기

자주 묻는 질문

Java 26을 지금 당장 써봐도 됩니까? 위험한 게 있습니까?

로컬 개발 환경이나 CI 파이프라인에서 쓰는 건 아무 문제없습니다. 다만 프로덕션 배포는 권장하지 않습니다. 공식 지원이 2026년 9월에 종료되고, 그 이후로는 보안 패치도 없습니다. Spring Boot 4.0.x 기준으로는 Java 25까지만 공식 지원합니다. (출처: Oracle JDK 26 공식 블로그) 신기능 미리 체험하고 호환성 테스트하는 용도로는 지금 시작하는 게 좋습니다.
G1 GC 성능 향상이 5~15%라고 했는데, 항상 그렇습니까?

객체 참조를 자주 변경하는 워크로드에서 5~15% 향상이 측정됩니다. Spring Boot의 HTTP 요청 처리나 JPA 엔티티 조작이 여기에 해당합니다. 참조 변경이 드문 계산 집약적 코드(수치 계산, 이미지 처리 등)는 이 범위보다 낮을 수 있습니다. 추가로 x64 아키텍처에서는 참조가 적은 경우에도 write barrier 단순화로 최대 5% 개선이 보고됩니다. (출처: JEP 522 공식 문서; wikidocs Java 26 분석, 2026.03.18) 본인 서비스는 Java 26 CI에서 JMH 벤치마크를 직접 돌리는 게 가장 정확합니다.
Applet API가 삭제됐는데, 영향받는 프로젝트를 어떻게 찾습니까?

jdeps --multi-release 26 --missing-deps your-app.jar 명령으로 삭제된 API를 참조하는 코드를 찾을 수 있습니다. 직접 applet을 쓰지 않더라도 간접 의존성으로 java.applet을 참조하는 라이브러리가 있을 수 있습니다. 특히 10년 이상 된 레거시 엔터프라이즈 코드베이스에서 확인이 필요합니다. (출처: JEP 504, Oracle JDK 26 릴리스 노트)
Structured Concurrency가 여섯 번째 프리뷰인데, 언제 정식 출시됩니까?

Java 19에서 처음 프리뷰로 등장해 Java 26까지 여섯 번째 프리뷰를 거치고 있습니다. 정식 출시 타임라인은 오라클이 공식 답변을 내놓지 않은 부분입니다. 이번 프리뷰에서 Joiner 인터페이스에 onTimeout() 메서드가 추가되고, allSuccessfulOrThrow()가 스트림 대신 리스트를 반환하도록 변경됐습니다. 설계 완성도는 높아지고 있지만, 프로덕션 코드에는 아직 안정적으로 쓰기 어렵습니다. (출처: JEP 525 공식 문서)
다음 LTS는 언제입니까? Java 26에서 바로 LTS로 넘어가야 합니까?

다음 LTS는 Java 29로, 2027년 9월 출시가 예정돼 있습니다. 6개월 주기에 따라 Java 27(2026.09), Java 28(2027.03), Java 29(2027.09) 순입니다. 지금 Java 21 LTS에 있다면 Java 25 LTS로의 마이그레이션이 현실적입니다. Java 25에는 Compact Object Headers(힙 22% 절감), 가상 스레드 pinning 개선 등 실질적인 성능 개선이 포함돼 있습니다. Java 26의 신기능 중 정식 확정된 것만 추리면 G1 GC 개선, HTTP/3, AOT 캐시 확장, Applet 제거, final 경고 추가입니다. (출처: Oracle JDK 릴리스 로드맵)

▲ 목차로 돌아가기

마치며 — Java 26을 어떻게 다뤄야 합니까

Java 26은 화려한 릴리스가 아닙니다. “와, 이 기능 때문에 당장 올려야겠다”는 느낌이 드는 버전은 아닙니다. 그런데 막상 공식 문서를 꼼꼼히 읽고 나면 생각이 달라집니다. G1 GC 개선은 아무것도 안 해도 공짜로 오는 성능 향상이고, JEP 500의 final 경고는 미래 버전에서 에러로 바뀌기 전에 지금 CI에서 미리 잡아야 할 호환성 문제입니다.

개인적으로 이번 릴리스에서 가장 흥미로웠던 건 JEP 500입니다. final이 진짜 final이 된다는 게 단순한 언어 규칙 강화가 아니라 Project Valhalla를 향한 포석이라는 맥락이 붙는 순간, 이 변화가 왜 지금 들어왔는지가 보입니다. Java의 진화 방식은 오래 걸리지만, 방향이 있습니다.

결론은 단순합니다. 프로덕션은 Java 25 LTS로 유지하고, Java 26은 CI에 올려서 JEP 500 경고와 삭제된 API 호환성을 지금부터 점검하는 게 맞는 순서입니다.

▲ 목차로 돌아가기

본 포스팅 참고 자료

  1. Oracle 한국 공식 발표문 — 오라클, 자바 26 출시 (2026.03.17)
    https://www.oracle.com/kr/news/announcement/oracle-releases-java-26-2026-03-17/
  2. Oracle Java 기술 블로그 — The Arrival of Java 26 (2026.03.17)
    https://blogs.oracle.com/java/the-arrival-of-java-26
  3. Oracle JDK 26 공식 릴리스 노트 (2026.03.17)
    https://www.oracle.com/java/technologies/javase/26-relnote-issues.html
  4. dev.to — Java 26 Is Out, Here’s What Actually Matters for Spring Boot Developers (2026.03.17)
    https://dev.to/paszekdev/java-26-is-out-heres-what-actually-matters-for-spring-boot-developers-4k6d
  5. wikidocs — Java 26 출시: Valhalla를 향한 마지막 준비인가 (2026.03.18)
    https://wikidocs.net/blog/@jaehong/9440/
  6. Inside.java — So Long and Thanks for All the Applets (2025.12.03)
    https://inside.java/2025/12/03/applet-removal/

※ 본 포스팅은 2026년 3월 23일 기준 JDK 26 (Build 26+35) 공식 문서를 토대로 작성됐습니다. 본 포스팅 작성 이후 서비스 정책·UI·기능이 변경될 수 있습니다. 수치 및 지원 일정은 Oracle 공식 발표를 최종 기준으로 확인하시기 바랍니다.

댓글 남기기


최신 글


아이테크 어른경제에서 더 알아보기

지금 구독하여 계속 읽고 전체 아카이브에 액세스하세요.

계속 읽기