HyunJun 기술 블로그

Symbol 본문

JavaScript

Symbol

공부 좋아 2023. 7. 25. 15:17
728x90
반응형

Symbol

JavaScript의 Symbol은 원시 데이터 타입(primitive data type)으로, 유일하고 변경 불가능한 값이다. Symbol은 ES6(ECMAScript 2015)에서 도입되었다.

 

1. 사용 목적 & 방법

왼쪽의 변수명이 Symbol 객체를 식별하는 식별자가 되고, 오른쪽의 Symbol("")에 들어가는 문자열은 해당 Symbol에 대한 설명(description)이라고 할 수 있다. 이 문자열은 Symbol을 구분하거나 식별하는 데 사용되지 않으며, 단지 Symbol 객체를 디버깅하는 등의 용도로 사용된다. 이 문자열은 Symbol의 내부 속성으로 저장되며, Symbol 객체를 출력할 때나 디버깅 도구에서 사용될 수 있다.

const fooSymbol = Symbol("foo");
const barSymbol = Symbol("bar");

이렇게 하면 fooSymbol과 barSymbol은 서로 다른 Symbol 객체가 된다. 두 Symbol 객체가 내부적으로는 다르지만 같은 설명("foo"와 "bar")을 가지고 있으므로 디버깅 시에 구분하기 쉬워진다.

 

 

1) 유일한 키(key) 생성

Symbol을 객체의 키로 사용하면 다른 어떤 프로퍼티 키와도 충돌하지 않고 유일성이 보장된다. 객체의 프로퍼티 키로 사용되는 일반적인 문자열 키와는 다르게, Symbol은 외부에서 접근할 수 없으므로 객체의 특정 프로퍼티에 접근하기 위해서는 해당 Symbol을 알고 있어야 한다.

  const fooSymbol = Symbol("foo");
  const obj = {
    [fooSymbol]: "Hello",
  };

  console.log(obj.fooSymbol); // undefined
  console.log(obj["fooSymbol"]); // undefined
  console.log(obj[fooSymbol]); // "Hello"

문자열 키와의 차이, Symbol은 문자열 키와 다르게 직접적으로 프로퍼티에 접근하는 데에 사용되지 않는다. 문자열 키를 사용한 경우 해당 프로퍼티에 접근하기 위해서는 객체의 점 표기법 또는 괄호 표기법을 사용해야 한다. 예를 들어, obj.foo 또는 obj["foo"]와 같이 접근한다. 그러나 Symbol을 사용한 경우 해당 Symbol을 먼저 변수로 정의하고, 그 변수를 통해 프로퍼티에 접근한다.

 

2) 프로퍼티 키 열거(Enumeration)

Symbol을 프로퍼티 키로 사용한 경우 for...in 루프나 Object.keys()와 같은 메서드를 사용하여 객체의 프로퍼티들을 열거할 때 해당 Symbol 프로퍼티는 열거되지 않는다. 이는 일반적으로 객체의 내부 동작과 관련된 메타데이터를 숨기기 위해 사용된다.

  const fooSymbol = Symbol("foo");
  const obj = {
    [fooSymbol]: "Hello",
    bar: "World",
  };

  for (const key in obj) {
    console.log(key); // "bar"만 출력됨, fooSymbol은 열거되지 않음
  }

  console.log(Object.keys(obj)); // ["bar"], fooSymbol은 포함되지 않음

결론적으로, Symbol은 문자열 키와 다르게 직접적으로 접근할 수 없으며, 프로퍼티 키 열거에서도 제외되기 때문에 외부에 노출되지 않는다. 그러나 정확히 말하면 완전히 노출되지 않는 것은 아니며, 약간의 노출이 있을 수 있다. 예를 들어, Object.getOwnPropertySymbols() 메서드를 사용하면 객체의 모든 Symbol 프로퍼티를 가져올 수 있다. 하지만 이런 경우도 해당 Symbol 프로퍼티에 접근하기 위해서는 해당 Symbol을 알아야 하기 때문에 실제로는 노출이 매우 제한적이다.

 

2. 전역 레지스트리 & 지역 레지스트리

전역 레지스트리와 지역 레지스트리는 JavaScript의 Symbol 객체를 생성하고 관리하는 방식을 설명하는 개념이다. 

 

