JAVA에서 Platform Thread와 Virtual Thread

발행: (2026년 2월 4일 오전 03:07 GMT+9)
6 분 소요
원문: Dev.to

Source: Dev.to

Platform Threads

Java에서 고전적인 스레드 모델을 플랫폼 스레드라고 합니다. 이는 운영 체제에 직접 매핑되는 전통적인 스레드입니다.

Thread thread = new Thread(() -> {
    doWork();
});
thread.start(); // Starts a new platform thread

처음에는 강력하게 느껴집니다—실제 병렬 작업과 멀티태스킹을 얻을 수 있기 때문이죠. 하지만 다음과 같은 상황에서 문제가 발생합니다:

  • 스레드를 너무 많이 생성 → 애플리케이션이 느려짐.
  • 수천 개의 요청을 처리 → 스레드 풀 고갈.
  • 블로킹 I/O 수행 → 스레드가 외부 작업을 기다리며 대기 상태가 됨.

왜일까요? 플랫폼 스레드는 OS 스레드에 직접 매핑되기 때문입니다:

  • 하나의 Java 스레드 = 하나의 OS 스레드.
  • OS 스레드는 비용이 많이 듭니다(큰 스택, 스케줄링 오버헤드).

그 결과 개발자들은 다음과 같은 방법을 사용하게 됩니다:

  • 고정 크기 스레드 풀.
  • 비동기 API.
  • 리액티브 프로그래밍.
  • 복잡한 실행 모델.

이러한 우회 방법은 욕구에서 나온 것이 아니라 플랫폼 스레드의 확장성 한계 때문에 생깁니다.

핵심 문제

I/O 작업 중 스레드는:

  • 계산을 수행하지 않는다.
  • CPU를 사용하지 않는다.
  • 단지 외부 작업이 완료될 때까지 기다린다.

그럼에도 불구하고 희소한 OS 자원을 차지합니다. 바로 여기서 가상 스레드가 등장합니다.

Virtual Threads — Lightweight & Scalable

가상 스레드는 JVM이 관리하는 경량 스레드로, OS 스레드의 오버헤드 없이 수백만 개의 동시 작업을 수행할 수 있습니다.

Thread thread = Thread.startVirtualThread(() -> {
    doWork();
});
  • 플랫폼 스레드와 동일한 프로그래밍 모델 및 블로킹 스타일.
  • JVM에 의해 생성·스케줄링되며 OS 스레드에 영구적으로 연결되지 않음.
  • 플랫폼 스레드에 비해 매우 저렴함.

실제로 일어나는 일

  • Running: 가상 스레드는 carrier(플랫폼) 스레드에 탑재됩니다.
  • Blocking: 가상 스레드가 park 상태가 되면 carrier 스레드가 해제됩니다.
  • Unblocked: 가상 스레드는 사용 가능한 어떤 carrier 스레드에서도 재개됩니다.

즉, 차단되는 것은 가상 스레드 자체뿐이며, 기반이 되는 OS 스레드는 차단되지 않습니다. 이는 플랫폼 스레드의 확장성 병목을 해소합니다:

  • 블로킹 I/O가 더 이상 OS 스레드를 낭비하지 않음.
  • 스레드 풀이 더 이상 절대적인 한계가 아님.
  • 간단한 블로킹 코드도 대규모 동시성을 지원할 수 있음.

가상 스레드는 블로킹을 없애는 것이 아니라, 블로킹의 비용을 없애는 것입니다.

How They Differ

핵심 차이는 각 스레드 유형이 블로킹을 처리하는 방식에 있습니다:

AspectPlatform ThreadVirtual Thread
MappingOne‑to‑one with OS threadMany virtual threads share carrier threads
Blocking impactBlocks an OS threadBlocks only the virtual thread
Creation costHigh (stack, scheduling)Low (JVM‑managed)
ScalabilityLimited by OS resourcesCan handle millions of concurrent tasks

When It Makes Sense to Use One Over the Other

Use Virtual Threads When

  • 작업이 I/O‑중심일 때(예: 많은 동시 요청 처리).
  • 데이터베이스, 외부 API, 파일 시스템 등을 기다릴 때.
  • 웹 서버, API, 마이크로서비스를 구축할 때.
  • 단순하고 블로킹 방식의 코드를 원하면서도 확장성을 유지하고 싶을 때.

Use Platform Threads When

  • 작업이 CPU‑집약적일 때.
  • OS와의 긴밀한 상호작용이 필요할 때.
  • 스레드 고정(pin), 네이티브 호출 또는 기타 저수준 작업이 포함될 때.

Practical Guideline

Use virtual threads for waiting; use platform threads for computing.

이 규칙은 대부분의 실제 상황에서 적용됩니다.

가상 스레드는 Java를 더 빠르게 만들지는 않지만, 스레드 풀 한계를 신경 쓰지 않고도 간단한 블로킹 코드를 쉽게 작성할 수 있게 해줍니다.

Back to Blog

관련 글

더 보기 »

두 버그, 하나의 증상

배경: Raku MCP SDK에서 SSE 클라이언트 전송을 구현하면서 겪은 디버깅 전쟁 이야기. 작업은 간단해 보였다: 레거시 SSE 전송을 추가하는 것.