들어가며
자바스크립트를 공부하던 중, ES6부터 Symbol이라는 데이터타입이 추가되었다는 사실을 알았다. Symbol이 대체 뭘까?

Symbol
- Symbol은 ES6에서 도입된 고유하고 변경할 수 없는 값을 생성하는 원시(primitive) 데이터 타입이다.
- 다른 원시 타입(숫자, 문자열, 불리언 등)과 다르게, 심볼은 유일한 식별자로 사용되며 객체의 프로퍼티 키로 주로 활용된다.
- 심벌 이외의 원시 값은 리터럴을 통해 생성하지만 심벌은 Symbol 함수를 호출해 생성한다.
- 이때 생성된 심벌값은 외부에 노출되지 않으며, 다른 값과 절대 중복되지 않는 유일무이한 값이다.
1. 객체 프로퍼티의 고유한 키 생성
문자열 키는 충돌할 위험이 있지만 Symbol을 사용하면 절대 중복되지 않는 고유한 프로퍼티 키를 만들 수 있다. 같은 키 이름 "id"를 사용했더라도 각각 다른 Symbol이므로 충돌이 발생하지 않기 때문에, 외부에서 실수로 접근하거나 덮어쓸 위험이 줄어든다.
예제 1 (문자열 키 충돌)
const obj = {
id = "123",
};
obj[id] = "456"; // 기존 프로퍼티가 덮어씌어짐
console.log(obj);
// 실행결과
{ id: '456' }
예제 2 (Symbol 사용)
const id1 = Symbol("id");
const id2 = Symbol("id"); // 같은 설명을 넣어도 완전히 다른 Symbol
const obj = {
[id1]: "123",
[id2]: "456",
};
console.log(obj[id1]);
console.log(obj[id2]);
console.log(obj);
// 실행결과
123
456
{ [Symbol(id)]: '123', [Symbol(id)]: '456' }
2. 프로퍼티를 은닉(숨김)해 외부 접근 방지
객체의 일반 프로퍼티는 for...in 또는 Object.keys() 등을 사용하면 모두 나열되지만 Symbol을 프로퍼티 키로 사용하면 기본적으로 숨겨지므로(은닉), 외부 접근을 방지할 수 있다.
예제 3 (Symbol로 숨겨진 프로퍼티)
const secretKey = Symbol("secret");
const user = {
name: "velkoz",
age: 20,
[secretKey]: "떡볶이",
};
console.log(Object.keys(user));
console.log(Object.getOwnPropertyNames(user));
// 실행결과
[ 'name', 'age' ]
[ 'name', 'age' ]
💡 그렇다면 Symbol 타입 변수에 API Key 값을 할당해도 되는 걸까?
결론부터 말하자면, 보안상 적절하지 않다. Symbol은 고유한 값이며, 객체의 프로퍼티 키로 사용할 때 충돌을 방지하는 용도로 쓰이지, 보안적인 목적으로 데이터를 보호하는 기능을 제공하지는 않는다. secretKey는 Ojbect.keys()나 for...in을 사용해도 보이지 않지만 Object.getOwnPropertySymbols()을 사용하면 Symbol 키를 확인할 수 있다.
console.log(user[secretKey]);
console.log(Object.getOwnPropertySymbols(user));
// 실행결과
떡볶이
[ Symbol(secret) ]
Reflect.ownKeys()를 사용하면 Symbol 키까지 포함해서 조회할 수 있다.
예제 4
const API_KEY = Symbol("secret");
const config = {
[API_KEY]: "super-secret"
};
console.log(config[API_KEY]);
console.log(Reflect.ownKeys(config));
// 실행결과
super-secret
[ Symbol(secret) ]
3. Symbol.for()를 이용해 전역적으로 공유
Symbol()을 직접 사용하면 매번 새로운 심볼이 생성되지만, Symbol.for()를 사용하면 전역 심볼 레지스트리(Global Symbol Registry)에 등록해 같은 키에 대해 전역적으로 같은 심볼을 참조할 수 있기 때문에 Symbol을 재사용할 수 있다.
예제 5
const sym1 = Symbol.for("sharedKey");
const sym2 = Symbol.for("sharedKey");
console.log(sym1 === sym2);
// 실행결과
true
4. 내부 심볼 (Symbols for Built-in Features) 활용
Symbol.iterator를 사용하면 객체에 반복자(iterator)를 추가해 for...of 루프에서 사용할 수 있다.
예제 6
class CustomCollection {
constructor(items) {
this.items = items;
}
[Symbol.iterator]() {
let index = 0;
return {
next: () => ({
value: this.items[index++],
done: index > this.items.length
})
};
}
}
const collection = new CustomCollection(["a", "b", "c"]);
for (const item of collection) {
console.log(item);
}
// 실행결과
a
b
c
참고
'Language > JavaScript' 카테고리의 다른 글
[JS] Math.random() 보안 취약점과 해결방안 (0) | 2025.03.15 |
---|---|
[JS] forEach(console.log) (0) | 2025.03.02 |