이 글은 '이웅모'님의 '모던 자바스크립트 Deep Dive' 책을 통해 공부한 내용을 정리한 글입니다. 저작권 보호를 위해 책의 내용은 요약되었습니다.
에러가 없는 코드를 한 번에 작성하는 것은 매우 힘든 일이다. 에러가 발생하면 프로그램은 실행 도중 강제 종료되므로 에러 핸들링은 매우 중요하다.
다음 코드를 보자.
const $button = document.querySelector('button');
$button.classList.remove('hidden');
console.log('hello');
위 코드는 DOM에서 button
태그를 찾고 class 속성들 중 hidden
이란 속성을 제거하라는 코드이다. 만약 DOM에 버튼 태그가 없다면 이는 고스란히 런타임 에러로 이어진다.
따라서 두 번째 줄에서 Uncaught TypeError
를 발생시키고 프로그램은 강제 종료되어 기대했던 'hello'란 문자열 값을 콘솔에서 볼 수 없을 것이다.
옵셔널 체이닝 연산자는 간략하게 정리하면 ?
연산자 앞 요소가 nullish
하다면 에러 대신 undefined
를 반환한다. 자세한 내용은 여기를 참고하자.
따라서 위의 코드를 다음과 같이 개선시켜볼 수 있을 것이다.
const $button = document.querySelector('button');
$button?.classList.remove('hidden');
console.log('hello');
해당 코드는 에러를 반환하지 않고 'hello' 문자열을 출력한다.
단축 평가란 간략하게 정리하면 표현식을 평가하는 도중에 평가 결과가 확정된 경우 나머지 평가 과정을 생략하는 것을 말한다. 즉, 다음과 같다.
const name = true && 'Kim';
const age = false || 100;
console.log(name, age); // Kim 100
위 코드를 다음과 같이 단축평가 또는 if
문을 사용해서 런타임 에러를 방지할 수 있다.
// 단축 평가
const $button = document.querySelector('button');
$button && $button.classList.remove('hidden');
console.log('hello');
// if문
const $button = document.querySelector('button');
if($button instanceof HTMLButtonElement) $button.classList.remove('hidden');
console.log('hello');
두 코드 모두 정상적으로 'hello'를 콘솔에 출력한다.
일반적으로 이 방식을 에러 핸들링이라 한다. 문법은 다음과 같다.
try {
// 실행하고자 하는 코드 (에러 및 예외 발생 가능성이 있는 코드)
} catch (error) {
// 에러 발생 시 실행할 코드 (error에 Error 객체가 전달된다.)
} finally {
// 에러 발생 여부와 상관없이 무조건 한 번 실행되는 코드
}
우선은 먼저 try
블록의 코드가 실행이 되고, 에러가 발생한다면 catch
블록의 코드가 실행이 된다. 그리고 발생한 Error 객체가 error
매개변수에 전달되며 catch
블록에서만 유효하다. finally
블록은 에러 발생 여부와 상관없이 무조건 한 번 실행된다.
try {
const $button = document.querySelector('button');
if(!($button instanceof HTMLButtonElement)) throw new Error('[ERROR] button 없음!');
$button.classList.remove('hidden');
} catch (e) {
console.error(e);
}
console.log('hello');
위 코드를 실행해보면 다음과 같은 결과를 볼 수 있다.
Error
생성자 함수는 에러 객체를 생성한다. 에러 메세지를 인수로 전달할 수 있다.
const error = new Error('[ERROR]');
Error
생성자 함수로 생성한 에러 객체는 message
프로퍼티와 stack
프로퍼티를 갖는데 message
프로퍼티는 생성자 함수 인수로 전달한 에러 메시지이고, stack
프로퍼티는 에러를 발생시킨 콜 스택의 호출 정보를 나타내는 문자열이다. 이들은 디버깅 목적으로 사용된다.
또한 에러 객체의 프로토타입은 Error.prototype
이다. 에러의 종류는 여기를 참고하자.
에러 객체를 던질 때 주로 사용한다. 에러 객체를 생성한다고 에러가 발생하는 것이 아니라 throw
문으로 에러 객체를 던져야 에러가 발생한다.
에러는 호출자 방향으로 전파된다. 즉 콜 스택의 아래 방향인 이전에 푸쉬된 실행 컨텍스트의 방향으로 전파된다.
const foo = () => {
throw new Error('[ERROR]');
}
const goo = () => {
foo();
}
const hoo = () => {
goo();
}
hoo();