문제의 역사:
심볼 타입은 JavaScript(ES6)에서 고유 식별자를 생성하기 위해 추가되었으며, 이는 객체의 다른 속성과 중복되지 않도록 보장합니다. 타입스크립트는 ES6 호환성을 지원하면서 심볼을 지원합니다.
문제:
심볼이 등장하기 전에는 객체 속성의 키로 문자열이 자주 사용되었습니다. 이는 객체의 확장 또는 재사용 시 우발적인 이름 충돌과 비공식 속성을 숨기는 것을 불가능하게 하여 오류를 유발했습니다. 심볼은 외부 코드에서 보이지 않는 고유한 키를 생성할 수 있도록 했지만, 타입화를 검토해야 하는 문제가 발생했습니다. 심볼 키를 가진 타입을 어떻게 설명하고 안전하게 API에서 사용할까요?
해결책:
타입스크립트는 값을 심볼로 지원하지만, 심볼 키의 타입화에는 몇 가지 특징이 있습니다. 심볼을 생성하기 위해서는 전역 생성자 또는 전역 심볼 레지스트리를 사용할 수 있습니다. 인터페이스나 타입에서 심볼 키는 명시적으로 심볼로 타입을 지정해야 하며, 이러한 속성에 접근하기 위해서는 심볼에 대한 참조를 유지해야 합니다.
코드 예:
const SECRET = Symbol('secret'); interface SecretObject { [SECRET]: string; visible: string; } const obj: SecretObject = { visible: 'see me', [SECRET]: 'hidden', }; console.log(obj.visible); // 'see me' // console.log(obj["secret"]); // 오류: 해당 속성이 없습니다! console.log(obj[SECRET]); // 'hidden'
주요 특징:
심볼은 객체에서 사용될 때 문자열로 자동 변환될 수 있나요?
아니요, 심볼은 문자열로 자동 변환될 수 없으며, 이를 수행하려고 하면(TypeError) 오류가 발생합니다.
const mySymbol = Symbol('desc'); // alert('prefix_' + mySymbol); // TypeError
Object.keys로 심볼 키를 나열할 수 있나요?
아니요, Object.keys와 for...in은 심볼 키를 무시합니다. 그러한 키를 얻으려면 Object.getOwnPropertySymbols를 사용해야 합니다.
const sym = Symbol('a'); const obj = { [sym]: 42 }; Object.keys(obj); // [] Object.getOwnPropertySymbols(obj); // [Symbol(a)]
Object.assign으로 복사할 때 심볼 키의 속성이 전달되나요?
네, Object.assign는 문자열 키와 심볼 키를 모두 복사하지만, JSON.stringify는 그렇지 않습니다.
const s = Symbol('s'); const o1 = { [s]: 123, foo: 'bar' }; const o2 = Object.assign({}, o1); o2[s]; // 123
개발자가 비공식 속성에 문자열 키('_private')를 사용하여 컨벤션에 의존했습니다. 팀 B에서 우연히 동일한 문자열을 추가하게 되었고, 속성이 덮어쓰여져 예측할 수 없는 오류가 발생했습니다.
장점:
단점:
두 번째 개발자는 숨겨진 속성을 위해 심볼을 적용했습니다(예: Symbol('internal')). 이제 팀 내부에서도 내부 데이터를 우연히 덮어쓰기 불가능하며, 특정 심볼에 대한 참조가 있어야만 접근 가능합니다.
장점:
단점: