WeakMap
이란 객체를 키로 사용하며, 키로 사용된 객체가 다른 곳에서 참조되지 않을 때 자동으로 가비지 컬렉션 될 수 있는 자바스크립트의 자료구조 입니다.
객체와 연결된 데이터를 메모리에 안전하게 저장하고, 객체가 더 이상 필요하지 않을 때 자동으로 데이터를 정리하는 용도로 사용됩니다.
- 키는 객체만 사용할 수 있습니다. 문자열이나 숫자는 사용할 수 없습니다.
set
4가지 메소드만 사용할 수 있습니다.
size
로 몇 개의 데이터를 가지고 있는지 확인하거나 순회를 돌기 위해서는 객체가 계속 메모리를 차지(강한 참조)하고 있어야 하기 때문입니다.
즉, WeakMap
으로는 정확한 크기를 확인하거나 순회할 방법이 없습니다.
약한 참조란, 해당 객체가 다른 곳에서 더 이상 사용되지 않는다면 가비지 컬렉터에 의해 자동으로 메모리에서 제거될 수 있도록 하는 참조입니다.
일반적인 객체나 Map
에 저장한 경우, 더 이상 데이터에 접근할 수 없다고 해도 가비지 컬렉션 대상이 되지 않고 메모리에 남아있게 됩니다.
이는 사용하지 않는 데이터이지만, 메모리에는 존재하게 되어 메모리 누수 문제를 일으킬 수 있습니다.
실제로 WeakMap
을 사용하는 사례를 보면서, 언제/왜 사용하는지 알아보겠습니다.
카드 UI를 DOM에 추가하고, 추가 데이터를 Map
에 저장하는 예제 입니다.
DOM에서는 제거 되었지만, Map
에는 데이터가 남아 메모리 누수 문제가 있습니다.
직접 돔을 추가하고, 제거하면서 크롬 개발자 도구를 통해 메모리 사용량을 확인해보겠습니다.
메모리 사용량을 직관적으로 볼 수 있도록, 카드 만들 때 10MB 크기의 Uint8Array
를 같이 사용했습니다.
- "Create Profile Card" 버튼을 클릭하면 카드를 추가하고, Map에 객체 정보를 추가합니다.
- "Close" 버튼을 누르면 카드를 제거합니다.
카드를 1개 만들었을 때, 예상한대로 Map의 크기는 약 10MB입니다.
추가로 카드를 1개 더 만들었을 떄 Map의 크기는 약 21MB입니다.
정상적으로 메모리에 할당 된 것 같으니, 이제 DOM을 삭제해보겠습니다.
화면상으로는 카드가 사라지고, DOM에서 해제 되었지만, profileDataMap에서 데이터를 삭제하는 코드가 없기 때문에 profileDataMap에는 userData가 남아있어 메모리 사용량이 변하지 않았습니다.
즉, Map은 강한 참조를 가지고 있어서 key
인 card
가 삭제되었어도 profileDataMap
에는 데이터가 그대로 남아 있습니다.
이번에는 WeakMap
으로 동일하게 테스트 해보겠습니다. 11번 라인에 있는 Map()
만 WeakMap()
으로 바꿔주었습니다. 이번에는 메모리 사용량만 바로 확인해보겠습니다.
- 카드 1개 추가 (WeakMap 크기 약 10MB)
- 카드 1개 추가 (WeakMap 크기 약 21MB)
- 카드 1개 추가 (WeakMap 크기 약 31MB)
- 카드 1개 제거 (WeakMap 크기 약 21MB)
- 카드 1개 제거 (WeakMap 크기 약 10MB)
WeakMap
은 약한 참조를 가지고 있어서, 데이터를 삭제하는 코드가 없어도 key
인 card
가 삭제되면 WeakMap
의 데이토 같이 회수되는 것을 확인할 수 있습니다.
Dom
에 추가적인 데이터를 저장할 때 Dom
이 삭제되면 데이터가 같이 삭제되기를 원한다면 WeakMap
을 사용할 수 있습니다.
key
로 지정한 객체가 더 이상 참조되지 않게 되면 메모리가 해제 되는 특성으로 캐싱시에도 유용합니다.