JavaScript Symbol

JavaScript의 Symbol은 ES6(ECMAScript 2015)에서 도입된 원시 데이터 타입입니다. 심볼은 유일하고 변경 불가능한 값으로, 객체의 프로퍼티 키로 사용됩니다. 이 특성 덕분에 심볼은 객체의 프로퍼티를 고유하게 만들고, 충돌을 피할 수 있습니다. 심볼에 대해 자세히 살펴보겠습니다.

1. Symbol 기본 개념

1.1 Symbol 생성

SymbolSymbol() 함수를 사용하여 생성합니다. 이 함수는 매번 호출할 때마다 새로운 유일한 심볼 값을 반환합니다.

const sym1 = Symbol();
const sym2 = Symbol();
console.log(sym1 === sym2); // false

1.2 심볼 설명

심볼을 생성할 때 선택적으로 설명(description)을 추가할 수 있습니다. 설명은 디버깅 시 유용합니다.

const sym = Symbol('description');
console.log(sym.description); // 'description'

2. Symbol 사용

2.1 객체의 프로퍼티 키로 사용

심볼은 객체의 프로퍼티 키로 사용할 수 있으며, 이를 통해 객체의 프로퍼티를 고유하게 만들 수 있습니다.

const sym = Symbol('key');

const obj = {
  [sym]: 'value'
};

console.log(obj[sym]); // 'value'

2.2 심볼의 유일성

각 심볼은 유일하므로, 같은 설명을 가진 두 심볼도 서로 다른 심볼입니다.

const sym1 = Symbol('key');
const sym2 = Symbol('key');

console.log(sym1 === sym2); // false

2.3 심볼의 비공식 속성

심볼은 객체의 비공식 속성(숨겨진 속성)으로 사용되며, 객체의 프로퍼티 열거와 같은 작업에서 제외됩니다.

const sym = Symbol('hidden');
const obj = {
  [sym]: 'hiddenValue',
  visible: 'visibleValue'
};

console.log(Object.keys(obj)); // ['visible']
console.log(Object.getOwnPropertySymbols(obj)); // [Symbol(hidden)]
console.log(obj[sym]); // 'hiddenValue'

3. Symbol 관련 내장 심볼

JavaScript에는 몇 가지 내장 심볼이 있으며, 이들은 특정 기능을 위해 사용됩니다.

3.1 Symbol.iterator

이 심볼은 객체가 이터러블(iterable) 객체임을 나타내는 데 사용됩니다. 이터러블 객체는 for...of 루프와 spread 연산자와 같은 구문에서 사용됩니다.

const iterableObj = {
  *[Symbol.iterator]() {
    yield 1;
    yield 2;
    yield 3;
  }
};

for (const value of iterableObj) {
  console.log(value); // 1 2 3
}

3.2 Symbol.toStringTag

이 심볼은 객체의 기본 문자열 표현을 커스터마이즈하는 데 사용됩니다. Object.prototype.toString 메서드에서 반환되는 기본 문자열을 변경할 수 있습니다.

const obj = {
  [Symbol.toStringTag]: 'CustomObject'
};

console.log(Object.prototype.toString.call(obj)); // [object CustomObject]

3.3 Symbol.hasInstance

이 심볼은 instanceof 연산자가 객체가 특정 클래스의 인스턴스인지 확인하는 방식을 커스터마이즈하는 데 사용됩니다.

class MyClass {
  static [Symbol.hasInstance](instance) {
    return instance.customProperty === true;
  }
}

const obj = { customProperty: true };
console.log(obj instanceof MyClass); // true

3.4 Symbol.toPrimitive

이 심볼은 객체가 원시 값을 변환하는 방법을 정의하는 데 사용됩니다. valueOftoString 메서드와 함께 원시 값으로 변환됩니다.

const obj = {
  [Symbol.toPrimitive](hint) {
    if (hint === 'number') return 42;
    if (hint === 'string') return 'hello';
    return true;
  }
};

console.log(+obj); // 42
console.log(`${obj}`); // hello
console.log(obj + ''); // 'true'

3.5 Symbol.unscopables

이 심볼은 with 문에서 객체의 프로퍼티를 숨기기 위해 사용됩니다.

const obj = {
  prop: 1,
  [Symbol.unscopables]: { prop: true }
};

with (obj) {
  console.log(prop); // ReferenceError: prop is not defined
}

4. Symbol의 활용 사례

4.1 프로퍼티의 비공식적인 키

심볼을 사용하여 객체의 프로퍼티를 비공식적으로 설정하면, 다른 코드에서 해당 프로퍼티에 쉽게 접근할 수 없으므로 은닉된 정보를 안전하게 저장할 수 있습니다.

const secret = Symbol('secret');
const obj = {
  [secret]: 'hiddenValue'
};

// 외부에서 접근 불가
console.log(obj[secret]); // 'hiddenValue'

4.2 라이브러리 및 프레임워크에서의 사용

심볼은 라이브러리 및 프레임워크에서 내부 상태를 관리하거나 API와의 충돌을 방지하는 데 유용합니다.

const privateData = Symbol('privateData');

class MyClass {
  constructor(data) {
    this[privateData] = data;
  }

  getData() {
    return this[privateData];
  }
}

const instance = new MyClass('secret');
console.log(instance.getData()); // 'secret'

결론

JavaScript의 Symbol은 고유하고 변경 불가능한 값을 생성하여 객체의 프로퍼티 키로 사용하기에 매우 유용한 기능입니다. 이 특성 덕분에 심볼은 객체의 프로퍼티를 고유하게 만들고, 라이브러리 및 프레임워크의 내부 상태를 안전하게 관리하는 데 도움을 줍니다. 심볼의 내장 심볼과 다양한 활용 사례를 이해하면, JavaScript에서 더 효과적으로 프로그래밍할 수 있습니다.

Leave a Reply

Your email address will not be published. Required fields are marked *