FrontEnd/JavaScript

[JS] Symbol

728x90

[ 본글은 https://ko.javascript.info/symbol 글을 정리한 글입니다 ]

 

Symbol이란 자바스크립트에서 객체의 Key로 올수 있는 2가지 자료형 중 하나이다.

 

Symbol혹은 문자형만 올 수 있다.

 

 

 

지금까지 JS를 사용할 경우에는 항상 Key가 문자형인 경우만 대부분 사용했었다. 하지만 Symbol을 활용하면 문자형 말고도 객체형의 키를 사용할 수 있다.

 

Symbol은 아래와 같이 만든다.

// 심볼 id에는 "id"라는 설명이 붙습니다.
let id = Symbol("id");

 

 

 

Symbol의 가장 큰 특징은 유일성이 보장된다는 것이다. 문자형은 두형태가 같으면 중복되지만, Symbol로 만들면 설명이 같아도 다르게 취급한다.

let id1 = Symbol("id");
let id2 = Symbol("id");

alert(id1 == id2); // false

 

 

즉, Symbol은 문자형과는 다르게 이를 객체의 키로 사용하면 절대 객체가 겹칠 수가 없다.

 

 

따라서 명시적으로 형변환을 해주지 않는 이상 묵시적으로 문자형으로 절대 변환되지 않는다.

let id = Symbol("id");
alert(id); // TypeError: Cannot convert a Symbol value to a string

 

또한 변환이 되더라도 아래처럼 Symbol임이 표시된다.

let id = Symbol("id");
alert(id.toString()); // Symbol(id)가 얼럿 창에 출력됨

 

 

 

 

그럼 간략하게 Symbol을 활용해서 어떻게 객체의 키를 추가하는지 알아보자.

 

만약 user라는 객체를 서드파티 코드에서 가져왔다고 생각해보자.

 

 

서드파티 ??

제 3자 즉 플러그인, 라이브러리, 프레임워크  과 같이 개발자가 직접 작성한 코드가 아닌 외부에서 가져오는 코드들을 의미한다.

 

 

만약 이렇게 가져온 코드에 id란 key를 붙여주고 싶은 경우가 있을 것이다. 하지만 이러한 서드파티의 객체에는 함부로 key를 붙일 수 없다. 왜냐하면 id란 key를 이미 사용하고 있을 수 있기에 위험한 코드가 될 수도 있기 때문이다.

 

let user = { // 서드파티 코드에서 가져온 객체
  name: "John"
};

let id = Symbol("id");

user[id] = 1;

alert( user[id] ); // 심볼을 키로 사용해 데이터에 접근할 수 있습니다.

 

 

 

객체 리터럴 {...} 을 활용해서 객체를 만든 경우엔 아래와 같이 만들 수 있다.

let id = Symbol("id");

let user = {
  name: "John",
  [id]: 123 // "id": 123은 안됨
};

 

 

 

 

 

 

Symbol의 또다른 특징으로는 for...in 연산자를 활용해도 나오지 않는다.

 

et id = Symbol("id");
let user = {
  name: "John",
  age: 30,
  [id]: 123
};

for (let key in user) alert(key); // name과 age만 출력되고, 심볼은 출력되지 않습니다.

// 심볼로 직접 접근하면 잘 작동합니다.
alert( "직접 접근한 값: " + user[id] );

 

 

 

 

 

지금까지 쓴 것을 정리하자면 Symbol은 설명을 똑같이 주어도 모두 별개로 가리킨다. 그렇다면 같은 심볼을 지칭할 수 있는 방법은 아예 없을까??? 

 

그렇지는 않다. 전역 심볼 개념을 활용하면 이를 해결할 수 있다.

 

 

// 전역 레지스트리에서 심볼을 읽습니다.
let id = Symbol.for("id"); // 심볼이 존재하지 않으면 새로운 심볼을 만듭니다.

// 동일한 이름을 이용해 심볼을 다시 읽습니다(좀 더 멀리 떨어진 코드에서도 가능합니다).
let idAgain = Symbol.for("id");

// 두 심볼은 같습니다.
alert( id === idAgain ); // true

 

Symbol.for 메서드를 활용하면 해당 심볼을 찾아서 저장한다.

 

 

 

 

 

심볼 설명을 어느정도 읽었는데 이 심볼이란게 실무에서 실제로 적용되는지 궁금해서 유즈케이스를 조금 찾아보았다.

 

 

 

찾아보았더니 아래와 같은 경우에서 사용하긴 하는데, 굳이 실무에서 엄청 자주 사용되거나 하는 기술은 아직 아닌 것 같다.

1. 노티피케이션 기능 구현시
- 무언가를 삭제했을 때 노티피케이션(알림)을 띄워주는경우를 생각해봅시다.
- 빠르게 여러개를 삭제하는 경우, 새로운 알림창이 뜰 때 기존에 있던 알림창을 닫아줘야한다는 요구사항이 추가될겁니다.
- 이때 노티피케이션 하나하나를 식별할 수 있는 값을 만들어주는 과정이 필요한데, 이럴 때 Symbol을 사용할 수 있습니다.
- 대체할수있는 방법으론 uuid 관련 로직을 직접 구현하거나 패키지를 쓰는 방법이 있습니다.

2. api 상태 관련 변수 값 지정시
- api 상태를 다음과 같은 4가지 경우로 나눠서 관리한다고 가정해봅시다.
- IDLE, PENDING, SUCCESS, ERROR
- 이때 각 상태를 string으로 저장하게 되면 오타가 나는 등의 문제가 발생할 확률이 생깁니다.
- 이럴때 심볼을 활용할 수 있습니다.

export const apiStatus = {
IDLE: Symbol('IDLE'),
PENDING: Symbol('PENDING'),
SUCCESS: Symbol('SUCCESS'),
ERROR: Symbol('ERROR')
}

- 대체할 수 있는 방법으론 아래와 같이 하는 경우가 있습니다.

export const IDLE = 'IDLE'
export const PENDING = 'PENDING'
export const SUCCESS = 'SUCCESS'
export const ERROR = 'ERROR'

 

 

그래도 알고있으면 언젠간 써먹지 않을까 싶다.

728x90

'FrontEnd > JavaScript' 카테고리의 다른 글

[JS] fill 2차원배열 주의점  (0) 2023.06.25
[JS] 원시값의 메서드  (0) 2023.06.14
[JS] 옵셔널 체이닝 ?.  (1) 2023.06.08
가비지 컬렉션  (2) 2023.06.03
[JS] 폴리-필(Polyfill) , 바벨  (0) 2023.05.26