Language/Javascript

Javascript - Symbol(심볼)이란?

둉이 2021. 12. 30. 05:14

 

자바스크립트의 원시형 데이터 타입으로는 총 6가지가 있다.

 

  1. 숫자(Number)
  2. 문자열(String)
  3. 불리언(boolean)
  4. undefined
  5. null
  6. 심볼(Symbol)

 

그 중에서도 심볼이라는 타입이 있는데, 추가된 지도 얼마 안됐고(ES6) 보통 잘 사용되지는 않다 보니 지금까지 이게 뭘까 싶었는데, 오늘에서야 공부를 하게 됐다.

 

오늘은 심볼 타입에 대해 알아보자!

 


 

 

먼저, 심볼의 정의부터 알아보자면,

심볼(Symbol)이란?

다른 값과 중복되지 않는 자료형(unique)

이다.

 

심볼은 유일성이 보장되는 자료형이기 때문에 일반적으로 심볼 타입은 객체의 프로퍼티 키로 사용된다.

 

그럼 심볼 값은 어떻게 생성하며, 또 어떻게 사용할 수 있는지 알아보자!

 

심볼 값 생성

심볼 값은 Symbol() 함수를 호출하여 생성한다.

이 함수를 통해 생성된 심볼 값은 외부로 노출되지 않으며 다른 값과 절대 중복되지 않는다.

const sym = Symbol('name');

console.log(sym);  // Symbol(name)
console.log(typeof sym);  // symbol

 

참고로 Symbol() 함수 앞에 new 키워드를 붙여 사용하는 경우 TypeError가 발생한다.

(Uncaught TypeError: Symbol is not a constructor.)

 

 

그리고 Symbol() 함수에는 문자열 인자를 전달할 수 있는데, 이는 심볼 값에 대한 설명으로 심볼 값 생성에 영향을 주지 않는다.

 

생성할 때 전달한 심볼 값에 대한 설명은 description 프로퍼티로 접근이 가능하다.

const s1 = Symbol('hihi');
const s2 = Symbol('hihi');

console.log(s1 === s2);  // false
console.log(s1.description);  // hihi

const s3 = Symbol();
const s4 = Symbol();

console.log(s3 === s4);  // false

 

심볼을 Object의 프로퍼티 key로 사용

심볼은 유일성을 보장하므로 Object의 프로퍼티 키로 사용하기 적합하다.

키끼리 충돌이 발생할 가능성이 없기 때문에 의도치 않게 값이 덮어지거나 수정되는 일도 발생하지 않기 때문이다.

 

심볼을 프로퍼티 키로 사용하면 얻을 수 있는 또 다른 장점으로는 프로퍼티 은닉이 가능하다는 점이다.

 

심볼 값을 키로 갖는 프로퍼티는 for .. in 문이나 Object.keys(), Object.entries(), Object.getOwnPropertyNames() 메소드를 사용해도 접근할 수 없다.

 

하지만 Object.getOwnPropertySymbols() 메소드를 사용하면 심볼 값을 사용한 프로퍼티 키 목록을 얻을 수 있다.

const password = Symbol('pwd');
const user = {
  id: 'sap03110',
  [password]: '******',
  name: 'mjkim',
}
console.log(Object.keys(user));  // id, name
console.log(Object.getOwnPropertySymbols(user));  // Symbol(pwd)

 

그리고 여기서 예외!

 

Object.assign()을 사용하는 경우에는 심볼 키 값을 갖는 프로퍼티를 배제하지 않는다.

객체를 복사하거나 병합하는 경우에는 보통 심볼을 포함한 프로퍼티 전부를 사용하고 싶어할 것이기 때문에 의도해서 설계되었다고 한다.

const id = Symbol("id");
const user = {
  [id]: 123
};

const clone = Object.assign({}, user);
console.log(clone); // { Symbol(id): 123 }

 

심볼을 이용한 Enum 생성

자바스크립트에서는 enum을 지원하지 않기 때문에 Object.freeze()와 Symbol을 사용하여 enum을 흉내내어 사용할 수 있다.

const day = Object.freeze({
	SUNDAY: Symbol('sunday'),
    MONDAY: Symbol('monday'),
    TUESDAY: Symbol('thusday'),
    WEDNESDAY: Symbol('wednesday'),
    THURSDAY: Symbol('thursday'),
    FRIDAY: Symbol('friday'),
    SATURDAY: Symbol('saturday'),
});

const TODAY = day.THURSDAY;
console.log(TODAY);

 

물론 Symbol() 대신 일반 문자열을 사용하는 것도 가능하지만, 심볼을 사용하여 키의 중복 가능성을 제거하고 의미를 부여하는 것이 좋은 코드를 작성하는 방법이다.

 

심볼의 메서드

Symbol은 Symbol.for(), Symbol.keyFor()이라는 메서드를 제공한다.

 

Symbol.for() 메소드는 인자로 전달받은 문자열을 키로 사용하여 키와 심볼 값의 쌍들이 저장되어 있는 전역 심볼 레지스트리에서 해당 키와 일치하는 심볼 값을 검색할 수 있다.

 

전역 심볼 레지스트리란?

생성된 심볼 값을 관리하는 저장소
Symbol.for() 메소드로 생성된 심볼 값만 관리됨

 

검색에 성공하면 해당 심볼 값을 반환하고 검색에 실패하면(존재하지 않는 경우) 새로운 심볼 값을 생성하여 생성된 심볼 값을 반환한다.

const obj = {
  [Symbol.for('newKey')]: 123,
}

 

여기서 주의할 점은, 그냥 Symbol() 함수를 호출하여 심볼 값을 생성한 경우에는 전역 심볼 레지스트리에 저장되지 않는다.

따라서 Symbol.for() 메소드로 검색도 불가능하다.

 

Symbol.keyFor() 메소드는 Symbol 값을 인자로 전달받아 해당 Symbol의 키를 추출하여 반환한다.

const s = Symbol.for('hihi');
const s2 = Symbol('hihi2');

console.log(Symbol.keyFor(s));  // hihi
console.log(Symbol.keyFor(s2));  // undefined