본문 바로가기

Language/JavaScript

<자바스크립트> try catch & 에러

 

1. try catch

* 소개

 - try catch문법은 에러를 잡아서 다룰 수 있게 도와준다.

 

try {
  // ...
} catch (err) {
  // ...
}

 

  - 위와 같은 꼴을 하고 있으며, 먼저 try 내부의 코드를 실행한다. 에러가 없으면 catch를 건너뛰고 에러가 있으면 임의의 인자 err에 에러객체를 담아 catch를 실행한다.

 

 - 이렇게 하면 에러가 발생하더라도 스크립트가 죽지 않고 에러를 별도로 처리할 수 있다.

 

 - try catch는 런타임 에러에만 동작하므로 우선 실행 가능한 코드를 작성해야한다.

 

 - try catch는 동기적으로 작동하므로 try내부에 스케줄 된 코드를 작성하면 에러를 잡아내기 힘들다. 이럴 때는 스케줄된 함수 내부에 try catch를 작성하면 된다.

 

* 에러 객체

 - 에러 객체는 다음과 같이 세 가지의 프로퍼티를 가질 수 있다.

 

 - name : 에러 이름.

 - message : 에러 상세 내용

 - stack : 비표준 프로퍼티로 현재 호출 스택을 의미. 에러를 유발한 중첩 호출들의 순서정보를 가지고 있음

 

try {
  harry;
} catch(err) {
  console.log(err.name); // ReferenceError
  console.log(err.message) // harry is not defined
  console.log(err.stack); // ReferenceError: harry is not..

  console.log(err)
  // ReferenceError: harry is not defined
}

 

2. 에러 만들기

* throw

 - 실무에서 문법상의 오류는 없으나 의도치 않은 에러를 맞닥뜨릴 수 있다. 이런 경우 에러로 인지하지 못하고 try만 실행된다. 아래 예시를 보자.

 

let json = '{ "age": 22 }';

try {
  
  let user = JSON.parse(json);
  console.log( user.name );
  
} catch (e) {
  console.log( "에러 발생" );
}

// undefined

 

 - json파일이 name과 age를 담고 있기를 바라지만 age만 등록되어 넘어온 경우이다. 이 때 parse로 user에 객체를 담고 name을 확인하면 undefined가 출력될 것이다. 이는 catch에서 잡지 못하는 에러이다.

 

 - 위와 같은 경우에서 throw연산자를 사용하면 에러를 생성할 수 있다.

 

throw <error object>

 

  - 이론적으로는 원시형 자료를 포함한 어떤 것이든 에러 객체로 사용할 수 있으나 내장에러와의 호환을 위해 에러 객체에 name과 message 프로퍼티를 넣는 것을 권장한다.

 

 - 자바스크립트는 Error, SyntaxError, ReferenceError, TypeError등의 표준 에러 객체 관련 생성자를 지원하므로 이를 이용해 에러 객체를 만들 수도 있다.

 

let error = new Error("에러 발생!!");

console.log(error.name); // Error
console.log(error.message); // 에러 발생!!

 

 - 내장 생성자를 사용해 만든 에러 객체는 name 프로퍼티는 생성자 이름과 동일하며, message 값은 인수에서 가져온다.

 

let json = '{ "age": 22 }';

try {

  let user = JSON.parse(json);

  if (!user.name) {
    throw new SyntaxError("이름이 필요합니다.");
  }

  console.log( user.name );

} catch(err) {
  console.log( "JSON Error: " + err.message );
  // JSON Error: 이름이 필요합니다.
}

 

 - 이제 위에서 처리하지 못했던 에러를 정상적으로 catch해서 처리하는 것을 볼 수 있다.

 

* 다시 던지기

 - 위에서 에러를 정상적으로 catch한 것 처럼 보이지만 한가지 문제가 있다. 만약 json문제가 아닌 다른 문제가 나타났다면 어떨까? 그렇다 하더라도 catch는 하나 뿐이며 똑같이 JSON Error라고 출력할 것이다.

 

 - 이러한 문제를 해결하려면 catch는 알고 있는 에러만 처리하고 나머지는 다시 던져야 한다.

 

function readData() {
  let json = '{ "age": 22 }';

  try {
    // ...
    blabla(); // 에러
  } catch (err) {
    // ...
    if (!(err instanceof SyntaxError)) {
      throw err;
    }
  }
}

try {
  readData();
} catch (err) {
  console.log( "에러: " + err ); 
  // 에러: ReferenceError: blabla is not defined
}

 

 - 위는 try catch를 하나 더 만들어서, 예상치 못한 에러를 처리하는 예시이다.

 

 - 내부적으로 instanceof로 SyntaxError인지를 확인하였고 이것이 아니라면 err를 다시 던진다.

 

 - 이렇게해서 외부에서 catch하여 에러를 처리한다.

 

3. finally

* finally

 - try catch는 finally라는 코드 절을 하나 더 가질 수 있다.

 

try {
   ... 코드를 실행 ...
} catch(e) {
   ... 에러 핸들링 ...
} finally {
   ... 항상 실행 ...
}

 

 - finally는 try실행이 끝난 후거나 catch실행이 끝난 후 반드시 실행된다.

 

 - finally는 return을 사용해서 명시적으로 빠져나가는 경우에도 실행된다.

 

 - finally는 실행 결과에 상관없이 실행을 완료하고 싶을 경우에 사용 된다.(ex, 시간 측정)

 

 - 참고로 try, catch, finally안의 변수는 각각 지역변수이므로 유의하자.

 

 


 

 

참고

 

 

 

모던 자바스크립트 튜토리얼

 

모던 JavaScript 튜토리얼

 

ko.javascript.info