TokyoAJ

도쿄아재

SPRINGBOOT 2025.09.20

Java 버전별 특징 (Java 18 → 24)

Java 18 (2022)

1) UTF-8 기본 문자셋(기본값 통일)

  1. 운영체제/로케일에 관계 없이 기본 인코딩이 UTF-8.
System.out.println(Charset.defaultCharset()); // UTF-8

해설: 레거시 환경에서 발생하던 인코딩 혼선을 낮춰줍니다.

2) Simple Web Server (jwebserver)

  1. 정적 파일을 서빙하는 초경량 개발용 웹 서버.
# 현재 디렉토리를 8000번 포트로 서빙
jwebserver --directory . --port 8000

해설: 문서/샘플 테스트에 유용. 보안/프락시 등은 최소한.

3) JavaDoc @snippet

  1. 코드 조각을 문서에 삽입.
/**
* Example usage:
* {@snippet :
* List<Integer> xs = List.of(1,2,3);
* System.out.println(xs);
* }
*/
public class SnippetExample {}

해설: JavaDoc 내 코드 유지/검증이 쉬워집니다.

4) Vector API / FFM API(진행형, Incubator/Preview)

// Vector API 개념 예시 (패키지/네임은 버전에 따라 다를 수 있음)
var sp = FloatVector.SPECIES_PREFERRED;
var a = FloatVector.broadcast(sp, 2.0f);
var b = FloatVector.broadcast(sp, 4.0f);
var c = a.mul(b); // lane-wise 곱
System.out.println(c);

해설: 수치 연산을 SIMD로 가속. (실사용 시 --add-modules 설정 필요)


Java 19 (2022)

1) Virtual Threads (Preview, Project Loom)

try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
List<Callable<String>> tasks = IntStream.range(0, 5)
.mapToObj(i -> (Callable<String>) () -> "task-" + i)
.toList();
var results = executor.invokeAll(tasks);
for (var r : results) System.out.println(r.get());
}

해설: 경량 스레드로 동시성 코드를 단순화. 블로킹 I/O도 저렴해집니다.

2) Record Patterns (Preview)

record Point(int x, int y) {}

static String locate(Object obj) {
return switch (obj) {
case Point(int x, int y) when x == 0 && y == 0 -> "origin";
case Point(int x, int y) -> "point(" + x + "," + y + ")";
default -> "unknown";
};
}

해설: record를 패턴으로 분해 매칭해 값 추출을 간결하게.

3) Pattern Matching for switch (더 성숙한 Preview)

static String toStr(Object o) {
return switch (o) {
case String s when s.isEmpty() -> "<empty>";
case String s -> "S:" + s;
case Integer i && i > 0 -> "positive int";
default -> "other";
};
}

4) Structured Concurrency (Incubator)

// 개념 예: 여러 태스크를 구조적으로 묶어 취소/예외/수명 관리
try (var scope = new StructuredTaskScope.ShutdownOnFailure()) {
var f1 = scope.fork(() -> callServiceA());
var f2 = scope.fork(() -> callServiceB());
scope.join().throwIfFailed();
return combine(f1.result(), f2.result());
}

해설: 관련 작업을 묶어 수명/에러/취소를 한 덩어리로 관리.


Java 20 (2023)

1) Scoped Values (Incubator)

// ScopedValue는 ThreadLocal의 안전한 대안 (버전에 따라 API 다를 수 있음)
static final ScopedValue<String> USER = ScopedValue.newInstance();

ScopedValue.where(USER, "kim").run(() -> {
System.out.println("user = " + USER.get()); // "kim"
});

해설: 불변 컨텍스트를 호출 트리에 안전하게 전달.

2) Record Patterns (2nd Preview) / switch 패턴(4th Preview)

record Box<T>(T value) {}

static String unbox(Object o) {
return switch (o) {
case Box(String s) -> s;
case Box(Integer i) -> "int=" + i;
default -> "unknown";
};
}

3) FFM API / Virtual Threads / Structured Concurrency의 재프리뷰

  1. API 안정화 진행. 사용하는 JDK 버전에 맞춰 패키지·옵션 확인 필요.


Java 21 (2023, LTS)

1) Virtual Threads 정식

Thread.ofVirtual().start(() -> System.out.println("hello vt")).join();

해설: 비동기 I/O를 쓰지 않아도 간단한 동시성 구현 가능.

2) Record Patterns 정식 + Pattern Matching for switch 정식

record Range(int start, int end) {}

static int length(Object o) {
return switch (o) {
case Range(int s, int e) when s <= e -> e - s;
case String s -> s.length();
default -> 0;
};
}

