자바스크립트 try…catch 에러 핸들링

원본: Try/Catch in JavaScript – How to Handle Errors in JS

자바스크립트 코딩 시 버그와 오류 발생은 불가피한 요소입니다.

개인 프로젝트에 오류가 있어서 밤새 디버깅했는데 단순한 쉼표 같은 것이 원인이었다면 허탈했을 것 입니다. 하지만 고객이 보고한 오류는 좀 더 진지하게 심각합니다.

오류는 개발자를 짜증나고 고통스럽게 합니다. 이 포스트에서는 이러한 고통을 줄이기 위해 try…catch 라는 자바스크립트 구문에 대해 알아보겠습니다.

try…catch 블록 이란?

try…catch 블록은 기본적으로 자바스크립트의 오류를 처리하는 구문입니다. 스크립트 오류로 코드가 손상되는 것을 방지하고자 할 때 이 구문을 사용합니다.

동일한 작업을 if 문으로 수행할 수 있을 것 처럼 보이지만, try…catch 구문은 if…else 문이 수행하는 것 이상의 많은 이점이 있습니다.

다음은 문법 구문입니다:

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

try 블록에서는 코드의 오류를 테스트할 수 있습니다.

catch 블록은 오류가 발생했을 때 오류를 처리하는 부분입니다.

다음의 예제를 개발자 도구에서 실행해 보겠습니다:

try {
  getData(); // getData 라는 함수가 없을 때
} catch (e) {
  alert(e);
}
try...catch 예제

위의 코드가 기본적인 사용 구문입니다.

try 블록 내에서 오류가 발생하면 자바스크립트가 즉시 catch 블록에 제어권을 넘깁니다. 위 코드의 경우 경고창을 보여줍니다.

모든 자바스크립트 오류는 실질적으로 이름(Error, SyntaxError, TypeError)과 메시지 속성을 가지고 있는 객체입니다.

그렇기 때문에 위 catch 구문의 e를 경고창에 출력하면 “ReferenceError: getData is not defined”와 같은 메시지를 출력합니다.

다른 모든 자바스크립트 객체와 마찬가지로 e.name (ReferenceError) 과 e.message (getData is not defined) 처럼 속성에 개별적으로 접근할 수 있습니다.

하지만 위 코드의 기능은 에러를 경고창으로 알기 쉽게 보여줄 뿐 자바스크립트가 콘솔에 출력 해주는 작업과 크게 다를 바 없습니다.

그렇다면 이 구문을 쓰는 이유는 무엇일까요?

try…catch 구문 사용 방법

throw 구문

try…catch 구문의 장점 중 하나는 사용자 정의 오류를 표시할 수 있다는 점 입니다.

기존의 자바스크립트가 표시하는 지저분한 내용을 원하지 않는다면 throw 문을 사용하여 예외(exception)를 발생시킬 수 있습니다.

이 예외는 string, boolean, object 타입을 가질 수 있고, 예외가 발생하면 catch 문이 발생한 오류를 표시합니다.

const num = prompt("insert a number greater than 30 but less than 40");

try {
  if (isNaN(num)) throw "Not a number (☉。☉)!";
  else if (num>40) throw "Did you even read the instructions ಠ︵ಠ, less than 40";
  else if (num <= 30) throw "Greater than 30 (ب_ب)";
} catch (e) {
  alert(e);
}
throw 구문 예제

throw 구문을 위와 같이 사용하면 편해 보이지만 자바스크립트의 Error 생성자와 함께 오류를 throw 하는 것이 더 좋습니다.

기본적으로 자바스크립트의 Error는 다음의 6개 그룹으로 분류합니다:

  • EvalError – eval 함수 사용과 관련된 에러
  • RangeError – 입력한 숫자가 제한 범위 밖인 경우
  • ReferenceError – 선언되지 않은 변수를 사용했을 때
  • SyntaxError – 문법이 틀린 구문을 실행했을 때
  • TypeError – 허용되는 타입 이외의 타입을 사용한 경우
  • URIError – URI 함수에 잘못된 문자를 사용했을 때

위와 같은 에러 생성자를 활용하여 throw new Error("Hi there")와 같은 오류를 발생시킬 수 있습니다.

다음 예제와 같이 사용자 정의 에러 생성자 함수를 만들 수도 있습니다:

function CustomError(message) {
  this.value = "customError";
  this.message = message;
}

함수를 정의하면 throw new CustomError("data is not defined")와 같은 방식으로 사용할 수 있습니다.

finally 구문

finally 구문은 최종 실행 블록을 나타냅니다.

이는 try…catch 구문에 무슨 일이 발생하건(예외가 발생하건 안하건) 항상 마지막에 실행됩니다.

const data = prompt("name");

try {
  if (data === "") throw new Error("data is empty");
  else alert(`Hi ${data} how do you do today`);
} catch(e){
  alert(e);
} finally {
  alert("welcome to the try catch article");
}
finally 구문 예제

중첩 try 구문

이 구문 역시 다른 모든 자바스크립트 구문(if 문, for 문)과 마찬가지로 중첩이 가능합니다.

하지만 이는 코드를 읽기 어렵게 만들고 복잡하게 하기 때문에 사용하지 않는 것이 좋습니다.

다음의 예제를 확인해 보겠습니다:

try {
  try {
    throw new Error('oops');
  } catch (e) {
    console.log(e);
  } finally {
    console.log('finally');
  }
} catch (ex) {
  console.log('outer ' + ex);
}
try...catch 중첩 예제

위 예제에서 console.log() 메소드로 확인 결과 바깥의 catch는 실행되지 않는 것을 확인할 수 있습니다.

왜냐하면 안쪽 try…catch 구문에서 예외를 올바르게 처리했기 때문에 바깥의 블록에서 보기에는 안쪽 구문에 아무런 문제가 없기 때문입니다.

try {
  try {
    throw new Error('oops');
  } finally {
    console.log('finally');
  }
} catch (ex) {
  console.log('outer ' + ex);
}
try...catch 중첩 외부 catch 예제

이번 예제는 안쪽 구문에 catch로 예외를 처리하는 부분이 없습니다.

따라서 바깥 구문에서 보기에 안쪽 구문에 예외가 있는 것으로 판단하고 바깥의 catch가 실행되어 콘솔에 메시지를 출력했습니다.

정리

이 포스트에서는 다음과 같은 try…catch 구문과 관련된 개념을 알아봤습니다:

  • try…catch 구문이 무엇인지, 또 어떻게 작동하는지
  • 사용자 정의 에러를 어떻게 발생시키는지
  • finally 구문이 무엇인지, 어떻게 사용하는지
  • 구문이 중첩되면 어떻게 작동하는지

관련 글

자바스크립트 튜토리얼