배경
프로젝트에 Sequelize 객체를 JSON stringify 하여 캐시 키로 사용하는 부분이 있는데, 심볼이 무시되는 바람에 모두 같은 값으로 캐싱되는 이슈가 있었다. 왜 심볼은 stringify 에서 무시되는지, 그리고 Sequelize는 왜 심볼을 사용하는지를 정리해보았다.
왜 심볼은 stringify 에서 무시되는가
ECMAScript 명세에 따라 Symbol을 직렬화하지 않도록 명시되어있음.
- JSON 자체가 Text 기반 포맷 → Symbol은 런타임 고유 식별자라 문자열로 안전하게 표현할 방법이 없음.
- 상호 운용성 문제 → JSON은 다양한 언어에서 읽어야 하는데 대부분의 언어에는 Symbol 개념이 없음.
- 보안적/추상적 의미 → Symbol은 객체의 "숨겨진" 속성을 위해 설계됨. JSON 직렬화는 보통 데이터 교환 용도라 굳이 숨겨진 속성을 포함하지 않음.
왜 Sequelize는 심볼을 사용하는가
Sequelize는 동적 언어(자바스크립트)의 특성과 Active Record 철학을 살리기 위해 런타임 파싱 방식을 선택했다.
prisma 와 달리 sequelize.js 는 dataValues, _options, _previousDataValues 와 같은 런타임 상태를 객체에 직접 포함한다.
즉 런타임 파싱 시점에 사용자 정의 키와의 충돌을 막을 수 있고, 객체 중 내부 정보를 은닉하기 위함일 것이다.
JS 개발자는 어떻게 대응할 수 있는가
- replacer 함수 활용 - JSON.stringify의 두 번째 인자인 replacer를 사용해서 Symbol을 커스텀 직렬화할 수 있음
const obj = {
[Symbol('id')]: 123,
name: 'Alice',
role: Symbol('admin'),
};
const json = JSON.stringify(obj, (key, value) => {
if (typeof value === 'symbol') {
return value.toString(); // 또는 Symbol.keyFor(value) 등 활용
}
return value;
});
console.log(json);
// {"name":"Alice","role":"Symbol(admin)"}
2. flatted, circular-json, json-stringify-safe 등 심볼 직렬화까지 확장하거나 커스텀 핸들링하는 라이브러리 활용
'배운 것들 > 언어' 카테고리의 다른 글
| JVM Anatomy 세션 정리, 해석 (8) | 2024.12.27 |
|---|---|
| 자바스크립트 변수의 유효범위와 클로저 (모던자바스크립트 요약, 과제 풀이) (5) | 2024.12.08 |