JS Symbol - TIL(11.27)

권혁진·2022년 11월 27일
0
post-thumbnail
post-custom-banner

Symbol

  1. JavaScript의 primitive 타입들 중 다른 것들은 알겠는데 Symbol은 뭘까?
  2. JavaScript 객체의 키값으로는 string과 Symbol만 가능하다는데,
    Symbol이 뭐길래?

오늘은 Symbol에 대해 알아보자.

무슨 뜻일까?

Symbol 단어 자체가 낯설 수 있다. 나 역시 그랬음.

Symbol은 Computer Programming적으로 다음과 같은 의미를 갖는다.

Symbol이란, 그 인스턴스가 사람이 읽을 수 있는 형태의 고유한 식별자를 갖는 원시 데이터 타입이다.

뭔가 식별자의 역할을 해주겠거니로 이해하고 넘어가보자.
다른 언어들에서는 atom 이라는 이름으로 불리기도한다.

어떻게 생성하나요?

우선 심볼을 생성해보자.

심볼은 class-like한 형태로 제공되지만 new 연산자로 인스턴스를 생성할 수 없다. 전역적인 심볼 영역에 영향을 끼칠 수 있기 때문에 제한된 것인데, 이게 무슨 의미인지는 차근차근 이해해보자.

const badSymbol = new Symbol('TestSymbol') // Error
const goodSymbol = Symbol('TestSymbol');

goodSymbol을 생성한 방법처럼 심볼을 생성할 수 있다.
이렇게 생성된 심볼의 프로토타입을 한 번 확인해보자.

Object.getPrototypeOf(goodSymbol);

뭔가 Symbol 과 관련된 건 for keyFor 이 두개의 메서드 정도밖에 보이지 않는다.

forkeyFor 메서드가 위에서 언급한 전역심볼영역과 연관되어 있다. 차차 알아보고 우선은 이 심볼을 사용해 무언갈 해보자.

식별자로서의 심볼

MDN에서도 나와있듯이 심볼은 식별자로 이용이 가능한 원시 데이터 타입. 그게 전부이다.

그럼 이 식별자로서 심볼을 사용하는 것이 무슨 이득을 주는걸까?

const obj = {};
const sym = Symbol('age');

obj[sym] = 50;

obj.age // undefined
obj[sym] // 50

위처럼 age라는 심볼을 생성한 뒤 obj의 키 값으로 설정했다.

이렇게 보면 아니 이거 왜 써요 도대체?? 이런 생각이 들지도 모름.

심볼인 키값과 그렇지 않은 키값은 무슨 차이가 있을까?

심볼은 유니크하다.

const obj = {};
const sym = Symbol('age');
const otherSym = Symbol('age')

sym === otherSym // false

같은 토큰('age')으로 생성한 심볼이더라도 서로 다르다.
이 유니크하다는 특성이 어떤 장점을 가져올 수 있을까?

아래와 같이 someModule이라는 외부에서 가져온 코드가 있을 때, 사용하는 우리 입장에서는 이 객체의 내부가 어떻게 생겼는 지 모른다고 가정해보자.

그런데 우리의 요구사항 중에 이 객체를 식별해야하는 상황이 필요해서 임의로 id 프로퍼티를 추가한다면 ?

const someModule = { id: 2, name: 'John Doe' };
// ----------- using this module -----------
someModule.id = 'myid'

외부 코드의 기존 동작에 영향을 줄 수도 있게 된다.

이제, 심볼을 통해서 정의해보도록 하자.

const someModule = { id: 2, name: 'John Doe' };
// ----------- using this module -----------
const id = Symbol('id');
someModule[id] = 'myid';

이렇게 심볼을 정의할 경우 외부 코드의 기존 동작에 영향을 주지 않으면서 몰래(?) 프로퍼티를 추가할 수 있다.

심볼은 나름 숨겨져 있다.

const sym = Symbol('test');
const obj = {
  [sym]: 1234,
  name: 'John Doe',
  status: 'hungry',
};

Object.keys(obj) // ['name', 'status']
for (const el in obj) { console.log(el) } // ['name', 'status']

위처럼 객체를 순회할 때 심볼은 나타나지 않는다.

만약 sym 변수를 모른다면 obj의 [sym] 안에 저장되어있는 1234라는 값은 조회할 수 없다. (지금까지의 지식만으로는)

전역 심볼

지금까지의 내용으로 미루어보았을 때 심볼은 다음과 같다.

  1. 유니크한 식별자이다.
  2. 숨겨져 있다.
  3. 같은 토큰으로 생성된 심볼이라도 서로 다르다.

그래서 그런지 여러 곳에서 접근이 가능한 심볼 값을 만들기란 다소 어려워보인다.

이 때, 같은 토큰 값으로 만든 심볼이 서로 같은 값을 가질 수 있도록 하는 방법이 존재한다.

전역심볼영역을 사용하는 것이다.

for, keyFor

위에서 Symbol의 프로토타입을 살펴보면서 생성자 안에 for, keyFor 메서드가 있는 것을 확인했다.

각 메서드의 역할을 간단히 설명하자면 다음과 같다.

  • Symbol.for(token): 전역심볼영역에서 token에 해당하는 심볼을 반환한다,
  • Symbol.keyFor(sym): 전역심볼영역에서 sym이 갖고 있던 토큰을 반환한다.
Symbol.keyFor(Symbol.for('test')) === 'test'

위의 메서드를 사용하여 전역심볼영역에 접근하게 된다면 같은 토큰 값으로 만든 심볼이 서로 같은 값을 가질 수 있게 된다.

const sym = Symbol.for('id');

object[sym] = 1234;

// --------- other space --------- 
const mySym = Symbol.for('id');
object[mySym] === 1234 // true

well-known 심볼

Well-known symbols are built-in Symbol values that are explicitly referenced by algorithms of this specification. They are typically used as the keys of properties whose values serve as extension points of a specification algorithm. Unless otherwise specified, well-known symbols values are shared by all realms (9.3). - ECMAScript

오늘 알아본 심볼들은 자바스크립트의 내장 기능들을 구현하는 곳에서 사용되고 있다. 이 중에 잘 알려진 심볼들을 well-known symbol이라고 한다.
well-known symbol의 리스트는 ECMAScript 명세에서 찾아볼 수 있다.

👉 링크: https://tc39.es/ecma262/#sec-well-known-symbols


레퍼런스

profile
TIL을 마구잡이로 올리는 용도로 사용 중입니다.
post-custom-banner

0개의 댓글