[JS] 심볼(Symbol)

javaScript 기초를 탄탄하게 다져보자

Posted by lim.Chuck on December 20, 2024

[JavaScript]

기초

  1. [JS] Js기초
  2. [JS] Js기초 변수
  3. [JS] Js기초 자료형
  4. [JS] Js기초 형변환
  5. [JS] Js기초 연산자
  6. [JS] Js기초 반복문
  7. [JS] Js기초 switch
  8. [JS] Js기초 function
  9. [JS] Js기초 객체
  10. [JS] Js기초 배열

중급

  1. [JS] Js중급 호이스팅(Hoisting)과 TDZ(Temporal Dead Zone)
  2. [JS] Js중급 생성자함수
  3. [JS] 객체 메소드(Object methods), 계산된 프로퍼티(Computed property)
  4. [JS] 심볼(Symbol)
  5. [JS] WeakMap WeakSet
  6. [JS] 숫자, 수학 method (Number, Math)
  7. [JS] 문자열 메소드(String methods)
  8. [JS] 배열 메소드(Array methods)
  9. [JS] 구조 분해 할당 (Destructuring assignment)
  10. [JS] 매개변수 리스트와 전개 문법(Rest parameters and spread syntax)
  11. [JS] 클로저(Closure)
  12. [JS] setTimeout / setInterval
  13. [JS] call / apply / bind
  14. [JS] 상속, 프로토타입(Prototype)
  15. [JS] 클래스(Class)
  16. [JS] 클로미스(Promise)
  17. [JS] 비동기 처리(Async/Await)
  18. [JS] Generator
  19. [JS] 메모리 릭(Memory Leak)

심볼(Symbol)은 유일한 식별자를 만들 때 사용하는 특별한 타입이야! 🎯

1. 심볼 기본

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 심볼 만들기
const mySymbol = Symbol();
const mySymbol2 = Symbol("설명"); // 설명을 추가할 수 있음

// 각 심볼은 유일함!
const sym1 = Symbol("test");
const sym2 = Symbol("test");
console.log(sym1 === sym2); // false

// 객체의 프로퍼티 키로 사용
const obj = {
  [sym1]: "값1",
  [sym2]: "값2",
};

console.log(obj[sym1]); // "값1"
console.log(obj[sym2]); // "값2"

2. Symbol.for() - 전역 심볼

1
2
3
4
5
6
7
8
9
10
11
12
// 전역 심볼 레지스트리에서 심볼 생성/검색
const globalSym1 = Symbol.for("myKey");
const globalSym2 = Symbol.for("myKey");

console.log(globalSym1 === globalSym2); // true

// 심볼의 키 가져오기
console.log(Symbol.keyFor(globalSym1)); // "myKey"

// 일반 심볼은 키를 가져올 수 없음
const localSym = Symbol("myKey");
console.log(Symbol.keyFor(localSym)); // undefined

3. 숨겨진 프로퍼티로 사용

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
const LEVEL = Symbol("level");
const HP = Symbol("hp");

class Game {
  constructor() {
    this[LEVEL] = 1; // 심볼을 프로퍼티 키로 사용
    this[HP] = 100;
  }

  powerUp() {
    this[LEVEL]++;
    this[HP] += 50;
    console.log(`파워업! 레벨: ${this[LEVEL]}, HP: ${this[HP]}`);
  }
}

const game = new Game();
game.powerUp(); // "파워업! 레벨: 2, HP: 150"

// 심볼 프로퍼티는 일반적인 방법으로는 보이지 않음
console.log(Object.keys(game)); // []
console.log(Object.getOwnPropertyNames(game)); // []

// 심볼 프로퍼티 보기
console.log(Object.getOwnPropertySymbols(game)); // [Symbol(level), Symbol(hp)]

4. 내장 심볼 (Well-known Symbols)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
class Collection {
  constructor() {
    this.items = [];
  }

  // Symbol.iterator를 구현하여 반복 가능하게 만듦
  [Symbol.iterator]() {
    let index = 0;
    return {
      next: () => {
        if (index < this.items.length) {
          return { value: this.items[index++], done: false };
        }
        return { done: true };
      },
    };
  }

  // Symbol.toPrimitive로 형변환 동작 정의
  [Symbol.toPrimitive](hint) {
    if (hint === "number") {
      return this.items.length;
    }
    return this.items.join(", ");
  }
}

const collection = new Collection();
collection.items = ["🍎", "🍌", "🍊"];

// iterator 사용
for (let item of collection) {
  console.log(item); // 🍎, 🍌, 🍊
}

// toPrimitive 사용
console.log(+collection); // 3
console.log(`${collection}`); // "🍎, 🍌, 🍊"

5. 실전 예제: 프라이빗 프로퍼티 구현

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
const privateProps = new WeakMap();

class Player {
  constructor(name) {
    // 프라이빗 데이터 저장
    privateProps.set(this, {
      name: name,
      hp: 100,
      mp: 50,
    });
  }

  get status() {
    const props = privateProps.get(this);
    return `
            이름: ${props.name}
            HP: ${"❤️".repeat(props.hp / 20)}
            MP: ${"💙".repeat(props.mp / 10)}
        `;
  }

  useSkill(skillName) {
    const props = privateProps.get(this);
    const mpCost = {
      파이어볼: 30,
      힐링: 20,
    };

    if (props.mp >= mpCost[skillName]) {
      props.mp -= mpCost[skillName];
      console.log(`${skillName} 사용! (MP: ${props.mp})`);
      return true;
    }
    return false;
  }
}

const player = new Player("마법사");
console.log(player.status);
player.useSkill("파이어볼");

꿀팁! 🍯

  1. 심볼 사용 시기
1
2
3
4
5
6
7
8
9
10
11
12
13
// 1. 유니크한 프로퍼티 키가 필요할 때
const uniqueKey = Symbol("설명");

// 2. 프라이빗 데이터를 만들 때
const _private = Symbol("private");
obj[_private] = "비밀 데이터";

// 3. 내장 동작을 커스터마이징할 때
class MyArray {
  [Symbol.iterator]() {
    // 커스텀 반복 동작
  }
}

이제 심볼은 마스터! 😎 유니크한 값이 필요하거나 프라이빗한 데이터를 다룰 때 유용하게 사용할 수 있어!