Post

Java 21 Features with Spring

πŸ’‘ Spring Boot 3.2 + Java 21 연계 ν™œμš© μ˜ˆμ‹œ

1. βœ… Virtual Threads + Spring Boot 3.2

Java 21의 가상 μŠ€λ ˆλ“œ(Virtual Thread) 와 Spring Boot 3.2λŠ” 기본적으둜 ν˜Έν™˜λ©λ‹ˆλ‹€.

πŸ“Œ μ£Όμš” 효과

  • κΈ°μ‘΄ @RestController 기반 μ„œλΈ”λ¦Ώ API (Tomcat) 도 가상 μŠ€λ ˆλ“œλ‘œ μ‹€ν–‰ κ°€λŠ₯
  • 비동기 ν”„λ‘œκ·Έλž˜λ° 없이도 κ³ μ„±λŠ₯ 처리 κ°€λŠ₯ β†’ 동기식 μ½”λ“œλ‘œλ„ 높은 λ™μ‹œμ„±

βš™οΈ μ„€μ • 방법

1
2
3
4
# application.yml
server:
  tomcat:
    protocol: org.apache.coyote.http11.Http11Nio2Protocol
1
2
3
4
@Bean
public TomcatProtocolHandlerCustomizer<?> protocolHandlerVirtualThreadExecutor() {
    return protocolHandler -> protocolHandler.setExecutor(Executors.newVirtualThreadPerTaskExecutor());
}

πŸ‘ κΈ°λŒ€ 효과

  • 기쑴의 WebClient, CompletableFuture, @Async 없이도 λ™μ‹œμ„± ν–₯상
  • μš”μ²­ μˆ˜κ°€ λ§Žμ€ API μ„œλ²„μ— 적합 (예: λŒ€μš©λŸ‰ 배치 처리, IO-bound μ„œλΉ„μŠ€)

2. βœ… Scoped Values

ThreadLocal λŒ€μ²΄: 가상 μŠ€λ ˆλ“œμ—μ„œλ„ μ•ˆμ „ν•˜κ²Œ μ‚¬μš© κ°€λŠ₯

1
2
3
4
5
6
7
ScopedValue<String> USER_ID = ScopedValue.newInstance();

public void controller() {
    ScopedValue.where(USER_ID, "user-123").run(() -> {
        service(); // λ‚΄λΆ€μ μœΌλ‘œ USER_ID.get() μ‚¬μš© κ°€λŠ₯
    });
}
  • βœ… νŠΈλžœμž­μ…˜ ID, μš”μ²­μž ID, νƒ€μž„μ‘΄ λ“± μ»¨ν…μŠ€νŠΈ μ „νŒŒμ— 적합
  • 🚫 κΈ°μ‘΄ ThreadLocal은 가상 μŠ€λ ˆλ“œμ™€ ꢁ합이 μ•ˆ μ’‹μŒ β†’ 이걸둜 λŒ€μ²΄ κ°€λŠ₯

3. βœ… Pattern Matching for switch / Record Patterns

μš”μ²­ DTO, μ»€λ§¨λ“œ ν•Έλ“€λŸ¬ λ“±μ—μ„œ νŒ¨ν„΄ 기반 λΆ„κΈ° 처리

1
2
3
4
5
6
7
8
9
10
sealed interface Command permits CreateUser, DeleteUser {}
record CreateUser(String name) implements Command {}
record DeleteUser(Long id) implements Command {}

public void handle(Command command) {
    switch (command) {
        case CreateUser(var name) -> userService.create(name);
        case DeleteUser(var id) -> userService.delete(id);
    }
}
  • πŸ’‘ λ³΅μž‘ν•œ if-else / instanceof λΆ„κΈ°λ¬Έ 제거
  • μ„œλΉ„μŠ€ κ³„μΈ΅μ˜ λΆ„κΈ° λ‘œμ§μ„ λͺ…ν™•ν•˜κ³  νƒ€μž… μ•ˆμ „ν•˜κ²Œ κ΅¬ν˜„ κ°€λŠ₯

4. βœ… Foreign Function & Memory API

아직 Springμ—μ„œλŠ” 직접 ν™œμš© 사둀가 μ μ§€λ§Œ, κ³ μ„±λŠ₯ λ„€μ΄ν‹°λΈŒ 호좜 μ‹œ μ‚¬μš© κ°€λŠ₯
예: C 기반 μŒμ› 뢄석 라이브러리, μ˜μƒ 인코딩 λ“±κ³Όμ˜ 연동에 ν™œμš©


5. βœ… Sequenced Collections

μ»¨νŠΈλ‘€λŸ¬λ‚˜ μ„œλΉ„μŠ€μ—μ„œ μˆœμ„œκ°€ μ€‘μš”ν•œ 데이터 λ‹€λ£° λ•Œ λͺ…μ‹œμ  μΈν„°νŽ˜μ΄μŠ€ μ‚¬μš© κ°€λŠ₯

1
2
3
SequencedSet<String> history = new LinkedHashSet<>();
history.addFirst("eventA");
history.addLast("eventB");
  • LinkedHashSet, LinkedHashMap 등을 더 λͺ…ν™•ν•˜κ²Œ ν™œμš© κ°€λŠ₯
  • ν…œν”Œλ¦Ώ μ—”μ§„, νžˆμŠ€ν† λ¦¬ 둜그, 순차 UI λ Œλ”λ§μ—μ„œ 유용

βœ… 정리: 싀무 적용 κ°€μ΄λ“œ

κΈ°λŠ₯Spring 싀무 ν™œμš©
Virtual ThreadsTomcat 가상 μŠ€λ ˆλ“œ μ„€μ • β†’ IO μ„±λŠ₯ ν–₯상
Scoped Valuesμš”μ²­ μ»¨ν…μŠ€νŠΈ μ „νŒŒ (ex. userId, traceId)
Record PatternsCommand/DTO 처리 둜직 κ°„κ²°ν™”
Sequenced Collectionsμˆœμ„œ μžˆλŠ” 데이터 처리 λͺ…ν™•ν•˜κ²Œ
Foreign Function APIJNI λŒ€μ²΄ (λ„€μ΄ν‹°λΈŒ 라이브러리 호좜)
This post is licensed under CC BY 4.0 by the author.