본문 바로가기

[자바스크립트] Map, Set, WeakMap, WeakSet

 

 

 

들어가며

여행을 떠나보면, 언젠가 왜 이 여행을 하려 했을까 하는 생각이 들 때가 있었습니다. 공부를 할 때도 마찬가지였습니다. 자바스크립트를 활용해서 개발하고 있는데, 자바스크립트에 대한 기본은 알고 있는지, 왜 자바스크립트로 개발을 하려고 했는지 이유가 궁금할 때가 있었습니다. 이 고민에 대한 해답을 찾기 위해서는 자바스크립트, Node.js에 대해 자세하게 알아야겠다고 생각했습니다. 이번 기회를 통해 자바스크립트, Node.js에 대해 이해해야겠다고 생각했습니다. 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Map과 Set

ES2015에서는 해시 맵 컬렉션을 활용하도록 Map이라는 새로운 프로토타입을 도입했습니다. 간단히 예를 들어보겠습니다.

 

 

const profiles = new Map();
profiles.set('twitter', '@adalovelace');
profiles.set('facebook', 'adalovelace');
profiles.set('googleplus', 'ada');

console.log(profiles.size);
console.log(profiles.has('twitter'));
console.log(profiles.get('twitter'));
console.log(profiles.has('youtube'));
console.log(profiles.delete('facebook'));
console.log(profiles.has('youtube'));
console.log(profiles.get('youtube'));
for (const entry of profiles) {
	console.log(entry);
}

 

 

 

Map 프로토타입에는 set, get, has, delete, size와 같은 몇 가지 편리한 메서드 및 속성을 제공합니다. 또한 for 구문을 사용하여 모든 항목들을 반복할 수도 있습니다. 루프 내 모든 entry는 배열로서, 첫 번째 요소로 키를 두 번째 요소로 값을 갖습니다. 

 

심지어 Map을 활용하면 함수와 객체를 Map의 키로 사용할 수 있습니다. 예를 들어 이 기능을 활용하여 정밀한 테스트 프레임워크를 만들 수 있습니다. 

 

const tests = new Map();
tests.set(() => 2+2, 4);
tests.set(() => 2*2, 4);
tests.set(() => 2/2, 1);

for (const entry of tests) {
  console.log((entry[0]() === entry[1]) ? 'PASS' : 'FAIL')
}

 

위처럼 우리는 함수를 키로 예상되는 결과를 값으로 저장했습니다. 그런 다음 map 반복 구문을 통해 실행할 때 모든 entry들은 삽입 순서대로 출력됨을 알 수 있습니다.

 

ES2015는 Map과 함께 Set 프로토타입도 소개하고 있습니다. 이 프로토타입을 사용하면 모든 요소들이 유일한 고윳값을 가지는 목록인 집합(set)을 쉽게 만들 수 있습니다.

 

const s = new Set([0, 1, 2, 3]);
console.log(s.add(3))
console.log(s.size)
console.log(s.delete(0))
console.log(s.has(0))

for(const entry of s) {
  console.log(entry);
}

 

Set은 위의 Map과 매우 유사합니다. Set에서는 add(set을 대신함)와 has 그리고 delete 함수와 size 속성이 있습니다. 또한 set을 반복 구문으로 사용할 수도 있는데, 이 경우 모든 요소들은 값이 됩니다. 위 예에서는 set 내에 있는 숫자 중 하나가 될 것입니다. 마지막으로, set은 그 요소로 객체와 함수를 가질 수 있습니다. 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

WeakMap과 WeakSet

위에서 Map과 Set에 대해 살펴봤습니다. 하지만 ES2015는 WeakMap 및 WeakSet이라는 Map 및 Set 프로토타입에 대한 "weak" 버전도 정의해서 제공하고 있습니다. 

 

WeakMap은 인터페이스 측면에서 Map과 매우 유사합니다. 그러나 알아야 할 중요한 차이점이 두 가지 있습니다. WeakMap은 가지고 있는 요소 전체를 반복 구문으로 탐색할 방법이 없으며, 객체 만을 키로 가질 수 있습니다. 이것은 제약 사항처럼 보일 수 있지만 거기에는 그럴만한 이유가 있습니다. 실제, WeakMap의 독특한 특징은 키로 사용된 객체에 대한 유일한 참조가 WeakMap 내에만 남아 있을 경우, 이 객체를 가비지 컬렉트(garbage collect)할 수 있다는 것입니다. 이것은 애플리케이션의 생명 주기 내에서 삭제되어야 할 객체와 관련된 몇몇 메타 데이터를 저장하는 경우 매우 유용합니다. 예를 들어 보겠습니다.

 

 

let obj = {};
const map = new WeakMap();
map.set(obj, {key: "some_value"});
console.log(map.get(obj));
obj = undefined;
console.log(map.get(obj));

 

이 코드에서 obj 일반 객체를 생성합니다. 그런 다음 이 객체에 대한 메타 데이터를 map이라는 WeakMap에 저장합니다. 이 메타 데이터는 map의 get 메서드를 통해 획득할 수 있습니다. 그런 후 해당 객체에 undefined를 값으로 할당함으로써 객체를 제거할 수 있는데, 이렇게 되면 객체는 가비지 컬렉터에 의해 정리되고 메타 데이터는 map에서 제거됩니다.

 

WeakMap과 유사하게 WeakSet 또한 Set의 weak 버전입니다. 마찬가지로, Set과 WeakSet의 차이는 WeakSet 내 유일 참조가 남을 경우 해당 객체를 가비지 컬렉트 할 수 있다는 것입니다.

 

let obj1 = {key: "val1"};
let obj2 = {key: "val2"};
const set = new WeakSet([obj1, obj2]);
console.log(set.has(obj1));
obj1 = undefined;
console.log(set.has(obj1));

 

WeakMap과 WeakSet이 Map과 Set 보다 좋거나 나쁜 것이 아니라 단지 사용처가 서로 다르다는 점을 이해하는 것이 중요합니다. 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

마치며

자바스크립트, Node.js를 공부하면서, 내가 사용하는 언어나 언어의 환경에 대해 자세하게 이해해야겠다고 생각했습니다. 그래야만 내가 사용하고 있는 언어에 대한 깊은 이해를 할 수 있다고 생각합니다. 이렇게 기초적인 부분을 습득하다 보면, 언젠가는 좋은 개발자로 성장할 수 있다고 믿습니다.

 

 

 

 

 

 

 

 

 

 

 

 

 

 


 

 

 

 

 

 

 

 

 

 

 

 

 

출처

 

Node.js 디자인 패턴:모듈형의 확장 가능한 서버 측 어플리케이션 제작을 위한

COUPANG

www.coupang.com