Error

Error

Error 객체는 런타임 오류가 발생할 때 던져집니다. 또한 사용자 정의 예외의 기본 객체로도 사용할 수 있습니다. JavaScript 표준 내장 오류 타입들의 기반이 됩니다.

출처: Error - JavaScript | MDN

본문

런타임 오류가 발생하면 새 Error 객체가 생성되어 던져집니다. Error는 직렬화 가능한 객체이므로 structuredClone()으로 복제하거나 postMessage()로 Worker 사이에서 복사할 수 있습니다.

오류 타입 (Error types)

일반적인 Error 생성자 외에도 JavaScript에는 다른 핵심 오류 생성자들이 있습니다.

  • EvalError — 전역 함수 eval()에 관한 오류를 나타내는 인스턴스를 만듭니다.
  • RangeError — 숫자 변수나 파라미터가 유효한 범위를 벗어날 때 발생하는 오류를 나타내는 인스턴스를 만듭니다.
  • ReferenceError — 잘못된 참조를 역참조할 때 발생하는 오류를 나타내는 인스턴스를 만듭니다.
  • SyntaxError — 문법 오류를 나타내는 인스턴스를 만듭니다.
  • TypeError — 변수나 파라미터가 유효한 타입이 아닐 때 발생하는 오류를 나타내는 인스턴스를 만듭니다.
  • URIErrorencodeURI() 또는 decodeURI()에 잘못된 파라미터가 전달될 때 발생하는 오류를 나타내는 인스턴스를 만듭니다.
  • AggregateError — 하나의 연산이 여러 오류를 보고해야 할 때(예: Promise.any()) 여러 오류를 단일 오류로 감싸는 인스턴스를 만듭니다.
  • InternalError — JavaScript 엔진의 내부 오류(예: "too much recursion")가 발생할 때를 나타내는 인스턴스를 만듭니다.

생성자

  • Error() — 새 Error 객체를 만듭니다.

정적 속성

  • Error.stackTraceLimit — 오류 스택 트레이스에 포함할 스택 프레임 수를 제한하는 비표준 숫자 속성.

정적 메서드

  • Error.captureStackTrace() — 제공된 객체에 stack 속성을 만드는 비표준 함수.
  • Error.isError() — 인자가 오류이면 true, 그렇지 않으면 false를 반환합니다.
  • Error.prepareStackTrace() — 사용자 코드가 제공하면 던져진 예외에 대해 JavaScript 엔진이 호출하는 비표준 함수로, 스택 트레이스의 사용자 정의 형식을 제공할 수 있게 합니다.

인스턴스 속성

Error.prototype에 정의되어 모든 인스턴스가 공유하는 속성: constructor, name(오류 타입의 이름, 초기 값은 "Error"이며 TypeError·SyntaxError 같은 서브클래스는 각자 name 속성을 제공), stack(비표준 스택 트레이스 속성). 각 인스턴스의 고유 속성: cause(현재 오류가 던져진 이유, 보통 잡힌 다른 오류), columnNumber, fileName, lineNumber(비표준 Mozilla 속성), message(오류 메시지).

인스턴스 메서드

  • Error.prototype.toString() — 지정된 객체를 나타내는 문자열을 반환합니다. Object.prototype.toString() 메서드를 재정의합니다.

예제

일반 오류 던지기 — 보통 throw 키워드로 오류를 발생시키기 위해 Error 객체를 만듭니다. try...catch 구문으로 처리할 수 있습니다.

try {
  throw new Error("Whoops!");
} catch (e) {
  console.error(`${e.name}: ${e.message}`);
}

특정 오류 타입 처리instanceof 키워드로 오류 타입을 검사해 특정 타입만 처리할 수 있습니다.

try {
  foo.bar();
} catch (e) {
  if (e instanceof EvalError) {
    console.error(`${e.name}: ${e.message}`);
  } else if (e instanceof RangeError) {
    console.error(`${e.name}: ${e.message}`);
  }
  // 등등
  else {
    // 우리 케이스와 일치하는 게 없으면 Error를 처리되지 않은 채로 둔다
    throw e;
  }
}

유사한 오류 구별하기 — 코드 블록이 서로 다른 처리를 요구하는 이유로 실패하지만 매우 유사한 오류(같은 타입과 메시지)를 던질 때가 있습니다. 원래 오류를 제어할 수 없다면, 그 오류를 잡아 더 구체적인 메시지를 가진 새 Error를 던지는 방법이 있습니다. 원래 오류는 새 Error의 생성자 options 파라미터에 cause 속성으로 전달해야 상위 try/catch 블록에서 원래 오류와 스택 트레이스를 사용할 수 있습니다.

function doWork() {
  try {
    doFailSomeWay();
  } catch (err) {
    throw new Error("Failed in some way", { cause: err });
  }
  try {
    doFailAnotherWay();
  } catch (err) {
    throw new Error("Failed in another way", { cause: err });
  }
}

라이브러리를 만든다면 오류 메시지를 파싱하도록 소비자에게 요구하는 대신 오류 cause로 서로 다른 오류를 구별하는 것이 좋습니다. 사용자 정의 오류 타입도 서브클래스 생성자가 super()를 호출할 때 options 파라미터를 전달하면 cause 속성을 사용할 수 있습니다. Error() 기본 클래스 생성자는 options.cause를 읽고 새 오류 인스턴스에 cause 속성을 정의합니다.

사용자 정의 오류 타입Error에서 파생된 자신만의 오류 타입을 정의해 throw new MyError()와 함께 사용하고, 예외 핸들러에서 instanceof MyError로 오류 종류를 검사할 수 있습니다. 이렇게 하면 더 깔끔하고 일관된 오류 처리 코드가 됩니다.

주의: 내장 클래스의 서브클래싱은 Reflect.construct()가 없으면 특정 new.target으로 기본 클래스를 만들 방법이 없어 ES6 이전 코드로 안정적으로 트랜스파일할 수 없습니다. 추가 설정이 필요하거나 생성자 끝에서 수동으로 Object.setPrototypeOf(this, CustomError.prototype)을 호출해야 합니다.

class CustomError extends Error {
  constructor(foo = "bar", ...params) {
    super(...params);
    if (Error.captureStackTrace) {
      Error.captureStackTrace(this, CustomError);
    }
    this.name = "CustomError";
    this.foo = foo;
    this.date = new Date();
  }
}

더 알아보기

  • throw, try...catch — 예외 처리 구문
  • TypeError, RangeError, ReferenceError, SyntaxError, URIError, EvalError — 내장 오류 타입
  • core-js의 Error cause 폴리필