JavaScript의 Symbol
은 ES6(ECMAScript 2015)에서 도입된 원시 데이터 타입입니다. 심볼은 유일하고 변경 불가능한 값으로, 객체의 프로퍼티 키로 사용됩니다. 이 특성 덕분에 심볼은 객체의 프로퍼티를 고유하게 만들고, 충돌을 피할 수 있습니다. 심볼에 대해 자세히 살펴보겠습니다.
1. Symbol 기본 개념
1.1 Symbol 생성
Symbol
은 Symbol()
함수를 사용하여 생성합니다. 이 함수는 매번 호출할 때마다 새로운 유일한 심볼 값을 반환합니다.
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
이 심볼은 객체가 원시 값을 변환하는 방법을 정의하는 데 사용됩니다. valueOf
및 toString
메서드와 함께 원시 값으로 변환됩니다.
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에서 더 효과적으로 프로그래밍할 수 있습니다.