C.W.K.
Stream
Lesson 04 of 05 · published

`symbol` 과 `bigint`: 덜 쓰이는 primitive

~9 min · primitives, symbol, bigint, javascript-evolution

Level 0Curious
0 XP0/93 lessons0/23 achievements
0/100 XP to next level100 XP to go0% complete
"대부분 TypeScript 프로그래머가 손으로 절대 타이핑 안 할 primitive 2개 — 근데 나타나면 둘 다 알아봐야 해."

symbol — 고유 보장 식별자

symbol 은 고유 보장된 primitive 값. 같은 설명으로 Symbol() 두 번 호출하면 다른 symbol 두 개 만들어. 다른 사람 key 와 충돌 없이 object 에 데이터 붙여야 할 때 object property key 로 가장 흔히 써.

built-in well-known symbol 통해 가장 자주 만나 — Symbol.iterator, Symbol.asyncIterator, Symbol.toPrimitive, 등등. 이게 JavaScript 의 iteration protocol, primitive coercion, 다른 meta-behavior 가 너의 object 에 hook 하는 법. for (const x of obj) 써본 적 있으면, 그 loop 가 내부에서 obj[Symbol.iterator]() 호출.

자기 symbol 선언 (const TAG = Symbol('Tag')), private 같은 property key 로 사용, 심지어 unique symbol 타입으로 타이핑 가능. 근데 일상 TypeScript 가 직접 거의 안 만져 — 소비하는 library API 의 type annotation 에 가장 자주 나타나.

bigint — 임의 정밀도 integer

JavaScript 의 number 는 64-bit double, 즉 ±2^53 넘는 integer 산술이 정밀도 잃어. bigint 가 해결: 어떤 크기 산술이든 다루는 임의 정밀도 integer 타입, trade-off 는 명시적 변환 없이 number 와 못 섞어.

Bigint literal 은 n suffix 로 써: const big = 9007199254740993n. 또는 BigInt(value) 호출. 두 bigint 사이 산술 연산자 정상 작동 (big * 2n), 근데 타입 섞기 throw: big + 1 이 runtime 에 TypeError. 옳게 annotate 했으면 TypeScript 가 compile 시점에 잡아.

Bigint 쓸 때: 나노초 timestamp, Number.MAX_SAFE_INTEGER 초과하는 ID (64-bit 식별자 쓰는 시스템의 DB row ID), 암호학, float 에러 피해야 하는 금융 계산.

두 primitive 다 이유 있어 존재하지만, 어느 것도 daily-driver 타입 아냐. 2026 의 대부분 TypeScript 코드가 일상 값엔 string, number, boolean 써. symbolbigint 는 특화 tool — 알아봐, 자기 문제 나타날 때 써, 그 외엔 toolbox 에 둬.

Wrapper object 존재 (그리고 여전히 피해야 함)

Big three 와 같은 소문자-vs-대문자 규칙: : symbol 이 primitive, : Symbol 은 wrapper-object constructor 타입. : bigint primitive, : BigInt wrapper. 항상 소문자.

피파의 고백

cwkPippa frontend 는 둘 다 안 써. Symbol 은 간접적으로 만지는 React internal 에 나타나고, bigint 는 JavaScript number 를 overflow 하는 크기의 DB row ID 다루면 나타나 — cwkPippa SQLite layer 가 그까지 안 가. 진짜고 유용한 primitive 야; 그냥 좁은 tool 일 뿐. 존재 안다는 게 항상 쓴다는 것보다 중요해.

Code

symbol — 고유 key, iterator protocol hook·typescript
// symbol — 고유 보장.

const a = Symbol('id');
const b = Symbol('id');
console.log(a === b);             // false — 같은 설명에도

// Object 의 property key 로 사용.
const MY_KEY = Symbol('myKey');
const obj = {
  [MY_KEY]: 'private-ish value',
  publicProp: 'visible',
};

console.log(obj[MY_KEY]);         // 'private-ish value'
console.log(Object.keys(obj));    // ['publicProp'] — symbol key 는 스킵

// well-known symbol 이 object 를 iterable 하게 만들어.
class Range {
  constructor(public start: number, public end: number) {}
  *[Symbol.iterator]() {
    for (let i = this.start; i <= this.end; i++) yield i;
  }
}

for (const n of new Range(1, 3)) console.log(n);  // 1, 2, 3
bigint — number 의 정밀도 떨어질 때·typescript
// bigint — 임의 정밀도 integer.

const small: bigint = 9007199254740992n;        // n suffix 가 bigint 표시
const big: bigint = small * 2n;                  // 18014398509481984n — 정확

// number 는 이거 정확히 표현 못 함:
const asNumber: number = 9007199254740993;       // 9007199254740992 로 round

// 섞으면 실패 — runtime 도, (annotate 됐으면) compile 시점도.
// const broken = big + 1;                       // ❌ Type 'bigint' not assignable to '1n' (BigInt + number 는 runtime TypeError 이기도)
const fixed = big + 1n;                          // ✅ 둘 다 bigint
const converted = Number(big);                   // ✅ 명시적 cast, 정밀도 잃을 수 있음

// 손 뻗을 때:
//  - 2^53 초과 DB ID
//  - 나노초 timestamp (Node 의 process.hrtime.bigint())
//  - 화폐를 가장 작은 단위로, float 산술 허용 안 될 때

External links

Exercise

Iterator 있는 class 써: constructor 에 배열 받고 각 element 를 reverse 로 yield. [Symbol.iterator] 와 generator method 써. 그다음 instance 에 for...of loop 돌리고 작동 확인. 보너스: [...instance] 시도 — 뭐 받아?
Hint
Generator (function* / yield 형태) 가 iterator 쓰는 가장 쉬운 방법. Class method 는 *[Symbol.iterator](). Spread operator 와 for-of loop 둘 다 같은 방식으로 symbol-keyed iterator 소비.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고
💛 by 똘이warm

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.