WeakMap은 키가 반드시 객체여야 하고, 그 키를 약하게(weekly) 참조하는 Map이다.
약한 참조 = WeakMap에 키로 들어가 있어도 그 객체가 가비지 컬렉션(GC) 대상에서 제외되지 않는다는 것. 다른 곳에서 그 객체를 더 이상 참조하지 않으면 객체는 GC가 되고, WeakMap에 있던 해당 항목(키와 값)도 함께 사라진다.
const wm = new WeakMap();
let user = { name: "Kim" };
wm.set(user, { visits: 3 });
console.log(wm.get(user); // { visits: 3 } 이게 나온다
user= null;
// 이제 { name: "Kim" } 객체를 가리키는 곳이 없음.
// -> GC가 객체를 회수하면서 WeakMap 항목도 같이 사라짐
일반 Map이었다면 Map이 키를 강하게 붙잡고 있어서, user = null을 해도 객체가 메모리에 계속 남는다. 즉, 메모리 누수가된다.
WeakMap 활용법
- 객체에 부가 데이터 붙이기 (원본을 건드리지 않고)
객체에 직접 프로퍼티를 추가하지 않고 메타데이터에 연결할 때 사용한다.
외부 라이브러리 객체나 DOM 노드에 특히 유용
const clickCount = new WeakMap();
function track(el) {
clickCount.set(el, (clickCount.get(el) ?? 0) + 1);
}
button.addEventListener('click', () => track(button);
// button이 DOM에서 제거되고 참조가 끊기면 카운트 데이터도 자동 정리됨
2. 객체 단위의 캐싱 / 메모이제이션
입력 객체별로 무거운 계산 결과를 캐싱할 때 사용 가능. 입력 객체가 사라지면 캐시도 같이 사라지므로 따로 캐시를 비울 필요가 없음
const cache = new WeakMap();
function computeBoundingInfo(mesh) {
if (cache.has(mesh)) return cache.get(mesh);
const result = heavyCalculation(mesh);
cache.set(mesh, result);
return result;
}