본문 바로가기
JAVA

자바 성능의 혁명: Java 21 가상 스레드(Virtual Thread) 도입하기

by 공부 안하고 싶은 사람 2026. 3. 25.
반응형
Java Modernization Series 01

스레드당 1MB는 옛말,
Virtual Thread가 가져온 성능 혁명

 

안녕하세요, code-resting입니다. 자바 개발자들을 오랫동안 괴롭혔던 문제 중 하나는 '스레드 비용'이었습니다. 요청 하나당 스레드 하나를 할당하는 방식은 동시 접속자가 늘어날수록 메모리와 컨텍스트 스위칭 비용을 감당하기 힘들었죠. 하지만 Java 21에서 정식 도입된 가상 스레드는 이 공식을 완전히 깨버렸습니다.

1. 플랫폼 스레드 vs 가상 스레드

기존의 자바 스레드(플랫폼 스레드)는 운영체제(OS)의 커널 스레드와 1:1로 매핑되었습니다. 이는 생성 비용이 비싸고 개수도 제한적이었죠.

  • 기존 방식: 스레드 하나가 수백 KB~1MB의 메모리를 점유함. 수천 개만 생성해도 OOM 위험.
  • 가상 스레드: JVM 수준에서 관리되는 경량 스레드. 스레드당 수십 바이트 수준으로, 수백만 개를 동시에 띄워도 문제가 없음.

2. 어떻게 이렇게 빠를까? (Mount/Unmount)

가상 스레드의 핵심은 논블로킹(Non-blocking)처럼 동작하면서 코드는 동기(Synchronous) 방식으로 짤 수 있다는 점입니다.

동작 메커니즘:

  1. 가상 스레드가 I/O 작업(DB 조회, API 호출 등)을 만나 대기 상태가 되면,
  2. 실제 실행을 담당하던 OS 스레드(Carrier Thread)에서 자신을 분리(Unmount)합니다.
  3. OS 스레드는 다른 가상 스레드를 즉시 처리하러 가고, I/O가 완료되면 다시 합체(Mount)되어 작업을 이어갑니다.

3. 실전 적용: 톰캣(Tomcat)을 가볍게!

Spring Boot 3.2 이상을 사용한다면 단 한 줄의 설정으로 내장 톰캣의 스레드 모델을 가상 스레드로 바꿀 수 있습니다.

# application.yml
spring:
  threads:
    virtual:
      enabled: true

이제 더 이상 max-threads 개수를 고민하며 스레드 풀 튜닝에 시간을 쏟지 않아도 됩니다.

4. 주의사항: Pinning 현상

⚠️ 모든 곳이 정답은 아닙니다.

synchronized 블록 내부에서 가상 스레드를 사용하면 OS 스레드가 해제되지 못하고 고정되는 Pinning 현상이 발생할 수 있습니다. 이를 방지하려면 ReentrantLock으로 교체하는 등의 작업이 필요합니다.

💡 마무리하며

가상 스레드는 자바의 비동기 프로그래밍 난이도를 대폭 낮춰준 축복과 같은 기능입니다. 리액티브 프로그래밍(WebFlux)의 복잡함 없이도 높은 처리량(Throughput)을 얻을 수 있죠. 2026년 백엔드 아키텍처를 고민하신다면, 가장 먼저 Java 21 업그레이드를 검토해 보시기 바랍니다.

© 2026 code-resting. All rights reserved.

반응형

댓글