이 문서를 통해 아래 질문들에 답할 수 있게 됩니다.
Memory Pressure와 Swap에서 붙잡아야 할 핵심 판단 기준은 무엇인가?memory 압박은 latency로 먼저 보일 수 있다라는 기준은 어떤 JVM/OS 신호로 확인되는가?- Java/Spring 코드에서
Memory Pressure와 Swap판단 기준은 어떤 장애 신호로 드러나는가?
개요
이 문서의 주제는 Memory Pressure와 Swap이다. Memory pressure, page fault, swap, OOM kill이 Java 서버에 미치는 영향을 설명한다.
먼저 붙잡을 기준은 다음 문장이다. memory 압박은 latency로 먼저 보일 수 있다. Heap OOM이 나기 전에도 page fault, swap, GC 증가, cgroup pressure가 응답 지연과 CPU 상승으로 먼저 나타날 수 있다.
핵심 모델
- 판단 기준: memory 압박은 latency로 먼저 보일 수 있다.
- Memory pressure는 heap만의 문제가 아니라 RSS, native/direct memory, page cache, cgroup limit이 함께 압박받는 상태다.
- Swap
si/so가 움직이면 Java heap이 아직 살아 있어도 latency가 크게 흔들릴 수 있다. - Heap OOM, native OOM, OS/cgroup OOM kill은 증거와 조치가 다르다.
- Cache, batch, export, upload처럼 메모리를 크게 잡는 기능은 backpressure와 상한이 필요하다.
- Memory 증설은 완화책일 수 있지만 leak, unbounded cache, batch 적재 문제를 대신 해결하지 못한다.
문서별 핵심 구분
- memory pressure는 GC 증가, page fault, swap, OOM kill로 나타난다.
- swap은 서버 latency를 크게 흔드는 위험 신호다.
- heap과 RSS, cgroup limit을 분리해서 본다.
원리
Memory pressure는 단순히 free memory가 낮다는 뜻이 아니다. JVM heap, native/direct memory, page cache, cgroup limit, swap 활동이 함께 압박을 받는 상태다.
Swap in/out이 발생하면 CPU가 계산 대신 memory page를 disk와 주고받는 데 시간을 쓰게 되어 latency가 크게 흔들릴 수 있다. Java 서버에서는 GC pause와 swap 지연이 겹치면 장애가 더 커진다.
Heap used가 높으면 GC와 heap dump를 보고, RSS가 높으면 native/direct/metaspace/thread stack을 본다. Container에서는 host memory보다 cgroup limit에 먼저 닿을 수 있다.
따라서 memory 장애는 heap, RSS, cgroup, swap, OOM kill log를 같은 시간대에 놓고 “어느 한계에 먼저 닿았는가”를 확인해야 한다.
Java/Spring 연결
- Actuator heap metric은 JVM heap을 보여 주지만 RSS와 cgroup pressure를 대신하지 못한다.
- Large response, batch export, cache, direct buffer, thread 증가가 memory pressure를 만들 수 있다.
- GC pause가 늘면 request thread는 살아 있어도 latency가 튈 수 있다.
- Container OOM kill은 Java
OutOfMemoryError없이 process 종료로 보일 수 있다. - Memory 완화는 유입 제한, batch 중지, cache 축소, heap dump 여부 판단으로 나눈다.
코드와 설정 예시
date -Is
free -h
vmstat 1 5
jcmd <pid> GC.heap_info
cat /proc/<pid>/status | grep -E 'VmRSS|VmSize|Threads'예시는 OS memory, JVM heap, process 상태를 같은 시간에 모으는 흐름이다. Swap이 움직이는지, OS OOM kill이 있었는지, heap과 RSS 중 어느 쪽이 먼저 압박을 받는지 나눠야 한다.
관찰 명령
free -h
vmstat 1 5
dmesg | grep -i 'out of memory' | tail
jcmd <pid> GC.heap_infoMemory Pressure와 Swap 관찰 명령은 결론이 아니라 가설 확인 도구다. 운영 중에는 반복 간격, 대상 PID, 수집 시각을 함께 남기고 출력이 큰 명령은 범위를 제한한다.
지표 해석
| 신호 | 먼저 의심할 것 | 다음 확인 |
|---|---|---|
si/so 증가 | swap 활동 | vmstat, disk latency |
| Heap used 증가 | heap leak, allocation burst | GC log, heap dump |
| RSS 증가, heap 안정 | native/direct/thread stack | NMT, /proc |
| OOM kill log | cgroup/OS limit 초과 | dmesg, container event |
Memory 분석은 heap, RSS, swap si/so, cgroup event, GC pause의 순서를 맞추는 일이다. 어느 한계에 먼저 닿았는지에 따라 dump, 완화, limit 조정이 달라진다.
장애 상황에서 보는 순서
- Heap, RSS, cgroup memory, swap 활동을 같은 시각에 확인한다.
- Java OOM인지 OS/cgroup OOM kill인지 로그로 나눈다.
- Swap
si/so, major fault, disk latency가 latency spike와 겹치는지 본다. - Heap 문제면 histogram/dump, RSS 문제면 NMT/direct/thread/metaspace를 본다.
- 임시 완화와 근본 수정(cache 제한, leak 수정, limit 조정)을 분리한다.
이 순서는 heap과 process memory를 분리하기 위한 루틴이다. Java OOM이 보이지 않아도 OS/cgroup이 process를 죽였을 수 있으므로 JVM 로그와 kernel/container event를 함께 본다.
실전 팁
- Swap이 움직이는 서버는 latency 관점에서 이미 위험 신호로 본다.
- Heap과 RSS가 다르게 움직이면 heap 밖 memory를 별도로 추적한다.
- Container에서는 host
free보다 cgroup limit과 OOM event를 우선한다. - Memory 증설은 leak과 unbounded cache를 숨길 수 있어 근본 수정과 분리한다.
- 장애 회고에는 heap/RSS/cgroup/swap/OOM log를 한 표로 남긴다.
주니어 팁
- Free memory 숫자 하나로 판단하지 말고 heap, RSS, swap을 나눠 본다.
- Java OOM과 OS OOM kill은 로그와 증상이 다르다.
- Swap
si/so가 움직이면 latency와 함께 확인한다.
시니어 팁
- Cache, batch, export, upload 기능은 memory 예산과 backpressure를 설계에 포함한다.
- Container memory limit은 heap과 native, page cache 여유를 함께 반영한다.
- OOM 대응 runbook에는 dump 수집 여부, disk 여유, 민감 정보 처리를 포함한다.
Guru급 팁
- 서비스별 memory budget은 heap, direct, metaspace, thread stack, page cache를 나눠 잡아야 container limit에 안전하게 들어간다.
- OOM runbook은 dump를 뜰지 말지부터 결정해야 한다. dump가 필요한 증거인지, disk와 개인정보 위험을 감당할지 판단한다.
- Memory 완화 후에는 cache hit ratio, GC pause, RSS, swap이 어떻게 바뀌었는지 같이 봐야 성능 손실을 평가할 수 있다.
위험 신호!
free의 available만 보고 Java memory 문제를 배제한다.- Heap만 키우고 RSS/cgroup limit을 확인하지 않는다.
- Swap이 움직이는데 GC tuning만 반복한다.
- OS OOM kill을 Java exception이 없다는 이유로 놓친다.
- Heap dump를 남기기 전에 disk 여유와 민감 정보를 확인하지 않는다.
확인 질문
확인 질문
- Heap OOM과 OS OOM kill을 구분해야 하는 이유는 무엇인가?
- Heap OOM은 JVM 내부 한계이고 OS/cgroup OOM kill은 process 전체 memory limit 초과라 증거와 조치가 다르기 때문이다.
- Swap이 Java 서버 latency를 흔드는 이유는 무엇인가?
- Memory page를 disk와 주고받으며 application과 GC가 기다리는 시간이 커질 수 있기 때문이다.
- Memory limit을 늘리기 전에 확인할 것은 무엇인가?
- Heap/RSS/cgroup/swap/OOM log와 leak, cache, batch 적재 같은 증가 원인을 확인해야 한다.