[GRADU] Java 21 버전 설정과 Virtual Thread

1 분 소요

이번 프로젝트는 Java 21 LTS(Long-Term Support) 버전으로 설정하였다.

스크린샷_2025-07-22_오후_5 06 58

선택한 이유

  1. LTS 지원

    Java 21은 2023년 9월 릴리즈된 장기 지원(LTS) 버전이다.

    Java 17 이후 약 2년 만에 나온 LTS로, 향후 수년간의 안정성과 보안 패치를 기대할 수 있다.

  2. Virtual Thread 지원

    Java 19부터 프리뷰로 제공되던 Virtual Thread가 Java 21에서 정식 기능으로 포함되었다.

    높은 동시성 처리가 필요한 웹 애플리케이션에 적합한 기능이다.


다른 선택지로는 Java 17과 24가 있었는데,

Java 24는 2025년 3월에 출시되어 새롭고 실험적인 기능이 많이 포함되어 있지만, LTS 버전이 아니기 때문에 안정성과 생태계 호환성 측면에서 불확실성이 있었다.

결국 Java 21의 Virtual Thread 기능을 활용한 성능 개선 효과를 얻고자 이 버전을 선택하게 되었다.


Java 21 주요 특징

기능 상태 설명
Virtual Thread 정식 도입 경량 스레드로 동시성 처리 성능 향상
Record Patterns 정식 도입 레코드 타입을 쉽게 분해하여 사용
Pattern Matching for switch 정식 도입 switch 문에서 타입 패턴 매칭 지원
SequencedCollection 인터페이스 정식 도입 순서가 있는 컬렉션을 위한 새로운 인터페이스
Structured Concurrency Incubator 동시성 코드의 가독성과 안정성 향상
String Template Preview 문자열 템플릿 기능 제공
Foreign Function & Memory API 3rd Preview 네이티브 코드와 메모리 접근 지원


Virtual Thread란?

Virtual Thread는 기존의 플랫폼 스레드(Operating System Thread)와 달리, 경량화된 스레드이다.

Thread.ofVirtual().start(() -> { ... }) 와 같이 생성할 수 있으며, 수천~수백만 개까지도 생성할 수 있다.

기존 스레드의 문제점

  • 스레드당 메모리 비용이 크다 (기본 1MB 스택)
  • 컨텍스트 스위칭 비용이 크다
  • 수천 개 이상 생성이 어렵다

Virtual Thread의 장점

  • 매우 가볍고 생성/소멸 비용이 적다
  • 스케줄링은 Java 내부 스케줄러가 담당
  • Executors.newVirtualThreadPerTaskExecutor()로 쉽게 병렬 작업 구성 가능
  • 웹 서버나 I/O 처리에 매우 유리하다

실전 적용 예시

try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
    List<Callable<String>> tasks = List.of(
        () -> fetch("https://api1.com"),
        () -> fetch("https://api2.com")
    );
    executor.invokeAll(tasks);
}

기존 플랫폼 스레드의 경우:

  • 이 작업이 blocking I/O라면, 스레드 하나가 완전히 점유된 채로 데이터를 기다린다.
  • 수백, 수천 개 요청이 있으면 그만큼 OS 스레드를 생성해야 한다 → 리소스 폭발, 컨텍스트 스위칭 비용 증가

Virtual Thread는 blocking I/O 작업 시 다음과 같은 메커니즘으로 작동한다:

  1. Virtual Thread가 blocking I/O 작업(예: 네트워크 요청)을 만나면, JVM은 해당 Virtual Thread를 ‘마운트 해제(unmount)’한다.
  2. 이때 해당 Virtual Thread가 사용하던 캐리어 스레드(Carrier Thread, 실제 OS 스레드)는 다른 Virtual Thread를 실행하는 데 재사용된다.
  3. I/O 작업이 완료되면, Virtual Thread는 다시 캐리어 스레드에 ‘마운트’되어 실행을 계속한다.
  4. 이러한 방식으로 적은 수의 OS 스레드로도 수많은 Virtual Thread를 효율적으로 실행할 수 있다.

카테고리:

업데이트: