에러 핸들링

seeen·2023년 4월 6일
0
post-thumbnail

이 글은 '이웅모'님의 '모던 자바스크립트 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' 문자열을 출력한다.

단축 평가와 if문

단축 평가란 간략하게 정리하면 표현식을 평가하는 도중에 평가 결과가 확정된 경우 나머지 평가 과정을 생략하는 것을 말한다. 즉, 다음과 같다.

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 finally 문

일반적으로 이 방식을 에러 핸들링이라 한다. 문법은 다음과 같다.

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 객체

Error 생성자 함수는 에러 객체를 생성한다. 에러 메세지를 인수로 전달할 수 있다.

const error = new Error('[ERROR]');

Error 생성자 함수로 생성한 에러 객체는 message 프로퍼티와 stack 프로퍼티를 갖는데 message 프로퍼티는 생성자 함수 인수로 전달한 에러 메시지이고, stack 프로퍼티는 에러를 발생시킨 콜 스택의 호출 정보를 나타내는 문자열이다. 이들은 디버깅 목적으로 사용된다.

또한 에러 객체의 프로토타입은 Error.prototype이다. 에러의 종류는 여기를 참고하자.

throw 문

에러 객체를 던질 때 주로 사용한다. 에러 객체를 생성한다고 에러가 발생하는 것이 아니라 throw문으로 에러 객체를 던져야 에러가 발생한다.

에러의 전파

에러는 호출자 방향으로 전파된다. 즉 콜 스택의 아래 방향인 이전에 푸쉬된 실행 컨텍스트의 방향으로 전파된다.

const foo = () => {
  throw new Error('[ERROR]');
}

const goo = () => {
  foo();
}

const hoo = () => {
  goo();
}

hoo();

profile
woowacourse FE 5th, depromeet Web 15th

0개의 댓글