1) 전역 레지스트리 (Global Registry): 

  • 전역 레지스트리는 JavaScript에서 Symbol.for() 메서드를 통해 생성된 Symbol 객체들을 저장하는 공유된 레지스트리이다.
  • Symbol.for(key: string): symbol 메서드를 사용하여 Symbol을 생성하면, 이 메서드는 전역 레지스트리에서 주어진 키(key)를 검색하고, 해당 키에 대한 Symbol이 이미 존재한다면 해당 Symbol을 반환한다.
  • 만약 전역 레지스트리에 해당 키로 생성된 Symbol이 없다면, 새로운 Symbol을 생성하여 전역 레지스트리에 등록하고 해당 Symbol을 반환한다.
  • 전역 레지스트리에 등록된 Symbol은 애플리케이션 전체에서 공유된다.
const mySymbol1 = Symbol.for("mySymbol"); // 전역 레지스트리에 등록됨
const mySymbol2 = Symbol.for("mySymbol"); // 이미 등록된 키로 검색하여 mySymbol1과 동일한 Symbol을 반환

console.log(mySymbol1 === mySymbol2); // true, 같은 Symbol을 공유

 

2) 지역 레지스트리 (Local Registry)

  • 지역 레지스트리는 JavaScript에서 Symbol() 생성자를 통해 생성된 Symbol 객체들을 저장하는 개별적인 레지스트리이다.
  • Symbol() 생성자를 사용하여 Symbol을 생성하면, 매번 새로운 고유한 Symbol을 생성한다. 따라서 Symbol()로 생성된 Symbol은 항상 새로운 값이며, 전역 레지스트리와는 별개이다.
  • 지역 레지스트리는 변수에 할당하여 관리하는 방식으로 Symbol을 사용한다.
const mySymbol1 = Symbol(); // 새로운 고유한 Symbol을 생성
const mySymbol2 = Symbol(); // 또 다른 새로운 고유한 Symbol을 생성

console.log(mySymbol1 === mySymbol2); // false, 항상 다른 Symbol 값

 

전역 레지스트리와 지역 레지스트리를 활용하여 Symbol을 생성하면 다음과 같은 특징이 있다 

  • Symbol.for()로 생성된 Symbol은 전역 레지스트리에 등록되어 애플리케이션 전체에서 공유된다.
  • Symbol()로 생성된 Symbol은 항상 새로운 고유한 값이므로 다른 Symbol과는 동일한 키를 가질 수 없다.
  • Symbol.for()로 생성된 Symbol과 Symbol()로 생성된 Symbol은 서로 다른 레지스트리에 속하며, 별개로 동작한다.

 

일반적으로 전역 레지스트리를 사용하여 Symbol을 생성하면 애플리케이션 전역에서 공유되기 때문에 필요한 경우가 아니라면 지역 레지스트리인 Symbol()을 사용하여 지역적인 Symbol을 생성하고 관리하는 것이 더 적절하다.

 

3) Symbol.keyFor

Symbol.keyFor(sym: symbol): string | undefined는 전역 레지스트리에 등록된 Symbol 객체의 키를 검색하는 메서드이다. 이 메서드는 주어진 Symbol 객체(sym)가 전역 레지스트리에 등록되어 있는지 확인하고, 만약 등록되어 있다면 해당 Symbol의 키를 반환한다. 그렇지 않으면 undefined를 반환한다. 

 

이 메서드는 Symbol.for()로 생성된 Symbol 객체에만 동작하며, 일반적으로 Symbol()로 생성된 Symbol에는 사용할 수 없다. Symbol.keyFor() 메서드를 사용하여 전역 레지스트리에 등록된 Symbol 객체의 키를 검색할 수 있다. 예를 들어, 다음과 같이 Symbol.for()로 생성된 Symbol을 전역 레지스트리에서 검색하는 예제이다.

const mySymbol = Symbol.for("mySymbol");
const key = Symbol.keyFor(mySymbol);

console.log(key); // "mySymbol", 전역 레지스트리에 등록된 키를 반환

 

만약 Symbol.for()로 생성하지 않은 Symbol에 대해 Symbol.keyFor()를 호출하면 undefined가 반환된다.

const mySymbol = Symbol("mySymbol");
const key = Symbol.keyFor(mySymbol);

console.log(key); // undefined, 전역 레지스트리에 등록되지 않은 Symbol이므로 undefined
728x90
반응형
Comments