자바21 의 성능에대한 고찰

kkjj·2025년 4월 22일
0

📌 들어가며

JDK21 이 나온지 거의 2년이 되가는 시점에 너무 늦은 글이기도 하나 최근에 프로젝트를 하나 새로 만들면서 도입하면서 글을 새로 작성해본다. Java 21이 정식 출시되면서 가장 주목받는 기능 중 하나는 Virtual Thread이다.
기존의 무거운 플랫폼 스레드와는 달리, 경량화된 경합 구조를 제공함으로써 병렬성 및 확장성에서 큰 이점을 준다.
이번 글에서는 Java 21의 Virtual Thread에 대한 이해와, 이를 실제 프로젝트에 어떻게 적용했는지 정리해보았다.

🧠 Java 21의 핵심: Virtual Thread란?

✅ 기존 Thread의 한계

new Thread() 혹은 ExecutorService 기반의 스레드는 OS 레벨 자원을 직접 사용한다.

수천 개 이상의 동시 처리에 한계가 존재 (스레드 생성 비용, 컨텍스트 스위칭 비용 등)

블로킹 I/O를 처리할 때, 해당 스레드가 자원을 점유한 채 대기 → 낭비

✅ Virtual Thread의 등장

java.lang.Thread.ofVirtual().start() 로 생성

경량화된 스레드: OS가 아닌 JVM 내부 스케줄러에서 관리

수천~수만 개의 스레드도 부담 없이 생성 가능

기존 API (예: Runnable, ExecutorService)와도 호환됨 → 러닝커브 낮음


💡 왜 Virtual Thread인가?

"블로킹 코드를 유지하면서도 비동기적 성능을 확보할 수 있다."

  • 기존에는 CompletableFuture, Reactor 같은 복잡한 비동기 방식 필요
  • Virtual Thread는 블로킹 API를 그대로 사용해도 스레드 낭비가 없음
  • 코드 가독성 + 생산성 향상

🔍 실제 프로젝트 적용: VSearch (검색 시스템)

✅ 목표

  • Java 21 기반 고성능 텍스트 검색 시스템 개발
  • 문서 검색 + 검색 기록 저장 + 자동완성 캐시 처리

✅ 기술 스택

  • Java 21
  • Spring Boot 3.x
  • MySQL
  • JPA (Hibernate)
  • Virtual Thread + CompletableFuture

자세한 코드 보실분은 GitHub에 올려놨습니다.
-> https://github.com/LeeKangJun33/-Virtual-Threads.git

✅ 주요 코드 예시

ExecutorService executor = Executors.newVirtualThreadPerTaskExecutor();

List<CompletableFuture<SearchResult>> futures = keywords.stream()
    .map(keyword -> CompletableFuture.supplyAsync(() -> searchService.search(keyword), executor))
    .toList();

List<SearchResult> results = futures.stream()
    .map(CompletableFuture::join)
    .toList();

Virtual Thread로 각 검색 요청을 병렬 처리

Spring Boot + JPA와도 무리 없이 호환됨

기존 리액티브 방식보다 간결해져서 유지보수 에도 좋아진거같다.

⚙️ 느낀 점

Virtual Thread 덕분에 복잡한 비동기 처리 없이도 성능 향상이 가능했습니다.

검색, 크롤링, 외부 API 요청 등 병렬성이 필요한 작업에 최적입니다.

아직 실서비스 적용 전에는 안정성 테스트가 필요하지만, 충분히 실전 투입 가능한 기술이라고 생각합니다. 아직 좀더 다듬어야 할 부분이 많지만 그래도 충분하다고 생각합니다.

✅ 마무리

Java는 안정적이지만 무겁고 느리다는 인식이 있었지만,
Java 21의 Virtual Thread는 그런 편견을 확실히 깨줄 수 있는 변화 라고 생각합니다.

profile
백엔드

0개의 댓글