일반적인 map
- 도달 가능한 값으로 취급되어 메모리에서 삭제되지 않습니다.
let john = { name: "John" }; let array = [ john ]; john = null; // 참조를 null로 덮어씀 // john을 나타내는 객체는 배열의 요소이기 때문에 가비지 컬렉터의 대상이 되지 않습니다. // array[0]을 이용하면 해당 객체를 얻는 것도 가능합니다. alert(JSON.stringify(array[0]));
이런 관점에서
위크맵(WeakMap)
은 일반 맵
과 전혀 다른 양상을 보입니다. 위크맵을 사용하면 키로 쓰인 객체가 가비지 컬렉션의 대상이 됩니다.
let john = { name: "John" }; let weakMap = new WeakMap(); weakMap.set(john, "..."); john = null; // 참조를 덮어씀 // john을 나타내는 객체는 이제 메모리에서 지워집니다!
WeapMap이란?
WeakMap
객체는 키가 약하게 참조되는 키/값 쌍의 컬렉션으로, 키는 반드시 객체여야만 한다.
- 원시 값은 키가 될 수 없다. 만약 키를 원시 값으로 추가하면
Uncaught TypeError: Invalid value used as weak map key
라는 에러가 발생한다.
WeakMap
은 특정 키에 대한 값이 있는지 메서드를 통해 확인 가능하지만, 키로 보유한 객체들을 열거하는 방법은 제공되지 않는다.- 즉, 반복 작업과
keys()
,values()
,entries()
메서드를 지원하지 않는다. - 지원하는 메서드
weakMap.get(key)
weakMap.set(key, value)
weakMap.delete(key)
weakMap.has(key)
clear()
메서드는 보안 이슈로 인해 IE를 제외한 모든 브라우저에서 deprecated 상태.- 그리고
WeakMap
의 키로 쓰인 객체는 가비지 컬렉션 대상이 된다.
- 프로그램 내 객체에 대한 참조가
WeakMap
을 제외하고 존재하지 않는다면, 해당 객체는 가비지로 수거된다.
왜 제한적일까?
→ 가비지 컬렉션의 동작 방식 때문!
- 위 예시의
john
을 나타내는 객체처럼, 객체는 모든 참조를 잃게 되면 자동으로 가비지 컬렉션의 대상이 됩니다.
- 그런데 가비지 컬렉션의 동작 시점은 정확히 알 수 없습니다.
- 가비지 컬렉션이 일어나는 시점은 자바스크립트 엔진이 결정합니다.
- 객체는 모든 참조를 잃었을 때, 그 즉시 메모리에서 삭제될 수도 있고, 다른 삭제 작업이 있을 때까지 대기하다가 함께 삭제될 수도 있습니다.
- 현재
위크맵
에 요소가 몇 개 있는지 정확히 파악하는 것 자체가 불가능한 것이죠.
- 가비지 컬렉터가 한 번에 메모리를 청소할 수도 있고, 부분 부분 메모리를 청소할 수도 있으므로 위크맵의 요소(키/값) 전체를 대상으로 무언가를 하는 메서드는 동작 자체가 불가능합니다.
어떤 경우에 사용할 수 있을까?
- 객체엔 ‘주요’ 자료를,
위크맵
과위크셋
엔 ‘부수적인’ 자료를 저장하는 형태로 위크맵과 위크셋을 활용할 수 있습니다.
- 방문 횟수를 저장할 때
- 캐싱할 때


WeakSet이란?
위크셋
은셋
과 유사한데, 객체만 저장할 수 있다는 점이 다릅니다. 원시값은 저장할 수 없습니다.
- 셋 안의 객체는 도달 가능할 때만 메모리에서 유지됩니다.
셋
과 마찬가지로위크셋
이 지원하는 메서드는 단출합니다.add
,has
,delete
를 사용할 수 있고,size
,keys()
나 반복 작업 관련 메서드는 사용할 수 없습니다.
let visitedSet = new WeakSet(); let john = { name: "John" }; let pete = { name: "Pete" }; let mary = { name: "Mary" }; visitedSet.add(john); // John이 사이트를 방문합니다. visitedSet.add(pete); // 이어서 Pete가 사이트를 방문합니다. visitedSet.add(john); // 이어서 John이 다시 사이트를 방문합니다. // visitedSet엔 두 명의 사용자가 저장될 겁니다. // John의 방문 여부를 확인해보겠습니다. alert(visitedSet.has(john)); // true // Mary의 방문 여부를 확인해보겠습니다. alert(visitedSet.has(mary)); // false john = null; // visitedSet에서 john을 나타내는 객체가 자동으로 삭제됩니다.
정리
WeakMap
은Map
처럼 열거 메서드를 지원해주진 못하지만 참조를 약하게 유지하여 메모리 누수 관리에 메리트가 있는 자료구조이다.
- 큰 단점은 반복 작업이 불가능하다는 점입니다. 하지만 weakmap, weakset을 이용해 할 수 있는 주요 작업을 방해하진 않습니다.
- 사실 요즘 대부분의 프로젝트들이 프레임워크 기반으로 구현되어 일반적인 상황에서 사용할 일이 많지 않겠지만,
- 프로젝트 내 객체를 식별자로 갖는 자료구조가 필요하다면 일반 객체나
Map
을 바로 사용하기 전에WeakMap
의 사용을 한 번 고려하면 어떨까 한다.
참고자료 :