ES6알아보기 12 - Symbol

ES6알아보기 12 - Symbol

2018, Dec 19    

Symbol 이란?

Symbol 이란 ES6 에서 추가된 Primative Data Type(원시 자료형) 입니다.
이미 Ruby 나 Objective-c 같은 언어들에서 차용되고 있는 걔념이기에 익숙하신 분들도 많겠지만, Javascript 개발자에게는 기존의 문법과 연관성이 없어보이는 사용법? 과 새로운 원시타입이라는 점 때문에 생소하게 느껴질 수도 있을 것 같습니다.

자료형을 확인해 보겠습니다.

// 원시타입
typeof 10         // 'number'
typeof 'hello'    // 'string'
typeof true       // 'boolean'
typeof undefined  // 'undefined'
typeof Symbol()   // 'symbol' ES6에서 새로 추가

// 객체타입
typeof {}         // 'object'
typeof function () {} // 'function'


Symbol 타입의 기본 사용법

위에서도 확인했지만 Symbol 타입은 Symbol() 함수를 실행해서 생성할 수 있습니다.
Symbol 은 이름에서도 유추해 볼 수 있듯이 각각의 Symbol 객체는 모두 유니크한 값을 가지고 있습니다.

assert.notEqual(Symbol(), Symbol())
assert.notEqual(Symbol('foo'), Symbol('foo'))

이런 특수성 때문에 가장 흔히 Symbol 을 사용하는 경우는 객체의 프로퍼티를 지정해 줄 때 입니다.

var obj = {}
obj['foo'] = 10
obj[Symbol('foo')] = 20
obj[Symbol('foo')] = 30

console.log(obj)
// { foo: 10, [Symbol(foo)]: 20, [Symbol(foo)]: 30 }

보통의 경우 객체에 동일한 키값을 가진 프로퍼티를 나중에 정의한 프로퍼티가 덮어쓰기 되지만, Symbol의 경우는 얼마든지 동일한 프로퍼티? 를 선언할 수 있습니다.

반대로 정의한 프로퍼티를 읽기 위해서는 어떻게 해야 할까요?

var obj = {}

// 잘못된 예
obj[Symbol('foo')] = 10
console.log(obj[Symbol('foo')]) // undefined

// 정의한 변수를 대입해서 불러오기
var bar = Symbol('bar')
obj[bar] = 20
console.log(obj[bar]) // 20

// Object.getOwnPropertySymbols() 를 사용해 불러오기
var [foo, bar] = Object.getOwnPropertySymbols(obj)
console.log(obj[foo]) // 10
console.log(obj[bar]) // 20


Global Symbol 사용하기

다음으로 알아볼 기본적인 사용법은 전역객체로써의 Symbol 사용법입니다.
전역으로써의 Symbol을 정의하고 불러오는 방법은 아래와 같습니다.

// 전역심볼 정의하기
var global1 = Symbol.for('foo')

// 정의한 심볼을 Global Symbol Registry 에서 불러오기
var global2 = Symbol.for('foo')
// global1 and global2 is equal
assert.equal(global1, global2)

Symbol() 로 함수를 실행했을 경우에는 매번 새로운 Symbol 을 반환한다는 것을 앞에서 알아보았습니다.
하지만 Global Symbol 은 이와는 달리 Symbol.for([키값]) 을 통해서 같은 키값은 가진 글로벌 심볼이 있는지 먼지 Global Symbol Registry 를 검색하고, 없을 경우 새로운 글로벌 심볼을 생성하여 반환합니다.

여기서 Global Symbol Registry 는 브라우저의 글로벌 객체인 window 나 node.js 의 global 객체안에 소속되었다고 생각하실 수도 있지만, 이 GSR 은 좀더 상위인 JS engine 자체에서 관리가 되고 있기 때문에 ~더 글로벌한~ 곳에서 관리되고 있다고 생각하면 될 것 같습니다.

한가지 더 추가로 global symbol 객체가 가지고 있는 키값은 아래와 같은 방법으로 찾을 수도 있습니다.

var global = Symbol.for('foo')
var key = Symbol.keyFor(global)
console.log(key) // 'foo'

이렇게 개발자가 직접 글로벌 심볼을 Global Symbol Registry 에 추가할 수 있지만, 이미 ES6 사양과 함께 이미 들어가 있는 글로벌 심볼들도 있는데 이걸 well-known Symbols 라고 부릅니다.

다음시간에는 이 well-knowm symbols 들을 살펴보면서, 더 똑똑하게 javascript 를 사용하는 방법을 알아보도록 하겠습니다.