NotificationService.save)
플랫폼 스레드는 블로킹 대기 중에도 OS 스레드를 점유하기 때문에 동시 요청 증가 시 스레드 풀이 소진되는 구조적 한계가 있다. 가상 스레드는 블로킹 구간에서 OS 스레드를 반환하기 때문에 스레드 풀 소진 없이 더 많은 동시 요청을 처리할 수 있다.
| 지표 | 100 VUs | 300 VUs | 변화 |
|---|---|---|---|
| 처리량 (req/s) | 5,385 | 4,357 | ▼ 19% 감소 |
| 평균 응답시간 | 15.27ms | 47.62ms | ▲ 3.1배 증가 |
| p(90) | 27.09ms | 84.88ms | ▲ 3.1배 증가 |
| p(95) | 33.89ms | 92.46ms | ▲ 2.7배 증가 |
| 실패율 | 0.03% | 0.08% | ▲ 증가 |
VUs가 3배 증가했음에도 처리량이 오히려 19% 감소했다. 일반적으로 요청 수가 늘면 처리량도 함께 증가해야 하지만, Tomcat 스레드 풀(200개)이 소진되면서 신규 요청을 받지 못하고 응답 지연과 처리량 감소가 동시에 발생한 것으로, 플랫폼 스레드의 구조적 한계를 수치로 확인할 수 있다.
POST /test/notifications/trigger?userId=${__VU}Tomcat 기본 스레드(200개) 한계 이하 구간에서 두 스레드 모델의 기준선을 측정한다. 스레드 풀에 여유가 있는 정상 부하 상태에서 플랫폼 스레드와 가상 스레드 간 차이가 존재하는지 확인한다.
| 지표 | 플랫폼 스레드 | 가상 스레드 | 차이 |
|---|---|---|---|
| 처리량 (req/s) | 5,385 | 5,491 | ▲ 2% 증가 |
| 평균 응답시간 | 15.27ms | 13.61ms | ▼ 11% 감소 |
| p(90) | 27.09ms | 19.86ms | ▼ 27% 감소 |
| p(95) | 33.89ms | 27.2ms | ▼ 20% 감소 |
| 실패율 | 0.03% | 0.02% | 유사 |
두 스레드 모델 간 유의미한 차이가 없다.
100 VUs는 Tomcat 기본 스레드(200개) 한계의 절반 수준으로, 스레드 풀에 여유가 충분하다. DB 커넥션 대기로 인한 블로킹이 발생하더라도 플랫폼 스레드가 이를 흡수할 수 있는 상태이기 때문에 가상 스레드의 이점이 드러나지 않는다.