STW

GC가 사용하지 않는 객체를 정리할 때 모든 애플리케이션 스레드를 일시적으로 멈추는 현상입니다.

왜 멈춰야 하는가

[ GC 없이 그냥 정리하면? ]

스레드 A: 객체 X를 사용 중 ──→ "X.name 읽어야지"
GC:      객체 X를 회수 ──→ "X 안 쓰니까 삭제!"
                              ↑ 동시에 일어나면 크래시

[ 해결: 모두 멈추고 정리 ]

스레드 A: 멈춤 ─────────────────── 재개
스레드 B: 멈춤 ─────────────────── 재개
GC:            안전하게 객체 정리

GC가 객체를 옮기거나 삭제하는 동안 다른 스레드가 그 객체를 참조하면 데이터 불일치나 크래시가 발생합니다. 이를 방지하기 위해 모든 스레드를 멈추는 것입니다.

동작 과정

정상 실행              STW               정상 실행
──────────      ──────────────       ──────────

스레드 A: 작업 중 → 정지 ─────────── → 재개
스레드 B: 작업 중 → 정지              → 재개
스레드 C: 작업 중 → 정지              → 재개
                     │
                  GC 스레드만 동작
                     │
                  ┌──┴──────────┐
                  │ 살아있는 객체 │
                  │ 마킹         │
                  │ 죽은 객체 제거│
                  │ 메모리 정리   │
                  └─────────────┘

체감 예시

[ 웹 서버에서 STW 발생 시 ]

사용자 요청 ──→ 서버 처리 중 ──→ STW 발생 (200ms)
                                  │
                                  ▼
                               모든 요청 처리가 멈춤
                               사용자: "왜 갑자기 느려졌지?"
                                  │
                                  ▼
                               STW 종료 → 밀린 요청 한꺼번에 처리
응답 시간
 ▲
 │        ┌── STW 발생
 │    200ms│
 │  ──────┤
 │  10ms  │  10ms
 │  ──────┘──────── 정상
 └───────────────────────► 시간

 평소 10ms 응답이 STW 때문에 갑자기 200ms로 튐

STW가 발생하는 GC 단계

┌─── Young Gen ──────┐         ┌─── Old Gen ──────┐
│                     │         │                   │
│  Minor GC           │         │  Major GC         │
│  Eden이 가득 찰 때   │         │  Old 영역 부족 시   │
│  STW: 수 ms         │         │  STW: 수십~수백 ms  │
│  빈번하지만 짧음      │         │  드물지만 길음       │
└─────────────────────┘         └───────────────────┘

                    Full GC
                    Heap 전체 정리
                    STW: 수백 ms ~ 수 초
                    가장 치명적
GC 종류대상STW 시간빈도
Minor GCYoung Gen수 ms자주
Major GCOld Gen수십~수백 ms가끔
Full GCHeap 전체수백 ms ~ 수 초드묾 (발생 시 치명적)

GC 알고리즘별 STW 비교

GCSTW 방식정지 시간특징
Serial전체 정지수백 ms단일 스레드, 소규모 앱용
Parallel전체 정지수백 ms멀티 스레드로 빠르게 처리
G1부분 정지수십 ms목표 정지 시간 설정 가능
ZGC거의 동시 처리수 ms 이하TB급 힙에서도 짧은 정지
Shenandoah거의 동시 처리수 ms 이하ZGC와 유사
STW 시간
 ▲
 │
 │  ███████████ Serial (수백 ms)
 │  ██████████  Parallel (수백 ms)
 │  ███         G1 (수십 ms)
 │  █           ZGC (수 ms 이하)
 │  █           Shenandoah (수 ms 이하)
 └──────────────────────────────────────

Concurrent GC는 어떻게 STW를 줄이는가

ZGC, Shenandoah 같은 최신 GC는 애플리케이션과 동시에 정리합니다.

[ 전통적 GC (Serial, Parallel) ]
앱 스레드: 실행 ─── 전체 정지 ─────────── 재개
GC 스레드:          마킹 → 정리 → 압축

[ Concurrent GC (ZGC, Shenandoah) ]
앱 스레드: 실행 ─ 짧은 정지 ─ 실행 ─── 짧은 정지 ─ 실행
GC 스레드:       초기 마킹    동시 마킹    최종 마킹   동시 정리
                 (~1ms)     (앱과 동시)   (~1ms)    (앱과 동시)

완전히 STW를 없앤 것이 아니라, 아주 짧은 STW만 남기고 대부분을 동시에 처리하는 방식입니다.

STW가 치명적인 분야

분야영향대안
실시간 트레이딩수 ms 지연 = 수억 원 손실C++, Rust 사용 또는 GC 튜닝
온라인 게임프레임 드랍, 끊김C++ 엔진 + 스크립트만 VM
자율주행정지 중 판단 불가C, C++ 사용
의료 장비실시간 모니터링 중단C, Ada 사용

실무에서 STW를 줄이는 방법

전략설명
GC 알고리즘 변경-XX:+UseZGC로 ZGC 사용
힙 크기 적절 설정너무 크면 Full GC 시 오래 정지
객체 생성 최소화불필요한 new 줄이기, 객체 풀링
GC 로그 모니터링-Xlog:gc*로 STW 시간 추적
Young Gen 비율 조정Minor GC 빈도와 Major GC 빈도 균형
# ZGC 사용 + GC 로그 활성화
java -XX:+UseZGC -Xlog:gc* -jar app.jar

핵심 정리

Stop-The-World는 GC가 안전하게 메모리를 정리하기 위해 모든 애플리케이션 스레드를 일시 정지시키는 현상입니다. 전통적 GC에서는 수백 ms까지 멈출 수 있지만, ZGC·Shenandoah 같은 최신 GC는 STW를 수 ms 이하로 줄였습니다. 다만 완전 제거는 불가능하므로, 극한의 실시간 성능이 필요한 분야에서는 여전히 GC 없는 네이티브 언어(C, C++, Rust)를 선택합니다.

CSLOG에서 보기