2025년 9월, Oracle이 Java 25를 공식 출시했습니다. Java 25는 Java 21 이후 첫 번째 LTS(Long-Term Support) 릴리스로, 최소 8년간의 장기 지원이 보장됩니다. 총 18개의 JEP(Java Enhancement Proposal)를 포함한 이번 릴리스는 성능 최적화, 개발자 생산성, 그리고 현대적인 프로그래밍 패러다임에 대한 지원을 크게 향상시켰습니다.
Java 25에서 가장 주목할 만한 기능 중 하나는 모듈 전체를 한 번에 임포트할 수 있는 새로운 구문입니다. 기존에는 모듈의 여러 패키지를 사용하려면 각각을 개별적으로 임포트해야 했지만, 이제는 import module 구문을 사용하여 모듈이 내보내는 모든 패키지를 간결하게 임포트할 수 있습니다.
기존 방식:
import java.util.*;
import java.time.*;
import java.nio.*;
// 여러 개의 import 문이 필요
Java 25의 새로운 방식:
import module java.base;
public class Main {
public static void main(String[] args) {
Date d = new Date();
LocalDateTime now = LocalDateTime.now();
Path path = Paths.get("/tmp");
System.out.println("간결한 모듈 임포트: " + d);
}
}
이 기능의 핵심 장점:
세 번째 프리뷰 단계에 있는 이 기능은 패턴 매칭을 원시 타입으로 확장합니다. 이전 버전에서는 패턴 매칭이 참조 타입에만 사용 가능했지만, 이제 int, double 등의 원시 타입도 직접 매칭할 수 있습니다.
기존 방식:
static void processValue(Object obj) {
if (obj instanceof Integer) {
Integer i = (Integer) obj;
System.out.println("정수 값: " + i);
} else if (obj instanceof Double) {
Double d = (Double) obj;
System.out.println("실수 값: " + d);
}
}
Java 25의 새로운 방식:
static void processValue(Object obj) {
switch (obj) {
case int i -> System.out.println("정수 값: " + i);
case double d -> System.out.println("실수 값: " + d);
case String s -> System.out.println("문자열 값: " + s);
default -> System.out.println("알 수 없는 타입");
}
}
// instanceof와 함께 사용
static void testInstance(Object obj) {
if (obj instanceof int i) {
System.out.println("정수입니다: " + i);
}
}
이 기능은 생성자에서 super() 또는 this() 호출 전에 검증 로직이나 안전한 계산을 수행할 수 있도록 합니다. 기존에는 생성자의 첫 번째 문장이 반드시 다른 생성자 호출이어야 했지만, 이제는 더 유연한 구조가 가능합니다.
기존 방식의 제약:
public class Person {
private final String name;
private final int age;
public Person(String name, int age) {
// super() 호출 전에는 어떤 로직도 실행할 수 없었음
super();
if (name == null || name.trim().isEmpty()) {
throw new IllegalArgumentException("이름은 필수입니다");
}
this.name = name;
this.age = age;
}
}
Java 25의 새로운 방식:
public class Person {
private final String name;
private final int age;
public Person(String name, int age) {
// super() 호출 전에 검증 로직 실행 가능
if (name == null || name.trim().isEmpty()) {
throw new IllegalArgumentException("이름은 필수입니다");
}
if (age < 0 || age > 150) {
throw new IllegalArgumentException("유효하지 않은 나이입니다");
}
super();
this.name = name.trim();
this.age = age;
}
}
Java 초보자들을 위한 진입 장벽을 낮추는 기능으로, 간단한 프로그램을 더욱 간결하게 작성할 수 있습니다.
기존 방식:
public class HelloWorld {
public static void main(String[] args) {
System.out.println("안녕하세요, 세상!");
}
}
Java 25의 새로운 방식:
void main() {
System.out.println("안녕하세요, 세상!");
}
다섯 번째 프리뷰 단계에 있는 구조적 동시성은 여러 스레드에서 실행되는 관련 작업들을 하나의 작업 단위로 처리하여 동시 프로그래밍을 단순화합니다.
import java.util.concurrent.StructuredTaskScope;
public class DataProcessor {
public Result processData() throws Exception {
try (var scope = new StructuredTaskScope.ShutdownOnFailure()) {
var userTask = scope.fork(() -> fetchUserData());
var orderTask = scope.fork(() -> fetchOrderData());
var productTask = scope.fork(() -> fetchProductData());
scope.join(); // 모든 작업 완료 대기
scope.throwIfFailed(); // 실패 시 예외 발생
return new Result(
userTask.resultNow(),
orderTask.resultNow(),
productTask.resultNow()
);
}
}
}
스레드 로컬 변수보다 효율적인 대안으로 정식 기능화되었습니다. 메서드가 스레드 내의 호출자와 자식 스레드와 불변 데이터를 공유할 수 있게 해줍니다.
public class RequestProcessor {
public static final ScopedValue<String> REQUEST_ID =
ScopedValue.newInstance();
public void processRequest(String requestId) {
ScopedValue.where(REQUEST_ID, requestId)
.run(() -> {
// 이 범위 내에서 REQUEST_ID를 사용할 수 있음
handleRequest();
});
}
private void handleRequest() {
String id = REQUEST_ID.get(); // 현재 요청 ID 획득
System.out.println("처리 중인 요청: " + id);
// 하위 메서드에서도 REQUEST_ID 접근 가능
callSubMethod();
}
}
JVM이 상수로 취급하는 객체를 위한 API를 도입하여, final 변수와 동일한 성능 혜택을 제공합니다.
public class ConfigurationManager {
private static final StableValue<DatabaseConfig> DB_CONFIG =
StableValue.of(loadDatabaseConfig());
public DatabaseConfig getDatabaseConfig() {
return DB_CONFIG.get(); // JVM에서 상수로 최적화
}
}
암호화 키를 사용자 패스워드로부터 유도하는 표준화된 API를 제공합니다. PBKDF2, Argon2, scrypt 등의 알고리즘을 지원합니다.
import javax.crypto.KDF;
import javax.crypto.spec.PBKDF2ParameterSpec;
public class PasswordProcessor {
public byte[] deriveKey(char[] password, byte[] salt) {
PBKDF2ParameterSpec spec = new PBKDF2ParameterSpec(
password, salt, 100_000, 256, "HmacSHA256");
KDF kdf = KDF.getInstance("PBKDF2");
return kdf.deriveKey(spec);
}
}
PEM 형식의 암호화 키, 인증서, 인증서 해지 목록을 인코딩/디코딩하는 API를 제공합니다.
import java.security.cert.X509Certificate;
import java.security.PEMEncoder;
import java.security.PEMDecoder;
public class CertificateHandler {
public String encodeCertificate(X509Certificate cert) {
PEMEncoder encoder = PEMEncoder.getInstance();
return encoder.encode(cert);
}
public X509Certificate decodeCertificate(String pemString) {
PEMDecoder decoder = PEMDecoder.getInstance();
return (X509Certificate) decoder.decode(pemString);
}
}
Java Flight Recorder에 CPU 시간 기반 프로파일링 지원이 추가되어, 특정 메서드나 스레드에서 소비되는 CPU 시간을 정확하게 측정할 수 있습니다.
실험적 기능에서 정식 제품 옵션으로 승격되어, 자바 힙 메모리 사용량을 줄이고 성능 향상을 제공합니다.
# 컴팩트 객체 헤더 활성화
java -XX:+UseCompactObjectHeaders MyApplication
열 번째 인큐베이터 단계에 있는 벡터 API는 지원되는 CPU에서 최적화된 벡터 명령어로 컴파일되는 벡터 계산을 표현할 수 있게 해줍니다.
import jdk.incubator.vector.*;
public class VectorExample {
static final VectorSpecies<Float> SPECIES = FloatVector.SPECIES_256;
public void vectorAdd(float[] a, float[] b, float[] c) {
int length = a.length;
int loopBound = SPECIES.loopBound(length);
for (int i = 0; i < loopBound; i += SPECIES.length()) {
var va = FloatVector.fromArray(SPECIES, a, i);
var vb = FloatVector.fromArray(SPECIES, b, i);
var vc = va.add(vb);
vc.intoArray(c, i);
}
}
}
Red Hat에서 개발한 Shenandoah 가비지 컬렉터에 generational 모드가 정식으로 추가되었습니다. 젊은 세대 객체들을 더 효율적으로 수집하여 일시 정지 시간을 줄이고 처리량을 향상시킵니다.
# Generational Shenandoah 활성화
java -XX:+UseShenandoahGC -XX:ShenandoahGCMode=generational MyApplication
주요 개선사항:
-XX:+UnlockExperimentalVMOptions 플래그가 더 이상 필요하지 않음JFR Method Timing & Tracing (JEP 520) ✅ 정식:
JFR Cooperative Sampling (JEP 518) ✅ 정식:
AOT Command-Line Ergonomics (JEP 514) ✅ 정식:
AOT Method Profiling (JEP 515) ✅ 정식:
레거시 32비트 x86 아키텍처(Linux)에 대한 지원을 완전히 제거하여 유지보수 오버헤드를 줄였습니다. JDK 24에서 32비트 Windows 포트가 제거된 것에 이어, 모든 32비트 포트가 완전히 제거되었습니다.
영향:
Java 25의 새로운 기능들은 실무에서 다음과 같은 이점을 제공합니다:
Java 25로의 마이그레이션을 위해서는:
Java 25는 LTS 릴리스로서 안정성과 혁신성을 모두 갖춘 중요한 업데이트입니다. 18개의 JEP를 통해 언어 기능 개선, 성능 최적화, 보안 강화, 그리고 개발자 경험 향상을 제공합니다.
특히 주목할 만한 점들:
Java 25의 8년 LTS 지원을 통해 기업들은 안정적인 플랫폼에서 최신 기능들을 활용할 수 있게 되었으며, 이는 Java가 현대적인 소프트웨어 개발의 핵심 플랫폼으로 계속 발전할 수 있게 하는 중요한 기반이 될 것입니다.
이 문서는 OpenJDK 공식 문서와 Oracle의 공식 발표를 바탕으로 검증되었습니다. 프로덕션 환경에서 사용하기 전에는 충분한 테스트와 검증을 수행하시기 바랍니다.
검증 소스:
정말 좋은 정보입니다. 바로 팔로잉 꾸~욱~