Java 장애는 JVM 옵션 하나를 더 잘 아는 것보다, 지금 눈앞의 문제가 메모리 압박인지, queue backlog인지, thread contention인지, 혹은 crash 전부터 누적된 saturation인지 먼저 가르는 쪽이 더 중요합니다.
이 글은 Java 운영 장애를 증상 기준으로 빠르게 분기하기 위한 허브입니다. 아래 내용을 다룹니다.
- 지금 보이는 문제가 OOM 축인지, executor backlog 축인지, GC/CPU 축인지
- 첫 몇 분 안에 무엇을 보면 다음 글을 빨리 고를 수 있는지
- Java 장애에서 자주 하는 잘못된 출발은 무엇인지
결론부터 말하면 Java 장애는 “가장 먼저 크게 보이는 병목”을 기준으로 분기를 잡는 편이 가장 빠릅니다.
이 허브가 필요한 순간
OutOfMemoryError가 보인다- thread pool queue가 계속 증가한다
- GC pause가 갑자기 길어졌다
- CPU는 뜨거운데 throughput은 떨어진다
- thread dump에서 waiting cycle이나 blocked progress가 보인다
- 서비스가 완전히 죽기 전부터 이미 saturation 상태다
이 단계에서는 해결책보다 라우팅이 먼저입니다. 잘못된 레이어를 먼저 손대면 장애만 더 길어질 수 있습니다.
첫 5분 체크
jcmd <pid> GC.heap_info
jcmd <pid> Thread.print
jcmd <pid> VM.native_memory summary
VM.native_memory summary는 NMT가 켜져 있을 때 특히 유용합니다. 세 명령의 목적은 장애 전체 해결이 아니라 첫 분기 선택입니다.
- heap과 영역 압박이 먼저 보인다: 메모리 축
- queue보다 blocked thread와 waiting cycle이 더 선명하다: deadlock 또는 contention 축
- CPU hot thread와 executor 포화가 먼저 보인다: backlog 또는 CPU 축
먼저 묻는 질문
1. 충돌하고 있는가, 멈추고 있는가, 버티고 있는가
crash, stall, saturation은 비슷해 보여도 첫 진단이 다릅니다. OOM이면 메모리 축이 먼저고, forward progress가 멈추면 deadlock 쪽이 먼저입니다.
2. 문제의 중심이 heap인가, queue인가
메모리가 크다고 해서 항상 메모리 문제인 것은 아닙니다. executor backlog가 먼저 커지면 메모리도 같이 오르기 쉽습니다.
3. pause가 핵심인가, contention이 핵심인가
긴 GC pause와 hot CPU는 모두 처리량 저하를 만들지만, 조사 방향은 다릅니다. pause가 먼저면 메모리 흐름을, contention이 먼저면 hot thread와 lock 대기를 봐야 합니다.
메모리 압박 축으로 들어가야 할 때
아래에 가깝다면 힙 덤프를 추출하여 OOM 발생 위치부터 파악하는 편이 좋습니다.
- heap, metaspace, native 영역 압박이 보인다
- OOM variant 자체가 중요하다
- 큰 collection, cache, retained payload가 의심된다
- class metadata 증가가 이상하다
retained object의 정체가 아직 모호하다면 힙 덤프 분석 도구를 이용해 참조 트리를 확인하는 것이 좋습니다.
queue backlog 또는 executor saturation 축으로 들어가야 할 때
아래에 가깝다면 스레드 풀 크기와 태스크 큐 설정을 다시 점검해 보세요.
- executor queue가 계속 증가한다
- worker가 계속 바쁘거나 blocked 상태다
- 메모리보다 backlog가 더 먼저 눈에 띈다
함께 보면 좋은 글:
이 축은 “들어온 일을 왜 제때 소화하지 못하는가”를 좁혀 가는 문제에 가깝습니다.
긴 GC pause 또는 retained heap 축으로 들어가야 할 때
아래에 가깝다면 Java GC Pauses Too Long부터 보는 편이 좋습니다.
- 명확한 crash보다 pause spike가 먼저 보인다
- 트래픽이나 payload 변화 뒤 allocation churn이 커졌다
- old generation 증가가 의심된다
pause보다 retained object 증거가 더 필요하다면 힙 덤프를 통해 수명이 긴 객체들을 확인해 보세요.
hot CPU 또는 contention 축으로 들어가야 할 때
아래에 가깝다면 스레드 덤프를 추출해 핫 스레드(Hot Thread)가 어디서 시간을 쓰는지 확인해 보세요.
- CPU는 계속 높은데 throughput이 떨어진다
- host metric보다 hot thread가 더 중요해 보인다
- retry, spinning, contention, wasted work가 의심된다
lock contention이 특히 선명하면 병목이 되는 락(Lock) 획득 지점을 찾아 동시성 구조를 개선해야 합니다.
deadlock 또는 진행 정지 축으로 들어가야 할 때
서비스가 단순히 느린 것이 아니라 멈춘 것 같다면 락 순서 역전(Lock Ordering)이나 교착 상태(Deadlock)를 의심해 보는 편이 좋습니다.
- thread dump에 waiting cycle이 보인다
- throughput보다 lock ownership이 더 중요하다
- 서비스가 forward progress를 거의 못 만든다
이 경우는 CPU 튜닝보다 진행 정지를 푸는 것이 먼저입니다.
자주 하는 오진
backlog가 원인인데 heap만 먼저 늘리는 경우
queue가 계속 쌓이는 상황에서 heap만 늘리면 장애가 덜 보일 뿐, 병목은 그대로 남습니다.
pause 문제를 무조건 CPU 문제로 보는 경우
처리량 저하가 보인다고 해서 항상 hot thread가 먼저는 아닙니다. GC pause가 긴 경우도 체감상 비슷하게 보입니다.
deadlock 신호를 놓치고 executor 설정만 만지는 경우
waiting cycle이 보이는데 pool 크기만 바꾸면 증상은 더 복잡해질 수 있습니다.
아주 빠른 분기표
- OOM이나 메모리 영역 압박이 제일 선명하다: 메모리 글부터
- queue 증가가 제일 선명하다: thread-pool backlog 글부터
- pause spike가 먼저 보인다: GC 글부터
- hot thread 또는 contention이 먼저 보인다: CPU 글부터
- 진행 정지가 먼저 보인다: deadlock 글부터
그리고 첫 글 하나만 읽지 말고, 바로 인접 분기 하나를 더 비교하세요. Java 장애는 backlog와 메모리, contention과 deadlock이 서로 얽혀 보이는 경우가 많습니다.
장애 조사 순서
- 가장 먼저 크게 보이는 병목을 적습니다.
- 시스템이 crashing인지, stalling인지, saturating인지 구분합니다.
- memory-area pressure와 backlog pressure를 나눕니다.
- hot CPU contention과 blocked-progress deadlock을 나눕니다.
- 가장 강한 증상에 맞는 좁은 글로 들어간 뒤, 인접 분기 글 하나를 바로 비교합니다.
FAQ
Q. 이 글은 JVM 튜닝 가이드인가요?
아니요. 증상 기준으로 다음 분기를 고르는 허브 글입니다.
Q. queue 증가와 메모리 압박이 같이 보이면 어디부터 볼까요?
먼저 나타난 증상부터 보세요. 그리고 바로 이어지는 인접 가이드를 비교하면 됩니다.
Q. OOM은 없는데 GC pause만 심해졌다면 메모리 문제는 아닌가요?
그래도 메모리 압박 분기로 보는 것이 맞습니다. GC pause부터 보고, 필요하면 heap dump 분석으로 넘어가면 됩니다.
Q. CPU보다 deadlock을 먼저 봐야 하는 시점은 언제인가요?
forward progress가 멈추고, thread dump가 단순 hot loop보다 waiting cycle을 가리킬 때입니다.
Read Next
- 메모리 압박이 가장 선명하다면 힙 덤프를 통해 OOM 원인을 먼저 파악하세요.
- queue backlog가 먼저 눈에 띄거나 스레드 풀 고갈이 의심되면 Java ForkJoinPool Starvation 사례를 참고해 보세요.
- pause spike가 crash보다 더 눈에 띄면 Java GC Pauses Too Long를 보세요.
- hot thread나 contention이 핵심이면 스레드 덤프로 병목 지점을 찾으세요.
Related Posts
먼저 읽어볼 가이드
검색 유입이 많은 핵심 글부터 이어서 보세요.
- 미들웨어 트러블슈팅 가이드: Redis, RabbitMQ, Kafka 중 어디부터 볼까 Redis, RabbitMQ, Kafka가 함께 있는 시스템에서 지금 보이는 장애가 어느 계층에 더 가까운지, 첫 10분 안에 무엇을 확인하고 어떤 글로 들어가야 하는지 정리한 실전 허브 가이드입니다.
- Kubernetes CrashLoopBackOff: 먼저 볼 것들 startup failure, probe, config, resource limit 관점에서 CrashLoopBackOff를 어떻게 나눠서 봐야 하는지 정리한 가이드입니다.
- Astro 기술 블로그 SEO 체크리스트: 트래픽 기다리기 전에 먼저 고칠 것 Astro 기술 블로그를 위한 실전 SEO 체크리스트입니다. 배포 호스트 확인, robots.txt, sitemap, canonical, hreflang, 구조화 데이터, 페이지별 메타데이터, noindex 판단, 검증 명령까지 우선순위대로 정리합니다.
- 다국어 블로그 canonical과 hreflang 설정 가이드: 무엇을 확인하고 어디서 깨질까 다국어 블로그에서 canonical과 hreflang을 어떻게 설정해야 하는지 실전 기준으로 정리합니다. self-canonical, 상호 연결되는 hreflang 묶음, x-default, 카테고리 페이지, 최종 렌더 HTML 점검, 한 언어 버전이 다른 언어 버전을 눌러버리는 실수까지 다룹니다.
- OpenAI Codex CLI 설치 가이드: 설치, 인증, 첫 작업까지 OpenAI Codex CLI를 실전 기준으로 설치하는 방법을 정리했다. 설치, 로그인, 첫 실행, Windows 주의점, 첫 작업을 어떻게 시작하면 좋은지까지 다룬다.