-
[ES6] WeakMap vs Map [번역]맨땅에코딩/javascript 2020. 8. 9. 23:32
[서문]
Garbage Collection : JavaScript 엔진은 value를 메리에 저장하는데 ( 잠재적으로 사용될 수 있을동안 )
let john = { name: "John" }; // the object can be accessed, john is the reference to it // overwrite the reference john = null;
보통, 객체의 프로퍼티 혹은 배열이나 다른 데이터 구조의 요소들은 메모리에 그 데이터구조가 있을 동안만 접근 가능하다.
예를 들어, 배열에 객체를 넣을때, 그리고 배열은 살아있을때, 그 객체에 다른 참조가 없을때도 배열안에 있는 객체는 살아있다.
let john = { name: "John" }; let array = [ john ]; john = null; // overwrite the reference // john is stored inside the array, so it won't be garbage-collected // we can get it as array[0]
Map또한 마찬가지인데, Map이 존재하는 동안 Map에 담긴 object도 존재한다.
메모리를 차지하고 gc 되지 않을 것이다.
let john = { name: "John" }; let map = new Map(); map.set(john, "..."); john = null; // overwrite the reference // john is stored inside the map, // we can get it by using map.keys()
WeakMap은 근본적으로 이러한 관점에서 다르다.
key object의 gc를 보호하지 않는다.
[차이점]
1. WeakMap 의 key는 반드시 object여야 한다. ( integer , string X )
2. WeakMap의 key인 object의 참조부분이 없다면 - 메모리로부터 자동적으로 지워질것이다.
let john = { name: "John" }; let weakMap = new WeakMap(); weakMap.set(john, "..."); john = null; // overwrite the reference // john is removed from memory!
3. WeakMap은 iteration 과 keys(), values(), entries() 메소드를 지원하지 않는다.
* 지원가능한 메소드
- weakMAp.get(key)
- weakMap.set(key, value)
- weakMap.delete(key)
- weakMap.has(key)
왜 이러한 제한이 있을까?
: 기술적인 이유때문이다. 만약 object 모든 참조를 잃었다면 (위에 John 처럼) , 자동적으로 gc 처리된다.
하지만 기술적으로 삭제되는 상황을 설명한건 아니다.
JavaScript 엔진은 메모리 비움을 즉시 수행할 수도 있고 다른 삭제상황이 있을때를 기다릴 수도 있다.
따라서, 기술적으로 WeakMap의 현재의 요소는 알 수 없는 상태이다.
지워졌을 수도 안지워졌을 수도 있어서.. 혹은 부분적으로
그러한 이우로 key/value에 접근하는 메소드는 지원되지않는다.
[언제 WeakMap을 사용해?]
1. 추가적 데이터
WeakMap의 어플리케이션의 주요 사용처는 "추가적인 데이터 저장소" 이다.
만약 우리가 다른 코드에 속한 object를 작업하고 있다면 (아마도 thrid-party 라이브러리에서)
그 것으로 데이터를 저장하길 원하며, 오직 그 object가 살아있을때만 존재해야 할때
WeakMap 은 딱맞는 예제이다.
예제를 살펴보자.
사용자별 방문자수를 보유하는 코드를 작성한다고 가정하자.
Map안에 저장된 정보는 이러하다 : 사용자 object는 key이고 방문자수는 value다.
사용자가 떠나면 ( garbage collected ) 우리는 그 사용자의 방문수를 더이상 저장하고싶지않다.
Map 이용
// 📁 visitsCount.js let visitsCountMap = new Map(); // map: user => visits count // increase the visits count function countUser(user) { let count = visitsCountMap.get(user) || 0; visitsCountMap.set(user, count + 1); } // 📁 main.js let john = { name: "John" }; countUser(john); // count his visits // later john leaves us john = null;
: John object는 gc 처리돼야 하는데 visitsCountMap의 key로 남아있다.
그렇다면, 우리는 사용자가 탈퇴할때, visitsCountMap을 비워야한다. 그렇지않으면, 메모리에 무기한으로 남아있을 것이다. 이러한 비움작업은 귀찮은 작업이 될 수 있다.
WeakMap 이용
// 📁 visitsCount.js let visitsCountMap = new WeakMap(); // weakmap: user => visits count // increase the visits count function countUser(user) { let count = visitsCountMap.get(user) || 0; visitsCountMap.set(user, count + 1); }
: 우리는 visitsCountMap을 비울 필요가 없다. John object가 WeakMap의 key를 제외하고 접근 불가능해졌을때,
메모리로부터 제거된다.
2. Caching
: 함수의 결과가 기억돼야할때, 같은 object를 재사용하여 호출한다.
Map 이용
// 📁 cache.js let cache = new Map(); // calculate and remember the result function process(obj) { if (!cache.has(obj)) { let result = /* calculations of the result for */ obj; cache.set(obj, result); } return cache.get(obj); } // Now we use process() in another file: // 📁 main.js let obj = {/* let's say we have an object */}; let result1 = process(obj); // calculated // ...later, from another place of the code... let result2 = process(obj); // remembered result taken from cache // ...later, when the object is not needed any more: obj = null; alert(cache.size); // 1 (Ouch! The object is still in cache, taking memory!)
: 같은 object로 여러번의 process(obj) 를 할때, 처음에만 결과를 계산한다. 그 후에는 cache에서 값을 가져온다.
문제는, 그 object가 더이상 필요하지않을때 우리는 cache를 비울 필요가 있다.
WeakMap 이용
// 📁 cache.js let cache = new WeakMap(); // calculate and remember the result function process(obj) { if (!cache.has(obj)) { let result = /* calculate the result for */ obj; cache.set(obj, result); } return cache.get(obj); } // 📁 main.js let obj = {/* some object */}; let result1 = process(obj); let result2 = process(obj); // ...later, when the object is not needed any more: obj = null; // Can't get cache.size, as it's a WeakMap, // but it's 0 or soon be 0 // When obj gets garbage collected, cached da
: WeakMap은 object가 gc로 수집된 후에 자동으로 메모리에서 지워준다.
let messages = [ {text: "Hello", from: "John"}, {text: "How goes?", from: "John"}, {text: "See you soon", from: "Alice"} ]; let readMap = new WeakMap(); readMap.set(messages[0], new Date(2017, 1, 1)); // Date object we'll study later
: Set은 object의 yes/no 여부만 알 수 있지만 Map은 값을 저장할 수 있다.
[원문]
https://javascript.info/weakmap-weakset
'맨땅에코딩 > javascript' 카테고리의 다른 글
apply,call,bind 비교 (0) 2020.09.11 [ES6] WeakSet vs Set [번역] (0) 2020.08.09 [ES6] Set vs Array 비교 [번역] (0) 2020.08.07 [ES6] Map vs Object 비교 [번역] (0) 2020.08.07 [ES6] var, let, const 비교 (0) 2020.06.26