[JS]47장 에러처리

JH Cho·2022년 12월 27일
0

모던JS DeepDive 공부

목록 보기
22/27
post-thumbnail

47.1_ 에러 처리의 필요성

  • 에러가 발생하지 않는 코드 작성은 불가능
  • 만약 에러 발생을 대처하지 않으면 프로그램은 강제종료 됨
console.log('[Start]');

foo(); // ReferenceError: foo is not defined
// 발생한 에러를 방치하면 프로그램은 강제 종료된다.

// 에러에 의해 프로그램이 강제 종료되어 아래 코드는 실행되지 않는다.
console.log('[End]');

이러한 에러에 대처하기 위해 try...catch 문 사용!

console.log('[Start]');

try {
  foo();
} catch (error) {
  console.error('[에러 발생]', error);
  // [에러 발생] ReferenceError: foo is not defined
}

// 발생한 에러에 적절한 대응을 하면 프로그램이 강제 종료되지 않는다.
console.log('[End]');
  • 직접적으로 에러를 발생하지 않는 예외적 상황
// DOM에 button 요소가 존재하지 않으면 querySelector 메서드는 에러를 발생시키지 않고 null을 반환한다.
const $button = document.querySelector('button'); // null

$button.classList.add('disabled');
// TypeError: Cannot read property 'classList' of null
  • 이 때 에러 처리 방법 2가지
    • "?." 옵셔널 체이닝 연산자 또는 if문으로 단축평가
    • try...catch 문 사용

47.2_ try...catch...finally문

  • 일반적으로 이 방법을 에러처리라고 함.
  • finally 문은 불필요하다면 생략 가능
  • catch 문도 생략 가능하지만 catch문 없는 try문은 의미가 없어 생략하지 않음.
console.log('[Start]');

try {
  // 실행할 코드(에러가 발생할 가능성이 있는 코드)
  foo();
} catch (err) {
  // try 코드 블록에서 에러가 발생하면 이 코드 블록의 코드가 실행된다.
  // err에는 try 코드 블록에서 발생한 Error 객체가 전달된다.
  console.error(err); // ReferenceError: foo is not defined
} finally {
  // 에러 발생과 상관없이 반드시 한 번 실행된다.
  console.log('finally');
}

// try...catch...finally 문으로 에러를 처리하면 프로그램이 강제 종료되지 않는다.
console.log('[End]');
  • try 블록에서 에러가 발생하면 그 에러는 catch문의 err변수에 전달되어 catch 문이 실행됨.
  • 이렇게 에러 처리를 이용하면 프로그램 강제종료 예방 가능

47.3_ Error 객체

  • Error 생성자 함수는 에러 객체를 생성
  • Error 생성자 함수의 인자는 에러 메시지를 넣을 수 있다.
const error = new Error("Error!!");

Error: Error!!
    at <anonymous>:1:15
message: "Error!!"
stack: "Error: Error!!\n    at <anonymous>:1:15"
[[Prototype]]
: Object
  • 에러 객체는 message 프로퍼티와 stack 프로퍼티를 가짐
  • message는 인자, stack은 에러를 발생시킨 콜스택의 호출 정보를 나타냄.
const error2 = new TypeError("hh")

TypeError: hh
    at <anonymous>:1:16
message: "hh"
stack: "TypeError: hh\n    at <anonymous>:1:16"

47.4_ throw 문

  • 에러 생성자 함수로 에러 객체를 생성한다고 에러가 발생하는 것이 아님
  • 에러 객체 생성과 발생은 다름!
  • 에러를 발생시키기 위해선 try 문에서 에러를 throw해야 함
try {
  if(true) throw new Error("something wrong");
} catch (error) {
  console.log(error);
}

47.5 에러의 전파

  • 에러는 호출자 방향으로 전파됨
  • 콜 스택의 아래 방향으로 전파됨(실행 중 컨텍스트가 푸쉬되기 직전에 푸쉬된 실행컨텍스트 방향)
const foo = () => {
  throw Error('foo에서 발생한 에러'); // ④
};

const bar = () => {
  foo(); // ③
};

const baz = () => {
  bar(); // ②
};

try {
  baz(); // ①
} catch (err) {
  console.error(err);
}
  • foo(에러발생) -> bar로 전파 -> baz로 전파 -> 전역에서 error가 캐치 됨.

  • throw된 에러를 캐치하지 않으면 호출자 방향으로 전파됨.

  • 이 때 throw된 에러를 캐치하여 적절히 대응하면 프로그램을 강제 종료하지 않고 코드의 실행 흐름을 복구 가능

  • throw된 에러를 어디서도 캐치하지 않으면 강종!

주의!
비동기함수인 setTimeout 또는 프로미스의 후속 처리 메서드의 콜백 함수는 호출자가 없다.
즉, 콜스택이 비었을 때 이벤트 루프에 의해 콜스택으로 푸쉬되어 실행되고 콜백함수의 실행 컨텍스트는 콜 스택의 가장 하부에 존재하여 에러를 전파할 호출자가 존재하지 않음.

profile
주먹구구식은 버리고 Why & How를 고민하며 프로그래밍 하는 개발자가 되자!

0개의 댓글