Computer >> 컴퓨터 >  >> 프로그래밍 >> JavaScript

자바스크립트에서 WeakMap이 필요한 이유는 무엇일까?

WeakMap 객체는 키(key)가 약한 참조(weak reference)로 유지되는 키-값 쌍의 컬렉션입니다. 키는 반드시 객체여야 하며, 값은 어떤 타입이든 자유롭게 지정할 수 있습니다.

약한 참조(Weak Reference)란?

위키백과에 따르면, 약한 참조란 강한 참조(strong reference)와 달리 참조 대상 객체가 가비지 컬렉터(garbage collector)에 의해 수거되는 것을 막지 않는 참조를 의미합니다. 객체를 가리키는 모든 참조 경로에 최소 하나의 약한 참조만 포함되어 있다면, 그 객체는 '약하게 도달 가능(weakly reachable)'한 상태로 간주됩니다. 이런 객체는 도달 불가능(unreachable)한 것처럼 취급되며, 언제든지 가비지 컬렉션의 대상이 될 수 있습니다.

즉, WeakMap에 저장된 키 객체가 프로그램의 다른 곳에서 더 이상 사용되지 않으면, WeakMap이 해당 객체를 붙잡아 두지 않기 때문에 메모리가 자동으로 회수됩니다. 이것이 일반적인 Map과 WeakMap의 핵심적인 차이입니다.

WeakMap이 필요한 대표적인 이유

일반적인 Map이나 객체에 데이터를 저장하면 메모리 누수(memory leak)가 발생할 수 있는 상황에서, WeakMap을 활용하면 이러한 문제를 깔끔하게 해결할 수 있습니다. 주요 활용 사례는 다음과 같습니다.

  • 객체의 비공개(private) 데이터 관리 — 특정 객체에 대한 내부 데이터를 저장하고, 해당 Map에 대한 참조를 가진 코드에만 접근을 허용함으로써 캡슐화를 실현할 수 있습니다.

  • 라이브러리 객체에 대한 부가 정보 저장 — 라이브러리 객체 자체를 수정하지 않고도, 추가적인 성능 오버헤드 없이 관련 데이터를 보관할 수 있습니다.

  • 히든 클래스(hidden class) 문제 방지 — 동일한 타입의 객체가 매우 많이 존재하는 상황에서 소수의 객체에만 데이터를 연결해야 할 때, JS 엔진이 객체 타입별로 최적화에 사용하는 히든 클래스 구조를 해치지 않고 데이터를 관리할 수 있습니다.

  • 호스트 객체(host object)에 대한 데이터 보관 — 브라우저의 DOM 노드처럼 임의로 속성을 추가하기 어려운 호스트 객체와 관련된 데이터를 안전하게 저장할 수 있습니다.

  • 외부에서 객체에 기능(capability) 부여 — 원본 객체를 변경하지 않은 채 외부에서 새로운 기능이나 속성을 덧붙일 수 있습니다.

간단한 사용 예시

다음은 WeakMap을 활용해 클래스의 비공개 데이터를 관리하는 전형적인 패턴입니다.

const privateData = new WeakMap();

class User {
  constructor(name, age) {
    this.name = name; // 공개 속성
    privateData.set(this, { age }); // 비공개 데이터
  }
  getAge() {
    return privateData.get(this).age;
  }
}

const user = new User('철수', 30);
console.log(user.getAge()); // 30
console.log(user.age);      // undefined — 외부에서 접근 불가

User 인스턴스가 더 이상 참조되지 않으면, privateData에 저장된 나이 정보 역시 함께 가비지 컬렉션되므로 메모리 누수 걱정 없이 비공개 데이터를 유지할 수 있습니다.