TIL 95 - WeakMap, WeakSet(feat. GC)

김영현·2024년 5월 29일
0

TIL

목록 보기
106/129

WeakMap

WeakMapMap하고 유사한 기능을 가진 자료구조다. 즉, key => value를 연결하는 자료구조다.
다만 특이한점은 키값을 오직 객체로만 받는다.
왜 객체로만 받을까?

Map과 WeakMap의 차이

Map, WeakMap 둘 다 키를 객체로 받을 수 있다.(후자는 정확히 말하면 객체만 받는다)

const map = new Map();
let obj = { a: 1 };
map.set(obj, "object");

console.log(map.get(obj)); //(1)

obj = null;

console.log(map); //(2)

console.log("-------------"); //구분선

const weakMap = new WeakMap();
let obj2 = { b: 1 };
weakMap.set(obj2, "object2");

console.log(weakMap.get(obj2)); //(3)

obj2 = null;

console.log(weakMap); //(4)

키를 객체로 받았다는 건, 값이 키를 참조함을 의미한다. GC의 도달 가능성관점에서 보면, 자료구조의 값이 키를 계속 참조하고 있으므로 GC의 영향을 받지 않아야한다.

1번, 2번의 결과는 예상대로 아래와 같다.

하지만 WeakMap의 경우는 달라진다.

왜 이런현상이 발생할까?
=> WeakMap로 받아온 객체약한참조로 저장한다. 다시말해 얕은 복사를 수행한다.
아하 그렇단 얘기는 Map자료구조에서는 로 받아온 객체깊은복사해서 저장했단 거구나!

위와같은 이유로 WeakMap에 존재하는 메서드는 단 4가지get, set, delete, has다.
=> 키가 언제 GC에 의해 삭제될지 모르므로 사이즈 측정이 불가능하며 순회또한 불가능하다. (그래서 <items unknown>이 출력된다)

뭔가 쓸모없어 보이지만, 이런 자료구조는 분명 필요에 의해 만들어진다. 언어 자체에 추가됐다는 건 생각보다 쓸 일이 많다는 걸까?

WeakMap 활용 예시1) 캐시

객체를 키로하여 어떤 연산의 결과를 캐시하고싶다!

const cache = new WeakMap();

const calculateResult = (obj) => {
    if (cache.has(obj)) {
        return cache.get(obj);
    }
    const result = performExpensiveCalculation(obj); //연산 비용이 비싼 행위
    cache.set(obj, result);
    return result;
}

만약 기존의 Map을 활용했더라면, 캐시가 필요없어졌을 때 일일히 객체로된 키를 삭제해주어야 할 수 도있다.
그러나 WeakMap을 사용하여 메모리에서 객체가 삭제될때 캐시도 같이 삭제되게 만들 수 있다.

WeakMap 활용 예시2) third-party data

출처:https://ko.javascript.info/weakmap-weakset

사용자의 방문 횟수를 세어주는 코드가 있다고 가정해보자. 이 정보를 원래 Map사용자 객체로하여 저장하고있었다.
하지만 기존 코드는 사용자 객체가 초기화되어도 Map에 키로 남아있어 메모리 누수가 생긴다.

// 📁 visitsCount.js
let visitsCountMap = new WeakMap(); // 위크맵에 사용자의 방문 횟수를 저장함

// 사용자가 방문하면 방문 횟수를 늘려줍니다.
function countUser(user) {
  let count = visitsCountMap.get(user) || 0;
  visitsCountMap.set(user, count + 1);
}

let john = {...some};

countUser(john);

john = null;

visitsCountMap // <items unknown>

이렇게 WeakMap을 이용하여 관리해준다면 visitsCountMap에서 필요 없어진 데이터를 제거해줄 필요가 없다.


WeakSet

WeakSet은 Set과 유사하지만, 객체만 내부에 저장 가능하다. 또한 size, kesy()등의 반복 관련 메서드를 사용할 수 없다.
사실 WeakMap <=> Map의 관계와 아주 유사하다. 다만 복잡한 값 대신 간단한 값을 넣어 has등의 메서드로 존재하는지만 체크하는 용도로 많이 사용한다고 한다.


느낀점

들어보지도 못했던 자료구조인데 생각보다 신선했다. 다만 언제 어떻게 써야하는지 알아놓고 정작 실제로는 거의 써먹지 못할 것 같다 ㅋㅋ
최근 프로그래머스에서 백준으로 넘어가 알고리즘 문제를 풀고있는데, 메모리 관리가 굉장히 중요하다는 점을 다시금 깨닫고 있다.
시간복잡도도 중요하지만, 공간복잡도도 그만큼 중요하다!

profile
모르는 것을 모른다고 하기

0개의 댓글