
들어가며
자바는 1996년 처음 등장한 이후 지속적으로 발전해왔습니다. 특히 Java 8 이후로는 6개월마다 새로운 버전이 출시되면서 빠르게 진화하고 있습니다. 이 글에서는 Java 8부터 최신 버전인 Java 25까지의 주요 특징들을 살펴보겠습니다. 각 버전의 핵심 기능들을 이해하면 현대적인 자바 개발을 더 효과적으로 할 수 있습니다.
Java 8 (2014년 3월) - LTS
Java 8은 자바 역사상 가장 혁명적인 변화를 가져온 버전입니다. 함수형 프로그래밍 패러다임을 본격적으로 도입하면서 자바의 코딩 스타일을 완전히 바꾸어 놓았습니다.
람다 표현식 (Lambda Expressions)
람다 표현식은 익명 함수를 간결하게 표현할 수 있게 해주는 기능입니다. 기존에는 익명 내부 클래스를 사용해야 했던 코드를 훨씬 간결하게 작성할 수 있게 되었습니다.
// Java 7 이전 |
스트림 API (Stream API)
컬렉션 데이터를 함수형 스타일로 처리할 수 있게 해주는 강력한 API입니다. 데이터를 필터링하고, 변환하고, 집계하는 작업을 선언적으로 표현할 수 있습니다.
List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "David"); |
Optional 클래스
Null 참조로 인한 NullPointerException을 방지하기 위한 컨테이너 클래스입니다. 값이 있을 수도, 없을 수도 있는 상황을 명시적으로 표현할 수 있습니다.
Optional<String> optional = Optional.ofNullable(getName()); |
새로운 날짜/시간 API (java.time)
기존의 Date, Calendar 클래스의 문제점을 해결한 새로운 날짜/시간 API가 추가되었습니다. 불변 객체로 설계되어 스레드 안전하며, 더 직관적인 API를 제공합니다.
LocalDate today = LocalDate.now(); |
인터페이스의 Default 메서드
인터페이스에 구현부를 가진 메서드를 추가할 수 있게 되었습니다. 이를 통해 기존 인터페이스를 확장하면서도 하위 호환성을 유지할 수 있습니다.
public interface Vehicle { |
Java 9 (2017년 9월)
Java 9는 모듈 시스템이라는 대규모 변화와 함께 다양한 편의성 개선이 이루어진 버전입니다.
모듈 시스템 (Project Jigsaw)
자바 플랫폼을 모듈화하여 애플리케이션의 의존성을 명확하게 관리할 수 있게 되었습니다. module-info.java 파일을 통해 모듈 간의 의존성을 선언합니다.
module com.example.myapp { |
컬렉션 팩토리 메서드
불변 컬렉션을 쉽게 생성할 수 있는 팩토리 메서드가 추가되었습니다. 코드가 훨씬 간결해지고 가독성이 향상되었습니다.
List<String> list = List.of("Java", "Python", "JavaScript"); |
스트림 API 개선
스트림 처리를 더 유연하게 할 수 있는 새로운 메서드들이 추가되었습니다.
// takeWhile: 조건이 참인 동안만 요소를 가져옴 |
JShell (REPL)
자바 코드를 대화식으로 실행하고 테스트할 수 있는 도구입니다. 간단한 코드 스니펫을 빠르게 실행하고 결과를 확인할 수 있습니다.
$ jshell |
Java 10 (2018년 3월)
Java 10은 비교적 작은 변화가 있었지만, 개발자 경험을 크게 개선한 기능이 추가되었습니다.
지역 변수 타입 추론 (var)
메서드 내부의 지역 변수 선언 시 타입을 명시하지 않고 var 키워드를 사용할 수 있게 되었습니다. 컴파일러가 우변의 초기화 표현식을 통해 타입을 추론합니다.
// 기존 방식 |
주의할 점은 var는 지역 변수에만 사용할 수 있으며, 초기화 표현식이 반드시 필요합니다.
Java 11 (2018년 9월) - LTS
Java 11은 Java 8 이후 두 번째 장기 지원(LTS) 버전입니다. 많은 기업들이 Java 8에서 Java 11로 마이그레이션하면서 널리 사용되고 있습니다.
새로운 String 메서드
문자열 처리를 더 편리하게 해주는 다양한 메서드들이 추가되었습니다.
String text = " Hello World "; |
파일 처리 개선
파일을 읽고 쓰는 작업이 훨씬 간단해졌습니다.
// 파일 읽기 |
단일 파일 실행
javac로 컴파일하지 않고도 자바 파일을 직접 실행할 수 있게 되었습니다. 스크립트처럼 사용할 수 있어 간단한 프로그램을 작성할 때 편리합니다.
# 컴파일 없이 바로 실행 |
HTTP Client API (정식 버전)
Java 9에서 인큐베이터로 제공되던 HTTP Client가 정식 기능으로 추가되었습니다. 비동기 처리와 HTTP/2를 지원합니다.
HttpClient client = HttpClient.newHttpClient(); |
Java 12 (2019년 3월)
Switch 표현식 (Preview)
기존의 switch 문은 문장(statement)이었지만, Java 12부터는 값을 반환하는 표현식(expression)으로도 사용할 수 있게 되었습니다.
// 기존 switch 문 |
Java 13 (2019년 9월)
Text Blocks (Preview)
여러 줄에 걸친 문자열을 작성할 때 이스케이프 문자 없이 자연스럽게 표현할 수 있게 되었습니다. JSON, HTML, SQL 등을 작성할 때 특히 유용합니다.
// 기존 방식 |
Java 14 (2020년 3월)
Records (Preview)
데이터를 담는 단순한 클래스를 작성할 때 보일러플레이트 코드를 크게 줄일 수 있는 기능입니다. getter, equals, hashCode, toString 메서드가 자동으로 생성됩니다.
// 기존 방식 |
instanceof 패턴 매칭 (Preview)
instanceof로 타입을 체크한 후 자동으로 캐스팅이 이루어지도록 개선되었습니다.
// 기존 방식 |
개선된 NullPointerException 메시지
NullPointerException이 발생했을 때 어떤 변수가 null인지 정확하게 알려주게 되었습니다.
person.getAddress().getCity().getName(); |
Java 15 (2020년 9월)
Text Blocks (정식 기능)
Java 13에서 프리뷰로 제공되던 텍스트 블록이 정식 기능으로 추가되었습니다.
Sealed Classes (Preview)
클래스의 상속을 제한할 수 있는 기능입니다. 어떤 클래스가 이 클래스를 상속할 수 있는지 명시적으로 지정할 수 있습니다.
public sealed class Shape |
이를 통해 도메인 모델링을 더 명확하게 할 수 있고, 패턴 매칭과 함께 사용하면 강력한 타입 안전성을 제공합니다.
Java 16 (2021년 3월)
Records (정식 기능)
Java 14에서 프리뷰로 제공되던 Records가 정식 기능으로 추가되었습니다.
instanceof 패턴 매칭 (정식 기능)
Java 14에서 프리뷰였던 패턴 매칭이 정식 기능이 되었습니다.
Stream.toList()
스트림의 결과를 리스트로 변환하는 것이 더 간단해졌습니다.
// 기존 방식 |
Java 17 (2021년 9월) - LTS
Java 17은 Java 11 이후 두 번째 LTS 버전으로, 많은 기업들이 현재 사용하거나 마이그레이션을 계획하고 있는 버전입니다.
Sealed Classes (정식 기능)
Java 15에서 프리뷰였던 Sealed Classes가 정식 기능이 되었습니다.
switch 패턴 매칭 (Preview)
switch 문에서 타입 패턴을 사용할 수 있게 되었습니다.
static String formatter(Object obj) { |
난수 생성 API 개선
새로운 난수 생성 인터페이스와 구현체들이 추가되어 더 다양한 난수 생성 알고리즘을 사용할 수 있게 되었습니다.
RandomGenerator generator = RandomGenerator.of("L64X128MixRandom"); |
Java 18 (2022년 3월)
UTF-8 기본 문자 인코딩
JDK의 기본 문자 인코딩이 UTF-8로 변경되었습니다. 이전에는 운영체제에 따라 기본 인코딩이 달랐지만, 이제는 모든 플랫폼에서 일관되게 UTF-8을 사용합니다.
간단한 웹 서버
테스트나 프로토타이핑을 위한 간단한 웹 서버를 명령줄에서 바로 실행할 수 있게 되었습니다.
jwebserver |
코드 스니펫을 위한 @snippet 태그
Javadoc에서 코드 예제를 더 잘 작성할 수 있도록 새로운 태그가 추가되었습니다.
Java 19 (2022년 9월)
Virtual Threads (Preview)
Project Loom의 핵심 기능인 가상 스레드가 프리뷰로 제공되기 시작했습니다. 가상 스레드는 경량 스레드로, 수백만 개의 스레드를 생성해도 시스템 리소스를 크게 소비하지 않습니다.
// 가상 스레드 생성 |
가상 스레드는 높은 동시성이 필요한 서버 애플리케이션에서 특히 유용합니다.
Structured Concurrency (Incubator)
여러 작업을 구조화된 방식으로 동시에 실행하고 관리할 수 있는 API입니다.
try (var scope = new StructuredTaskScope.ShutdownOnFailure()) { |
Record Patterns (Preview)
Record의 컴포넌트를 패턴 매칭으로 분해할 수 있게 되었습니다.
record Point(int x, int y) {} |
Java 20 (2023년 3월)
Scoped Values (Incubator)
스레드 로컬 변수를 대체할 수 있는 새로운 메커니즘입니다. 특히 가상 스레드와 함께 사용할 때 효율적입니다.
final static ScopedValue<User> CURRENT_USER = ScopedValue.newInstance(); |
Record Patterns (Second Preview)
Record 패턴이 개선되어 중첩된 패턴도 지원하게 되었습니다.
Java 21 (2023년 9월) - LTS
Java 21은 최신 LTS 버전으로, 많은 혁신적인 기능들이 정식으로 추가되었습니다.
Virtual Threads (정식 기능)
가상 스레드가 정식 기능이 되면서 프로덕션 환경에서 사용할 수 있게 되었습니다. 이는 자바의 동시성 프로그래밍 패러다임을 크게 변화시킬 중요한 기능입니다.
Sequenced Collections
컬렉션의 순서를 다루는 새로운 인터페이스들이 추가되었습니다.
interface SequencedCollection<E> extends Collection<E> { |
switch 패턴 매칭과 Record 패턴 (정식 기능)
이제 switch 문에서 복잡한 패턴 매칭을 프로덕션 코드에서 사용할 수 있습니다.
sealed interface Vehicle permits Car, Truck, Motorcycle {} |
String Templates (Preview)
문자열 보간을 안전하게 수행할 수 있는 기능입니다.
String name = "John"; |
Java 22 (2024년 3월)
Unnamed Variables & Patterns
사용하지 않는 변수나 패턴을 명시적으로 표시할 수 있게 되었습니다.
// 사용하지 않는 변수 |
Statements before super() (Preview)
생성자에서 super() 호출 전에 문장을 실행할 수 있게 되었습니다.
public class PositiveBigInteger extends BigInteger { |
Foreign Function & Memory API (정식 기능)
네이티브 코드와 상호작용하기 위한 안전하고 효율적인 API가 정식으로 추가되었습니다. JNI를 대체할 수 있는 현대적인 방법을 제공합니다.
Java 23 (2024년 9월)
Primitive Types in Patterns (Preview)
primitive 타입도 패턴 매칭에서 사용할 수 있게 되었습니다.
static void test(Object obj) { |
Module Import Declarations (Preview)
모듈의 모든 패키지를 한 번에 import 할 수 있게 되었습니다.
import module java.base; // java.base 모듈의 모든 패키지 import |
Markdown in Javadoc
Javadoc 주석에서 Markdown 문법을 사용할 수 있게 되었습니다.
/// # Header |
Java 24 (2025년 3월)
Improved Pattern Matching
패턴 매칭이 더욱 강력해지고 사용하기 편리해졌습니다.
Flexible Constructor Bodies (Second Preview)
생성자 본문에서 super() 호출 전에 더 많은 작업을 수행할 수 있게 되었습니다.
Stream Gatherers
Stream API에 커스텀 중간 연산을 추가할 수 있는 Gatherers API가 도입되었습니다.
// 슬라이딩 윈도우 예시 |
Java 25 (2025년 9월) - LTS
Java 25는 최신 LTS 버전으로, AI 개발 지원과 성능 개선에 중점을 둔 18개의 JEP가 포함되었습니다.
Primitive Types in Patterns (정식 기능)
primitive 타입을 포함한 완전한 패턴 매칭이 정식 기능이 되었습니다. 이제 instanceof와 switch에서 모든 primitive 타입을 사용할 수 있습니다.
public static String formatValue(Object obj) { |
Structured Concurrency (Fifth Preview)
구조화된 동시성 API가 계속 개선되고 있습니다.
try (var scope = new StructuredTaskScope.ShutdownOnSuccess<String>()) { |
Stable Values (Preview)
값비싼 계산 결과를 효율적으로 공유할 수 있는 새로운 메커니즘입니다. Scoped Values와 유사하지만, 불변성을 보장하고 성능에 최적화되어 있습니다.
private static final StableValue<HeavyResource> RESOURCE = |
Compact Object Headers
객체 헤더를 압축하여 메모리 사용량을 줄이는 기능이 정식 옵션이 되었습니다. 이제 -XX:+UnlockExperimentalVMOptions 플래그 없이도 사용할 수 있습니다.
java -XX:+UseCompactObjectHeaders MyApplication |
Vector API (Incubator)
SIMD(Single Instruction Multiple Data) 연산을 활용하여 벡터 연산을 최적화할 수 있습니다. AI와 머신러닝 워크로드에 특히 유용합니다.
static final VectorSpecies<Float> SPECIES = FloatVector.SPECIES_PREFERRED; |
Enhanced JDK Flight Recorder
리눅스 환경에서 CPU 프로파일링 정확도가 크게 개선되었습니다. 애플리케이션의 성능 병목 지점을 더 정확하게 파악할 수 있습니다.
PEM Encodings of Cryptographic Objects (Preview)
암호화 관련 객체를 PEM 형식으로 쉽게 인코딩하고 디코딩할 수 있는 API가 추가되었습니다.
// 공개키를 PEM 형식으로 인코딩 |
LTS 버전 정리
자바의 LTS(Long-Term Support) 버전은 장기간 지원을 받을 수 있어 기업 환경에서 주로 사용됩니다.
- Java 8 (2014년 3월): 2030년까지 지원 예정
- Java 11 (2018년 9월): 2026년까지 지원 예정
- Java 17 (2021년 9월): 2029년까지 지원 예정
- Java 21 (2023년 9월): 2031년까지 지원 예정
- Java 25 (2025년 9월): 2033년까지 지원 예정 (최소 8년 보증)
LTS 버전 사이의 간격은 대략 2-3년이며, 각 LTS 버전은 최소 8년간의 상업적 지원을 받습니다.
버전 선택 가이드
새로운 프로젝트 시작 시
현재 시점(2025년)에서 새로운 프로젝트를 시작한다면 Java 21 또는 Java 25를 추천합니다. 두 버전 모두 LTS 버전이며, 현대적인 자바의 모든 기능을 활용할 수 있습니다.
기존 프로젝트 마이그레이션
- Java 8 → Java 11: 가장 많이 진행되는 마이그레이션 경로입니다. 비교적 안정적이고 많은 레퍼런스가 있습니다.
- Java 11 → Java 17: 현재 진행 중인 많은 프로젝트들이 선택하는 경로입니다.
- Java 17 → Java 21: 가상 스레드와 같은 혁신적인 기능을 사용하고 싶다면 고려해볼 만합니다.
학습 목적
최신 LTS 버전인 Java 21이나 Java 25를 사용하는 것을 추천합니다. 최신 기능들을 배우면서 자바의 발전 방향을 이해할 수 있습니다.
마치며
Java 8부터 Java 25까지의 발전 과정을 살펴보았습니다. 자바는 람다와 스트림으로 시작해서 Records, Sealed Classes, 패턴 매칭, 가상 스레드 등 현대적인 프로그래밍 패러다임을 지속적으로 도입해왔습니다.
특히 최근의 자바는 다음과 같은 방향으로 발전하고 있습니다:
- 코드 간결성: Records, 패턴 매칭, var 등으로 보일러플레이트 코드 감소
- 성능 개선: 가상 스레드, Vector API 등으로 동시성과 연산 성능 향상
- 안전성 강화: Sealed Classes, 개선된 Null 처리 등으로 타입 안전성 향상
- 개발자 경험: Text Blocks, Switch 표현식 등으로 가독성과 생산성 향상
- AI 지원: Vector API, 최적화된 메모리 관리 등 AI/ML 워크로드 지원
자바는 여전히 활발하게 발전하고 있으며, 6개월마다 새로운 버전을 출시하면서 현대적인 프로그래밍 언어로서의 경쟁력을 유지하고 있습니다. LTS 버전을 중심으로 안정성을 유지하면서도, 혁신적인 기능들을 빠르게 도입하는 전략은 앞으로도 계속될 것으로 보입니다.