FE 개발노트/Javascript

자바스크립트의 에러 생성 과정과 NativeError 예시

미스터코다리 2021. 10. 3. 15:42

1. 자바스크립트가 에러를 던지는 방법

(이번 단원은 Error 객체가 생성되고 상속되는 과정을 설명한 부연설명이므로 NativeError의 종류만 보고싶다면 지나쳐도 된다)

자바스크립트 에러가 감지하면 Error 생성자 함수를 통해 인스턴스를 생성하고 이를 throw, 즉 던진다. 또한 프로토타입 체인을 통해 NativeError, AggregateError 등 더 세부적인 에러 인스턴스들을 생성하여 던질 수 있다. (참고 : 20.5 Error Objects)

1-1. 에러를 생성하는 빌트인 객체 Error

Error Contructor

  • 전역 객체의 Error 프로퍼티의 초기값
  • [[Prototype]] 값으로 %Function.prototype%를 가짐
  • 하위 클래스로 확장 가능
  • 하위 클래스는 반드시 super 호출을 통해 [[ErrorData]] 값을 상속받아야 함

Error prototype object

  • [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false
  • 일반 객체다
  • 던져질 수 있는 Error 인스턴스가 아니다
  • [[ErrorData]] 내부 슬롯이 없다
  • %Error.prototype%
  • Object.prototype을 직접 상속받는다.

Error instance

  • Error 빌트인 객체로 생성한 인스턴스
  • 컨스트럭터를 통해 [[ErrorData]] 값을 가짐
  • 최종적으로 throw 던져지는 객체

1-2. Error를 상속받는 NativeError constructors

NativeError constructors

Error 객체를 상속받으며 extends 키워드를 통해 하위 클래스를 가질 수 있다. 에러 상황에 따라 구분되어진 총 6개의 종류가 있다.

NativeError 인스턴스들은 Error 프로토타입 객체를 상속받기 때문에 오류 메시지 값을 가지는 Error.prototype.message, 오류 이름의 Error.prototype.name 프로퍼티들을 사용할 수 있다.

총 6가지로 나뉘지만 EvalError는 실질적으로 사용하지 않기 때문에 5가지 종류라고 봐도 무방하다. (EvalError는 현재 사양서 기준 사용되지 않지만 이전 버전과의 호환을 위해 남겨둔 것이다.)

  • NativeError construnctors 종류 6가지

    • %ReferenceError.prototype%
    • %SyntaxError.prototype%
    • %TypeError.prototype%
    • %RangeError.prototype%
    • %URIError.prototype%
    • %EvalError.prototype%
  • [[Prototype]] 값으로 %Error%를 갖는다. 즉, Error 객체를 상속받는다.

  • extends 키워드를 통해 하위 클래스를 가질 수 있다.

1-3. 작동 방법

throw new Error('There is error') 와 같이 Error 빌트인 객체를 이용해 직접 에러를 만들어줄 수도 있으며, AggregateError(다수의 에러를 래핑한 것)로 처리할 수 도 있다. 런타임 진행 중 특정 상황에 맞춰 자동으로 NativeError를 생성해주기도 한다.

이번 포스팅에서는 특정 상황에 따라 자바스크립트 엔진이 자동으로 생성해주는 NativeError에 대해 알아보고자 한다.

2. NativeError 각각의 예시

2-1. EvalError

MDN : TypeError is used to indicate an unsuccessful operation when none of the other NativeError objects are an appropriate indication of the failure cause.

2-2. RangeError

어떤 값이 집합에 없거나 허용되는 범위가 아닌 경우 발생

MDN : Indicates a value that is not in the set or range of allowable values.

const arr = [1,2,3]
arr.length=90**99
// Uncaught RangeError: Invalid array length

const arr = new Array(1000000);
const arr2 = [];
arr2.push(...arr);
// Uncaught RangeError: Maximum call stack size exceeded

(괜한 부연 설명)왠지 범위 에러라고하면 배열에 없는 인덱스값이 접근할 때 나는게 아닌가.. 라고 착각할 수 있다. 하지만 자바스크립트에서 배열은 인덱스로 접근하는 것 처럼 보여도 실은 해쉬맵 기반 + 동적 접근을 하는 자료구조다. 없는 인덱스값에 접근했을 땐 마치 객체에 없는 프로퍼티에 접근한 것과 같이 undefined가 뜬다.

const arr = [1,2,3];
arr[6]; //undefined

2-3. ReferenceError

스코프체인(렉시컬 환경의 환경리코드)에서 식별자를 찾을 수 없을 때 발생

MDN : Indicate that an invalid reference has been detected.

let 1 = 1;
// Uncaught SyntaxError: Unexpected number
const apple = "testing"
apple;
banana;
// Uncaught ReferenceError: banana is not defined

2-4. SyntaxError

토크나이징, 파싱 과정에서 문맥상 요소의 역할을 파악할 수 없을 때 발생

MDN : Indicates that a parsing error has occurred.

let apple h = "apple"
// Uncaught SyntaxError: Unexpected identifier

class A {
    constructor(){}
    constructor(){}
}
// Uncaught SyntaxError: A class may only have one constructor

2-5. TypeError

다른 NativeError 생성 조건에 부합하지 않는 경우. 실행 중 데이터타입이 올바르게 사용되지 않았을 때 발생

MDN : TypeError is used to indicate an unsuccessful operation when none of the other NativeError objects are an appropriate indication of the failure cause.

함수에 전달된 피연산자 또는 인수가 해당 연산자나 함수가 예상하는 타입과 호환되지 않음
변경할 수 없는 값을 수정
부적절한 방법으로 값을 사용

const num = 123
num.toUpperCase()
// Uncaught TypeError: num.toUpperCase is not a function

2-6. URIError

전역 URI 핸들링 함수가 잘못된 방법으로 사용되었을 때 발생

MDN : Indicates that one of the global URI handling functions was used in a way that is incompatible with its definition.

try {
  decodeURIComponent('%')
} catch (e) {
  console.log(e instanceof URIError)  // true
  console.log(e.message)              // "malformed URI sequence"
  console.log(e.name)                 // "URIError"
  console.log(e.fileName)             // "Scratchpad/1"
  console.log(e.lineNumber)           // 2
  console.log(e.columnNumber)         // 2
  console.log(e.stack)                // "@Scratchpad/2:2:3\n"
}

3. Conclusion

Error 빌트인 객체(생성자 함수)를 통해, 혹은 그를 상속받은 객체를 통해 인스턴스를 생성하고 이를 던짐으로서 에러를 발생시키고 해당 기능을 종료한다.

에러 메시지와 종류를 통해 어떤 문제가 있는지 파악하면 에러 해결에 도움이 된다.

참고 링크

ECMAScript2021 NativeError
MDN Error
MDN URIError
MDN SyntaxError
MDN ReferenceError
MDN TypeError
MDN RangeError