문제의 역사: JavaScript에서 표준 오류는 Error 클래스를 통해 설명됩니다. 대규모 TypeScript 프로젝트에서는 상황을 정확하게 처리하기 위해 자체 오류 계층 구조를 사용하는 것이 중요하지만, 타입, 상속 및 'instanceof'의 동작과 관련하여 주의해야 할 사항이 있습니다.
문제: Error로부터 상속할 때 어려움이 발생할 수 있습니다. 프로토타입이 손실되고, 'instanceof'가 잘못 작동하며, 타입이 부정확하게 설명될 수 있고, 직렬화 시 stack trace가 손실되는 경우가 많습니다. 속성을 명시적으로 지정하지 않으면 오류 처리에서 버그가 발생할 수 있습니다.
해결책: Error 클래스를 확장하여 사용자 정의 오류를 올바르게 정의해야 합니다. 이름을 명시적으로 작성하고, 프로토타입을 수동으로 복원하며(ES5 및 CommonJS로 컴파일할 때 중요함), 오류 필드를 타입화해야 합니다.
코드 예:
class ValidationError extends Error { code: number; constructor(message: string, code: number = 400) { super(message); Object.setPrototypeOf(this, ValidationError.prototype); this.name = 'ValidationError'; this.code = code; } } function process(user: string) { if (!user) throw new ValidationError('User required', 401); }
주요 특징:
Object.setPrototypeOf(this, ...) 호출을 생략할 수 없는 이유는 무엇인가요?
Object.setPrototypeOf(this, Class.prototype)를 호출하지 않으면, ES5/CommonJS 또는 Babel로 컴파일할 경우 ValidationError에 대한 'instanceof'가 작동하지 않습니다. 이로 인해 ValidationError를 catch하는 블록이 오류를 포착하지 못하게 됩니다.
class CustomErr extends Error {} const err = new CustomErr('msg'); console.log(err instanceof CustomErr); // setPrototypeOf 없이는 false
사용자 정의 오류에서 name 필드를 생략 가능할까요?
this.name 속성을 설정하지 않으면 오류 스택 및 로그에 표시되는 내용이 부정확해져 원인 찾기가 어렵고 오류 분류가 힘들어집니다.
오류를 직렬화 가능하게 만들어야 하나요? 그렇다면 어떻게?
오류는 올바르게 직렬화되어야 합니다(예: 로깅 또는 네트워크 전송을 위해). 그렇지 않으면 JSON.stringify(new Error())가 message와 stack을 제공하지 않습니다. toJSON 메서드를 재정의해야 합니다.
class SerializableError extends Error { toJSON() { return { name: this.name, message: this.message, stack: this.stack }; } }
프로젝트에서 просто class MyError extends Error를 구현하고 프로토타입을 복원하지 않았습니다. 오류는 if (err instanceof MyError)로 포착했으나 작동하지 않아 코드가 조용히 치명적인 상황 처리를 건너뛰었습니다.
장점:
단점:
올바른 CustomError를 구현하고 name, code 및 toJSON을 명시적으로 설정했습니다. 다양한 오류 타입에 대한 처리를 테스트로 커버하여 로깅과 catch 핸들러에서 오류 구조가 명확해져 결함 탐색 시간이 감소했습니다.
장점:
단점: