원본: Try/Catch in JavaScript – How to Handle Errors in JS
자바스크립트 코딩 시 버그와 오류 발생은 불가피한 요소입니다.
개인 프로젝트에 오류가 있어서 밤새 디버깅했는데 단순한 쉼표 같은 것이 원인이었다면 허탈했을 것 입니다. 하지만 고객이 보고한 오류는 좀 더 진지하게 심각합니다.
오류는 개발자를 짜증나고 고통스럽게 합니다. 이 포스트에서는 이러한 고통을 줄이기 위해 try…catch 라는 자바스크립트 구문에 대해 알아보겠습니다.
Table of Contents
try…catch 블록 이란?
try…catch 블록은 기본적으로 자바스크립트의 오류를 처리하는 구문입니다. 스크립트 오류로 코드가 손상되는 것을 방지하고자 할 때 이 구문을 사용합니다.
동일한 작업을 if 문으로 수행할 수 있을 것 처럼 보이지만, try…catch 구문은 if…else 문이 수행하는 것 이상의 많은 이점이 있습니다.
다음은 문법 구문입니다:
try {
//...
} catch (e) {
//...
}
try 블록에서는 코드의 오류를 테스트할 수 있습니다.
catch 블록은 오류가 발생했을 때 오류를 처리하는 부분입니다.
다음의 예제를 개발자 도구에서 실행해 보겠습니다:
try {
getData(); // getData 라는 함수가 없을 때
} catch (e) {
alert(e);
}
위의 코드가 기본적인 사용 구문입니다.
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 구문을 위와 같이 사용하면 편해 보이지만 자바스크립트의 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");
}
중첩 try 구문
이 구문 역시 다른 모든 자바스크립트 구문(if 문, for 문)과 마찬가지로 중첩이 가능합니다.
하지만 이는 코드를 읽기 어렵게 만들고 복잡하게 하기 때문에 사용하지 않는 것이 좋습니다.
다음의 예제를 확인해 보겠습니다:
try {
try {
throw new Error('oops');
} catch (e) {
console.log(e);
} finally {
console.log('finally');
}
} catch (ex) {
console.log('outer ' + ex);
}
위 예제에서 console.log() 메소드로 확인 결과 바깥의 catch는 실행되지 않는 것을 확인할 수 있습니다.
왜냐하면 안쪽 try…catch 구문에서 예외를 올바르게 처리했기 때문에 바깥의 블록에서 보기에는 안쪽 구문에 아무런 문제가 없기 때문입니다.
try {
try {
throw new Error('oops');
} finally {
console.log('finally');
}
} catch (ex) {
console.log('outer ' + ex);
}
이번 예제는 안쪽 구문에 catch로 예외를 처리하는 부분이 없습니다.
따라서 바깥 구문에서 보기에 안쪽 구문에 예외가 있는 것으로 판단하고 바깥의 catch가 실행되어 콘솔에 메시지를 출력했습니다.
정리
이 포스트에서는 다음과 같은 try…catch 구문과 관련된 개념을 알아봤습니다:
- try…catch 구문이 무엇인지, 또 어떻게 작동하는지
- 사용자 정의 에러를 어떻게 발생시키는지
- finally 구문이 무엇인지, 어떻게 사용하는지
- 구문이 중첩되면 어떻게 작동하는지