JavaScript/기초

[JavaScript]Symbol이란?

DevStory 2021. 12. 31.

Symbol이란?

ECMAScript 2015부터 심볼(Symbol)이라는 새로운 원시 타입이 도입되었습니다. Symbol은 고유하고 변경할 수 없는 식별자를 생성하며, 한 번 생성하면 복사할 수 없습니다.

 

Symbol의 사용 목적은 객체의 고유한 프로퍼티 키를 만들기 위해 사용됩니다.

 

이번 포스팅에서는 Symbol의 다양한 예제와 사용 방법을 통해 Symbol이 무엇인지 설명합니다. 

 


Symbol 사용 방법

다음은 Symbol을 생성하는 예제입니다.

const name = Symbol('nameDescription');
const sym = Symbol();

Symbol은 위 예제처럼 Symbol() 함수로 생성할 수 있습니다. Symbol('nameDescription')과 같이 인자를 전달할 수 있는데, 인자는 디버깅 목적으로 Symbol에 대해 설명을 해주는 역할을 하며 특별한 의미를 가지고 있지 않습니다.

 

Symbol은 내장 객체와 비슷하지만 생성자가 없으므로 new 연산자를 사용하여 Symbol을 생성할 수 없습니다.

const sym = new Symbol();

실행 결과

 

Symbol() 함수는 변경 불가능한 고유한 Symbol을 반환하므로 다음처럼 두 개의 Symbol을 비교하면 false를 반환합니다.

Symbol('test') === Symbol('test')
// false

Symbol('test') == Symbol('test')
// false

Symbol을 생성하는 또 다른 방법

Symbol.for() 함수로 Symbol을 생성할 수 있습니다.

let sym1 = Symbol.for('id');
let sym2 = Symbol.for('id');

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

Symbol 객체는 생성되면 전역 심볼 레지스트리(global symbol registry)에 저장됩니다. 전역 심볼 레지스트리에 저장된 Symbol은 iframe 내부에 생성된 Symbol을 의미합니다.

 

Symbol.for() 함수는 전달된 키가 전역 심볼 레지스트리에 존재하는지 검색합니다. 검색에 성공하면 검색된 Symbol을 반환하며, 검색에 실패하면 새로운 Symbol을 생성하여 전역 심볼 레지스트리에 등록 후 생성된 Symbol을 반환합니다.

 

▶ Symbol.keyFor

Symbol.for() 함수로 생성된 Symbol은 키를 가지고 있으며, Symbol.keyFor() 함수로 Symbol의 키를 찾을 수 있습니다. 하지만 Symbol() 함수로 생성된 Symbol은 키가 존재하지 않습니다.

let sym1 = Symbol.for('id');
console.log(Symbol.keyFor(sym1));
// id

let sym2 = Symbol('id');
console.log(Symbol.keyFor(sym2));
// undefined

객체의 속성으로 사용하기

Symbol의 사용 목적을 위에서 객체의 고유한 프로퍼티 키를 만들기 위해 사용된다고 언급하였습니다. 다음은 객체의 속성으로 Symbol을 사용하는 예제입니다.

const obj = {};
const sym = Symbol();
obj[sym] = 'symValue';
obj.propKey = 'propValue';

console.log(obj);
// { propKey: 'propValue', Symbol(): ' symValue'}

console.log(obj[sym]);
// symValue

console.log(obj.sym);
// undefined

console.log(sym in obj);
// true

console.log(Object.keys(obj));
// ['propKey']

console.log(Object.getOwnPropertySymbols(obj));
// [Symbol()]

console.log(Reflect.ownKeys(obj));
// ['propKey', Symbol()]

Object.keys() 함수는 객체의 열거 가능하고 명명된(문자열 키) 속성을 배열 형식으로 반환합니다. 하지만, Symbol은 문자열(String)과는 다른 타입이므로 Object.keys() 함수는 Symbol을 인식하지 못합니다.

 

객체의 키가 Symbol 타입인 키를 추출하기 위해서는 Object.getOwnPropertySymbols() 함수를 사용해야 합니다. Symbol 타입을 포함한 모든 객체의 키를 배열로 추출해야 하는 경우에는 Reflect.ownKeys() 함수를 사용합니다.


객체의 키 이름 충돌 방지

위에서 설명한 예제를 통해 아래 내용을 확인했습니다.

  • Symbol은 새로운 원시 타입
  • Symbol은 고유한 값
  • Symbol을 사용하여 객체의 키 정의

 

Symbol 타입은 객체의 키를 추가하려는 상황에서 유용한데, 다음 예제를 통해 설명합니다.

// 라이브러리에서 제공하는 함수라고 가정
function libFunc(obj) {
  obj.id = 0;
}

libFunc() 함수가 라이브러리에서 제공하는 함수라고 가정합니다. 그리고 객체의 id라는 속성이 플랫폼 서비스의 사용자 로그인 id 값을 가진다고 가정 후 libFunc() 함수와 anotherLibFunc() 함수에 인자로 전달하게 되면, 중요한 값인 객체의 id 값이 0으로 변경되는 문제가 발생합니다.

 

이러한 문제를 해결하기 위해 각 라이브러리는 Symbol을 사용하여 고유한 값을 객체의 키로 설정합니다.

const libraryKey = symbol('libraryKey');

function libFunc(obj) {
  obj[libraryKey] = 0;
}
반응형

댓글