본문 바로가기
Archive

try ... catch 와 에러 핸들링

by livemehere 2022. 9. 4.

예상치 못한 에러가 발생하면, 스크립트는 즉시 중단되고 콘솔에 에러가 출력된다.

하지만 스크립트가 죽는경우는 최악의 경우이기 때문에, 에러 발생 소지가 있는 곳에서 try.. catch 구문을 통해 발생한 에러를 핸들링할 수 있다.

 

try 구문에는 실행가능한 코드만 동작한다.

코드를 읽는 중에 발생하는 에러를 parse-time error 라고하고,

try 구문 내용이 유효한 코드만 에러를 처리할 수 있다.

이런 에러를 runtime error 혹은 exception 이라고 한다.

에러처리가 안되는 경우

scheduled 된 코드에서 발생한 예외는 잡을 수 없다.

콜백함수 내의 코드는 실행될 시점에는 try.. catch문 바깥영역이기 때문이다.

try {
  setTimeout(function() {
    noSuchVariable; // 스크립트는 여기서 죽습니다.
  }, 1000);
} catch (e) {
  alert( "작동 멈춤" );
}

 

그래서 아래와같이 작성해아한다.

setTimeout(function() {
  try {
    noSuchVariable; // 이제 try..catch에서 에러를 핸들링 할 수 있습니다!
  } catch {
    alert( "에러를 잡았습니다!" );
  }
}, 1000);

Error 객체

1. name : 없다면 ReferenceError 가 이름

2. message : 에러의 상세내용을 담고있는 메세지

+ stack : 호출스택, 에러를 유발한 중첩 호출들의 순서 정보를 가진 문자열로 디버깅 목적으로 사용된다.

 

에러에대한 정보가 필요하지 않다면, 생략할 수 있다

try {
  // ...
} catch { // <-- (err) 없이 쓸 수 있음
  // ...
}

 

에러 객체는 name 과 message를 참조할 수 있다.

try {
  JSON.parse("{ 잘못된 형식의 json o_O }");
} catch(e) {
  alert(e.name); // SyntaxError
  alert(e.message); // Unexpected token b in JSON at position 2
}

여기서 흔히 axios를 통한 통신에러는 AxiosError 객체가 던져지는데,

서버에서 에러 status와 함께 보내는 데이터는 e.data 에 들어있다.

 

어떤 에러가 발생할지 모른다면

명확하게 하나의 에러가 아니라, 다양한 에러가 발생할 수 있다면, 타입을 명확하게 체크해주는 것이 좋다.

try {
  ...
  readUser()  // 잠재적 에러 발생처
  ...
} catch (err) {
  if (err instanceof ValidationError) {
    // validation 에러 처리
  } else if (err instanceof SyntaxError) {
    // 문법 에러 처리
  } else {
    throw err; // 알 수 없는 에러는 다시 던지기 함
  }
}

스크립트 전역의 에러 잡기

윈도우 전역에서 핸들링되지 않은 에러를 잡을 수 있다.

만능은 아니지만, 이런용도를 통해 개발자에게 에러를 전달하는 목적이있다.

window.onerror = function(message, url, line, col, error) {
    alert(`${message}\n At ${line}:${col} of ${url}`);
  };

커스텀 에러만들기

에러는 개발자에게 도움을 주기위한 것이기 때문에, 직관적일 수록 좋다.

그래서 커스텀에러를 만들곤 하는데, 이때 Error 를 상속받아 만드는 것이 좋다.

이렇게 했을때 instaceof Error 를 사용할 수 있어, 여러 에러객체를 식별할 수 있다는 장점이 있다.

 

아래처럼 super에 message 전달을 해준 후 name 프로퍼티를 덮어쓰거나, 새로운 프로퍼티를 추가하면 된다.

class ValidationError extends Error {
  constructor(message) {
    super(message); // (1)
    this.name = "ValidationError"; // (2)
  }
}

function test() {
  throw new ValidationError("에러 발생!");
}

try {
  test();
} catch(err) {
  alert(err.message); // 에러 발생!
  alert(err.name); // ValidationError
  alert(err.stack); // 각 행 번호가 있는 중첩된 호출들의 목록
}

 

에러 객체를 식별할 때, instanceof 도 되지만, name으로 식별할 수 도있다.

// ...
// (err instanceof SyntaxError) 대신 사용 가능
} else if (err.name == "SyntaxError") { // (*)
// ...

 

반응형

'Archive' 카테고리의 다른 글

제너레이터  (0) 2022.09.04
Promise의 5가지 API  (0) 2022.09.04
내장 클래스 확장하기  (0) 2022.09.03
class의 정적 메서드, 정적 프로퍼티  (0) 2022.09.03
클래스 문법  (0) 2022.09.03