티스토리 뷰

Javascript

[JavaScript] 심볼 (Symbol)

이근둥 2018. 10. 11. 18:04

안녕하세요


이번 포스팅에서는 ES6 (ECMAScript 2015)에 추가된 심볼(Symbol) 자료형에 대해 간단히 알아보도록 하겠습니다.






심볼은 자바스크립트의 원시(Primitive)타입으로 새롭게 추가되었습니다.

원시타입은 객체도 아니고 메서드도 아닌 타입을 의미합니다.


기존에는

string, number, boolean, null, undefined가 있었지만

여기에 오늘 알아볼 symbol 타입이 추가되었습니다.



심볼 생성 방법은 심볼 Wrapper 함수를 호출하면 됩니다.


const sym = Symbol()



심볼을 생성할 때 구분하기 위한 데이터를 추가하여 생성할 수도 있습니다.


Symbol(value)



심볼타입은 신기하게도 같은 value를 인자로 주고 생성하더라도 값은 같지 않습니다.

Symbol() 로부터 반환되는 값은 항상 고유합니다.



const s1 = Symbol()
const s2 = Symbol()
const aSymbol_1 = Symbol('a')
const aSymbol_2 = Symbol('a')

console.log(s1 === s2) // false
console.log(aSymbol_1 === aSymbol_2) // false


위 예제를 실행시켜보면 출력결과 모두 false로 나옵니다.


심볼은 고유하기 때문입니다.



같은 심볼을 사용하고싶을 땐 


const s1 = Symbol()
const s2 = s1


또는 


const s1 = Symbol.for('mySym')
const s2 = Symbol.for('mySym')

console.log(s1 === s2)


Symbol.for()로 생성하면 동일한 심볼을 사용할 수 있습니다.





심볼은 원시타입이라고 했는데 기존의 다른 원시타입과는 조금 다른부분이 있습니다.

바로 new 연산자를 통해 Wrapper 객체를 생성할 수 없다는 점 입니다.


const str = new String('Hello')
const num = new Number(12)
const sym = new Symbol() // TypeError!


number, string, boolean 등 기존의 원시타입은 new 연산자를 사용하여 생성할 수 있었지만 Symbol은 불가능합니다.




조금 특이하기도 하고 어디에 사용해야할지 감이 안잡히실겁니다.


본론부터 말하자면, 심볼 타입은 주로 객체의 고유한 프로퍼티의 값으로 사용하는 목적으로 쓰입니다.




아래와 같이 객체의 프로퍼티에 접근하는 용도로 사용이 가능합니다.


const a = Symbol()

const obj = {
a: 'a 입니다',
[a]: '조금 다른 a 입니다'
}

obj.a
obj[a]










이번에는 간단한 예제와 상황으로 주로 어떨 때 사용해야하는지 소개해드리도록 하겠습니다.


Number.isNumber = arg => {
return typeof arg === 'number' ? '숫자!' : '숫자 아님!'
}

const num = 10
console.log(Number.isNumber(num)) // 숫자!


우리는 숫자 타입인지 확인하는 라이브러리를 위와 같이 만들었습니다.


isNumber라는 속성에 메소드를 구현해서 사용자에게 배포했습니다.

우리가 배포한 라이브러리가 많은 유저들이 사용하는 인기 라이브러리가 되어 다양한 사용자들이 늘고 있는 상황입니다.



그러던 중, ECMA 표준으로 isNumber가 추가된다고 합니다!

표준으로 추가될 isNumber는 '숫자!', '숫자 아님!' 값이 아닌 boolean 형태의 값(true, false)으로 반환된다고 합니다.



이미 우리의 라이브러리를 사용하던 사용자들은 아래와 같이 숫자인지 아닌지 비교했을겁니다.

 

const num = 10
if (Number.isNumber(num) === '숫자!') {
// num 이 숫자일 때 실행할 로직..
}


하지만 표준으로 채택된 이후에는 위의 코드는 모두 사용할 수 없게 됩니다.


true와 false로 반환되기 때문에 사용자들은 isNumber을 사용하여 숫자를 비교하는 코드를

모두 표준에 맞춰 다시 작성해야하는 불상사가 일어나게 되죠




표준으로 채택되도 Number.isNumber에 우리 라이브러리의 구현 부분을 다시 덮어쓰면 되긴 하지만

자바스크립트에는 덮어쓸 수 없는 상수 프로퍼티가 몇몇 존재합니다.


만약 isNumber가 표준으로 적용되었는데 isNumber의 writeable이 false인 경우

(덮어쓸 수 없는 경우)


기존의 사용자들이 코드를 모두 변경해야하는 방법밖에 없습니다.






이러한 문제를를 방지하기 위해 프로퍼티를 고유하게 구분할 수 있는 심볼이 탄생했습니다.



만약 우리가 숫자인지 아닌지 구분하는 라이브러리를 개발하기 전에 심볼이 있덨다면

아래와 같이 구현하여 미래의 불상사를 방지할 수 있습니다.


const isNumber = Symbol()

Number[isNumber] = arg => {
return typeof arg === 'number' ? '숫자!' : '숫자 아님!'
}

const num = 10
if (Number[isNumber](num) === '숫자!') {
// num 이 숫자일 때 실행할 로직..
}


이와같이 심볼을 객체의 프로퍼티로 지정하면 고유한 값으로 프로퍼티가 지정되어있기 때문에

나중에 isNumber가 표준으로 채택된다고 해도 사용자들은 그대로 Symbol을 통해 프로퍼티에 접근하기 때문에 문제가 없습니다.




심볼 타입을 통해 고유한 프로퍼티를 정의하고 접근할 수 있게 되었습니다.

심지어 같은 심볼을 통해 접근하지 않는 이상 덮어쓰기도 불가능하게 되었죠!



심볼을 사용하는 상황은 위와같은 상황 말고도 더 있을 수 있겠지만 주로 고유한 프로퍼티를 위해 사용합니다.







다음 포스팅에서는 이터레이터와 제너레이터에 대해 알아보도록 하겠습니다.


감사합니다.

댓글
댓글쓰기 폼