7장 메모리 관리

메모리 수명 주기와 누수 점검

JavaScript 메모리는 root에서 도달 가능한 객체를 mark하고, 끊긴 객체를 sweep합니다. 누수는 “더는 필요 없지만 여전히 참조되는 값”입니다.

01

Allocate

객체, 배열, 클로저, DOM 노드를 만들면 힙에 공간이 잡힙니다.

02

Reference

전역 객체, call stack, DOM, closure에서 닿는 값은 reachable입니다.

03

Mark

GC가 window와 실행 컨텍스트를 root로 삼아 참조 그래프를 표시합니다.

04

Sweep

표시되지 않은 힙 객체는 회수되고, 계속 표시되는 불필요 객체는 누수 후보입니다.

Retained Size

Heap snapshot에서 retained size가 큰 객체는 어떤 참조가 붙잡는지 경로를 따라갑니다.

누수 원인

전역 배열, 해제하지 않은 setInterval, 이벤트 리스너, 무제한 Map 캐시가 값을 붙잡습니다.

DOM 참조

removeChild 후에도 변수, closure, listener가 잡으면 detached DOM tree가 남습니다.

WeakMap

DOM 노드별 메타데이터처럼 객체 수명 주기에 따라 사라져야 하면 WeakMap을 씁니다.

도달 경로

Chrome DevTools의 retaining path에서 window, listener, closure 중 무엇이 객체를 잡는지 확인합니다.

증가 패턴

같은 화면을 열고 닫은 뒤 강제 GC를 해도 heap과 listener 수가 계속 오르면 누수 신호입니다.

해제 위치

addEventListener, setInterval, MutationObserver를 만든 코드 근처에 remove/clear/disconnect가 있어야 합니다.