3) Sequenced Collections

SequencedCollection<String> sc = new ArrayList<>();
sc.addFirst("a"); sc.addLast("b");
System.out.println(sc.getFirst()); // a
System.out.println(sc.getLast()); // b

해설: 앞/뒤 모두에서 다루기 쉬운 양방향 순서 컬렉션.

4) String Templates (Preview)

// JEP 430: String templates (Preview) — 프로세서: STR
String name = "Kim";
int n = 3;
String msg = STR."Hello, {name}! n={n}";
System.out.println(msg);

해설: 템플릿 처리기를 통해 문자열·검증·포맷을 선언적으로.


Java 22 (2024)

1) String Templates (2nd Preview)

String who = "world";
String s = STR."Hi, {who}";

해설: 템플릿 안전성/가독성 개선 테스트 계속.

2) Stream Gatherers (Preview)

// 예: 누적 스캔(부분 합) 같은 패턴을 스트림 파이프라인에 통합
var runningSums = Stream.of(1,2,3,4,5)
.gather(Gatherers.scan(0, Integer::sum)) // [1,3,6,10,15]
.toList();
System.out.println(runningSums);

해설: Gatherers.*로 스트림 수집/변환을 강력하게 확장.

3) Scoped Values (2nd Incubator) / Vector/FFM/Structured Concurrency 재진전

  1. API 다듬기 지속.


Java 23 (2024)

1) Stream Gatherers (2nd Preview)

var windows = Stream.of(1,2,3,4,5,6)
.gather(Gatherers.windowFixed(3)) // [ [1,2,3], [4,5,6] ]
.toList();
System.out.println(windows);

2) String Templates (Preview 기능이 제거됨)

  1. 템플릿 실험은 중단/보류. (향후 재도입 가능성은 별개 이슈)

3) FFM/Vector/Scoped Values 등 재프리뷰/인큐베이터

  1. 이식성/안전성/성능을 위한 세부 다듬기.


Java 24 (2025)

1) Stream Gatherers 정식

// 누적/윈도우/폴드 등 다양한 패턴을 정식 API로
var folded = Stream.of("a","b","c")
.gather(Gatherers.fold(
new StringBuilder(),
(sb, s) -> sb.append(s.toUpperCase()),
StringBuilder::append)) // 개념 예시
.map(StringBuilder::toString)
.toList();
System.out.println(folded);

해설: 스트림 파이프라인에서 고급 수집/변환을 표준화.

2) 패턴 매칭 확장(원시 타입 포함)

static String inspect(Object o) {
return switch (o) {
case int i -> "int:" + i; // 원시 타입 패턴
case long l -> "long:" + l;
case double d -> "double:" + d;
case String s && s.isBlank() -> "<blank>";
default -> "other";
};
}

해설: Object에 박싱돼 넘어온 값도 언박싱+패턴으로 간결 처리.

3) Compact Object Headers (Incubator, Project Lilliput)

  1. 객체 헤더 축소로 힙 효율 향상. (JVM 옵션 필요, 실험적)

4) Generational Shenandoah GC (Experimental)

# 개념: 실험적 GC 활성화 예시(옵션은 빌드/배포판에 따라 상이)
java -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:ShenandoahGCMode=generational ...

해설: 젠네레이션 기반으로 페이즈/일시중지 개선 목표.

5) 보안/플랫폼/언어 생태 관련 변화

  1. Key Derivation Function API 추가(보안 키 파생 표준화).
  2. Module Import Declarations(실험/미리보기 성격): 모듈 선언 편의.
  3. Simple Source Files & Instance main 개선: 더 간단한 엔트리 작성.
  4. sun.misc.Unsafe 경고 강화, Windows 32-bit 포트 제거.


실무 Tips (18~24 묶음)

  1. 동시성: 대규모 I/O → Virtual Threads 우선 검토. 태스크 묶음 관리는 Structured Concurrency.
  2. 컨텍스트 전달: ThreadLocal 대신 Scoped Values(Incubator) 고려(불변·안전).
  3. 문자열/템플릿: String Templates는 21~22에서만 Preview. 23에서 제거되었으니 버전별 분기 필요.
  4. 고성능 수치/스트림: Vector API(하드웨어 의존), Stream Gatherers(24 정식)로 파이프라인 강화.
  5. 네이티브 연동: FFM API는 버전별 패키지/네이밍 변화를 따라가며 마이그레이션.
  6. JVM 옵션: Incubator/Experimental 기능은 모듈 추가/옵션 활성화가 필요할 수 있음.


댓글