Python 메모리 사용량이 계속 올라갈 때, 먼저 나눠서 봐야 할 문제는 세 가지입니다. 정상적인 workload 증가인지, 이미 해제됐어야 할 객체가 남아 있는지, 아니면 process model 때문에 worker 단위로 메모리가 복제되고 있는지입니다.
짧게 말하면, 어떤 process가 실제로 커지는지 확인하고, 증가가 traffic이나 시간과 어떻게 맞물리는지 본 다음, cache growth, retained object, worker multiplication을 분리해서 봐야 합니다.
먼저 어떤 메모리 패턴인지부터 구분하세요
메모리 사용량이 높다는 건 하나의 증상이 아닙니다. 보통 아래 중 하나에 가깝습니다.
- 특정 process 하나만 계속 커지는 경우
- 모든 worker가 큰 footprint를 안정적으로 유지하는 경우
- worker 수를 늘리자마자 전체 메모리가 점프하는 경우
- 특정 job이나 payload에서만 급증하는 경우
- traffic이 줄어도 메모리가 내려가지 않는 경우
각 패턴은 다른 원인으로 이어집니다. 그래서 “Python이 메모리를 많이 쓴다”는 출발점일 뿐 진단 자체는 아닙니다.
Python 메모리 증가를 만드는 흔한 이유
1. 큰 cache가 원래 가정보다 계속 커짐
application cache, LRU structure, lookup object, model object가 eviction 없이 커지는 경우가 많습니다.
2. worker가 process마다 메모리를 복제함
Gunicorn, Celery, multi-process 구조에서는 프로세스 하나는 괜찮아 보여도 worker 수만큼 곱해져 node-level incident가 될 수 있습니다.
3. 객체 참조가 의도보다 오래 남음
list, dict, queue, global state, background structure가 큰 객체를 hot path 이후에도 계속 붙잡고 있을 수 있습니다.
4. 큰 payload나 data-heavy transformation이 지배적임
큰 JSON, 파일 처리, tabular data, batch 처리, serialization은 leak처럼 보이는 spike를 만들 수 있습니다.
5. 한 가지 원인만 있는 게 아니라 혼합형임
실제 서비스에서는 duplication, cache growth, 큰 payload handling이 동시에 기여하는 경우가 많습니다.
실전 점검 순서
1. 어떤 process나 worker가 커지는지 확인하세요
pod나 node 전체 메모리만 보지 말고, 증가가 아래 어디에 속하는지 봐야 합니다.
- 특정 worker 하나
- 모든 worker
- parent-child process tree
- background process 하나
이 구분만으로도 원인 범위를 크게 줄일 수 있습니다.
2. 증가가 traffic, job, 시간과 어떻게 맞물리는지 보세요
유용한 패턴은 아래와 같습니다.
- traffic spike 때만 증가
- idle 상태에서도 증가
- background job 시작 직후 점프
- concurrency 변경 후 급증
traffic과 맞물리면 payload size와 caching이 유력하고, idle 상태에서도 계속 오르면 retained object나 background loop가 더 의심됩니다.
3. cache와 queue가 bounded 한지 확인하세요
이건 가장 신호가 큰 점검 중 하나입니다. unbounded cache와 backlog 구조는 전형적인 leak 없이도 메모리 증가를 설명합니다.
4. worker 수와 concurrency 변경 이력을 보세요
worker를 늘린 직후 나빠졌다면 Python worker memory duplication과 같이 보는 편이 맞습니다.
5. 가장 큰 payload를 만드는 code path를 확인하세요
request handler, batch job, parsing path, file operation, model-heavy operation이 실제 memory cost의 중심인 경우가 많습니다.
retained growth를 감 잡기 위한 짧은 예시
items = []
while True:
items.append("x" * 1_000_000)
실제 앱은 이만큼 단순하지 않지만, 패턴은 비슷합니다. 데이터가 구조에 들어가고, 의미 있게 해제되지 않는 것입니다.
패턴을 찾은 뒤 어떻게 바꿀지
cache가 주원인인 경우
eviction rule을 넣거나 더 엄격하게 만들고, value size를 줄이고, 항상-live process memory 밖으로 옮길 수 있는 데이터는 분리하세요.
worker multiplication이 문제인 경우
더 큰 node로 버티기 전에 per-worker state를 줄이거나 worker 수를 조정하는 편이 좋습니다.
큰 payload가 문제인 경우
payload를 줄이고, 가능하면 stream 방식으로 바꾸고, 변환된 큰 데이터를 오래 들고 있지 않도록 해야 합니다.
retained reference가 문제인 경우
queue, global, long-lived background state가 객체를 계속 소유하고 있지 않은지 추적해야 합니다.
빠른 체크리스트
Python 메모리 사용량이 높을 때는 아래 순서가 가장 실용적입니다.
- 어떤 process나 worker가 커지는지 확인한다
- 증가가 traffic, job, 시간과 어떻게 맞물리는지 본다
- cache와 queue의 bound를 확인한다
- 최근 worker나 concurrency 변경을 비교한다
- 가장 큰 allocation path를 본다
FAQ
Q. Python 메모리 사용량이 높으면 항상 leak인가요?
아닙니다. workload growth, cache expansion, worker multiplication인 경우가 많습니다.
Q. 웹 앱에서는 무엇부터 보면 되나요?
특정 worker 문제인지, 모든 worker 공통 문제인지, 그리고 traffic과 맞물리는지를 먼저 보세요.
Q. traffic이 줄어도 메모리가 안 내려오면요?
retained reference, background loop, eviction 없는 cache를 봐야 합니다.
Q. worker를 늘리자마자 왜 메모리가 나빠졌나요?
process-based concurrency가 단일 worker에서 괜찮아 보이던 메모리를 곱해버렸기 때문일 가능성이 큽니다.
Read Next
- 로그 부족 때문에 진단이 더딘 상태라면 Python 로그가 안 나올 때를 보세요.
- worker multiplication이 핵심 같다면 Python worker memory duplication을 같이 보세요.
- 더 넓은 흐름은 Python troubleshooting guide에서 볼 수 있습니다.
Related Posts
- Python 로그가 안 나올 때
- Python worker memory duplication
- Python troubleshooting guide
- Java OutOfMemoryError
Sources:
심사 대기 중에는 광고 대신 관련 가이드를 먼저 보여줍니다.
먼저 읽어볼 가이드
검색 유입이 많은 핵심 글부터 이어서 보세요.
- 미들웨어 트러블슈팅 가이드: Redis vs RabbitMQ vs Kafka 개발자를 위한 미들웨어 트러블슈팅 허브 글입니다. Redis, RabbitMQ, Kafka 중 어떤 증상부터 먼저 봐야 하는지와 어떤 문제 패턴이 각 시스템에 가까운지 정리합니다.
- Kubernetes CrashLoopBackOff: 먼저 볼 것들 startup failure, probe, config, resource limit 관점에서 CrashLoopBackOff를 어떻게 나눠서 봐야 하는지 정리한 가이드입니다.
- Kafka consumer lag가 계속 늘 때: 트러블슈팅 가이드 Kafka consumer lag가 계속 늘어날 때 무엇부터 봐야 하는지 정리합니다. poll 주기, 처리 속도, rebalance, consumer 설정까지 실전 기준으로 다룹니다.
- Kafka Rebalancing Too Often 가이드 Kafka consumer group에서 rebalance가 너무 자주 일어날 때 membership flapping, poll timing, protocol, assignment churn을 어떤 순서로 봐야 하는지 설명하는 실전 가이드입니다.
- Docker container가 계속 재시작될 때: 먼저 확인할 것들 exit code, command failure, environment mistake, health check 관점에서 Docker restart loop를 푸는 실전 가이드입니다.
심사 대기 중에는 광고 대신 관련 가이드를 먼저 보여줍니다.