"매 alive 인데 매 unused, 매 unused 인데 매 free X". 매 manual mem (C/C++) 의 free 누락, 매 GC mem (Java/JS) 의 unintended retention. 매 long-running process 의 매 가장 흔한 incident, 매 2026 도구는 매 ASan/heaptrack/V8 heap snapshot/JFR + AI-assisted root cause.
매 핵심
매 두 의미
매 Manual leak: 매 free X — 매 OS 가 매 process 종료 시 매 회수.
매 GC leak: 매 root 에서 매 reachable 이지만 매 logically dead — 매 unintended retention.
매 흔한 원인
매 Cache 의 unbounded growth.
매 Listener / observer 의 unsubscribe 누락.
매 Closure 의 unintended capture (JS).
매 Static collection (HashMap) 의 누적.
매 ThreadLocal 의 cleanup 누락 (JVM/web).
매 Native handle (file/socket) 의 close 누락.
매 Circular ref + RC (Python before GC, Swift, ObjC ARC).
매 detection 의 axes
매 Symptom: 매 RSS 증가, 매 OOM, 매 GC 빈도 ↑, 매 latency drift.
매 Tool: 매 sampling profiler, 매 heap snapshot, 매 allocation tracking.
패턴
C++ Valgrind
g++ -g -O0 main.cpp -o app
valgrind --leak-check=full --show-leak-kinds=all --track-origins=yes ./app
# 매 "definitely lost" 의 우선 fix
classFileHandle{FILE*f;public:explicitFileHandle(constchar*p):f(fopen(p,"r")){}~FileHandle(){if(f)fclose(f);}FileHandle(constFileHandle&)=delete;FileHandle&operator=(constFileHandle&)=delete;};// 매 std::unique_ptr / std::shared_ptr 가 매 default
JS — listener 누락
// 매 BAD — node 가 떠도 listener 가 retain
functionattach(el){consthandler=()=>doStuff(el);el.addEventListener("click",handler);}// 매 GOOD
functionattach(el){consthandler=()=>doStuff(el);el.addEventListener("click",handler);return()=>el.removeEventListener("click",handler);}
JS — closure 의 unintended capture
// 매 BAD — 매 huge 가 매 outer scope 에 retained
functionsetup(){consthuge=newArray(1e7).fill(0);constsmall=huge[0];return()=>small;}// 매 GOOD
functionsetup(){constsmall=(()=>{consthuge=newArray(1e7).fill(0);returnhuge[0];})();return()=>small;}
Java — static map leak
// 매 BADpublicclassCache{staticfinalMap<Key,Value>M=newHashMap<>();}// 매 GOOD — Caffeine size cap + evictionimportcom.github.benmanes.caffeine.cache.*;Cache<Key,Value>c=Caffeine.newBuilder().maximumSize(10_000).expireAfterWrite(Duration.ofMinutes(10)).build();
Java heap dump + MAT
jcmd <pid> GC.heap_dump /tmp/heap.hprof
# 매 Eclipse MAT 에서 dominator tree / leak suspect
Chrome DevTools — heap snapshot diff
1. baseline snapshot
2. suspect action 반복 (e.g. open/close modal x10)
3. second snapshot
4. "Comparison" mode, 매 retained 증가 식별
5. retainer chain 의 root 추적
Python tracemalloc
importtracemalloctracemalloc.start(25)snap1=tracemalloc.take_snapshot()# ... 매 action 반복 ...snap2=tracemalloc.take_snapshot()forstatinsnap2.compare_to(snap1,'lineno')[:10]:print(stat)
언제: 매 leak 패턴 식별, 매 fix 제안 (RAII, weak ref, eviction policy), 매 heap dump 분석 hint.
언제 X: 매 production heap 의 직접 access, 매 sensitive customer data dump.
안티패턴
매 OOM 시 -Xmx ↑: 매 leak 을 매 늦출 뿐.
매 try/finally 없는 close: 매 try-with-resources / RAII / context manager 사용.
매 Strong cache without eviction: Caffeine / LRU.
매 Listener pattern 의 no unsubscribe: weakRef / dispose.