본문 바로가기

JavaScript

[Deep dive] 47장 에러 처리

47.1 에러 처리의 필요성 

 

- 에러(error)가 발생하지 앟는 코드를 작성하는 것은 불가능. 따라서 에러는 언제나 발생 가능 

- 발생한 에러에 대해 대처하지 않고 방치하면 프로그램은 강제 종료됨

- 직접적으로 에러를 발생하지는 않는 예외(exception)적인 상황이 발생할 수 도 있음. 예외적인 상황에 적절하게 대응하지 않으면 에러로 이어질 가능성이 큼

//DOM에 button 요소가 존재하지 않으면 querySelector 메서드는 에러를 발생시키지 않고 null을 반환
const $butoon = document.querySelector('button'); //null
$button.classList.add('disabled');
//TypeError: Cnnot read property 'classList' of null

- 우리가 작성한 코드에서는 언제나 에러나 예외적인 상황이 발생할 수 있다는 것을 전제하고 이에 대응하는 코드를 작성하는 것이 중요 

 

47.2 try...catch ... finally문

 

예외 처리 방법

 

1) querySelector나 Array#find메서드처럼 예외적인 상황이 발생하면 반환하는 값(null 또는 -1)을 if 문이나 단축 평가 또는 옵셔널 체이닝 연산자를 통해 확인해서 처리하는 방법

 

2) 예외 처리 코드를 미리 등록해두고 에러가 처리하면 에러 처리 코드로 점프하도록 하는 방법

 = try...catch...finally문 

 

try...catch...finally문

 - try...catch...finally문으로 에러를 처리하면 프로그램이 강제 종료되지 않음

try {
	//실행할 코드 (에러가 발생할 가능성이 있는 코드)
}catch(err) {
 	//try 코드 블록에서 에러가 발생하면 이 코드 블록의 코드가 실행
    //err에는 try 코드 블록에서 발생한 Error 객체가 전달됨
} finally {
	//에러 발생과 상관없이 반드시 한 번 실행
}

- 먼저 try 코드 블록이 실행. 이떄 try 코드 블록에 포함된 문 중에서 에러가 발생하면 발생한 에러는 catch문의 err 변수에 전달되고 catch 코드 블록이 실행 

- catch문의 err 변수는 try 코드 블록에 포함된 문 중에서 에러가 발생하면 생성되고 catch 코드 블록에서만 유효 

- finally 코드 블록은 에러 발생과 상관없이 반드시 한 번만 실행

 

47.3 Error 객체 

 

- Error 생성자 함수는 에러 객체를 생성

- Error 생성자 함수에는 에러를 상세히 설명하는 에러 메시지를 인수로 전달 가능

const error = new Error('invalid');

- 에러 객체는 message 프로퍼티와 stack 프로퍼티를 가짐

 1) message 프로퍼티 

   : Error 생성자 함수에 인수로 전달한 에러 메시지

 

 2) stack 프로퍼티 

  : 에러를 발생시킨 콜스택의 호출 정보를 나타내는 문자열이며 디버깅 목적으로 상ㅇ 

 

- 자바스크립트는 7가지의 에러 객체를 생성할 수 있는 Error 생성자 함수 제공 

- 모두 Error.prototype을 상속 받음 

생성자 함수  인스턴스
Error 일반적 에러 객체
SyntaxError 자바스크립트 문법에 맞지 않는 문을 해석할 떄 발생하는 에러 객체 
ReferenceError  참조할 수 없는 식별자를 참조했을 때 발생하는 에러 객체
TypeError 피연산자 또는 인수의 데이터 타입이 유효하지 않을 때 발생하는 에러 객체
RangeError 숫자값의 허용 범위를 벗어났을 때 발생하는 에러 객체
URIError encodeURI 또는 decodeURI 함수에 부적절한 인수를 전달했을 떄 발생하는 에러 객체
EvalError eval 함수에서 발생하는 에러 객체 

 

47.4 thorw 문

 

- Error 생성자 함수로 에러 객체를 생성한다고 에러가 발생하는 것은 아님 

- 에러를 발생시키려면 try 코드 블록에서 thorw문으로 에러 객체를 던져야 함 

throw 표현식;

- 에러를 던지면 catch문의 에러 변수가 생성되고 던져진 에러 객체가 할당. 그리고 catch 코드 블록이 실행되기 시작

try {
   //에러 객체를 던지면 catch 코드 블록이 실행되기 시작
   thorw new Error('something wrong');
} catch(error) {
   console.log(error);
}

ex)

 - 외부에서 전달받은 콜백 함수를 n번만큼 반복 호출하는 repeat 함수 

 - repeat 함수는 두 번쨰 인수로 반드시 콜백함수를 전달받아야 함 

//외부에서 전달받은 콜백 함수를 n번만큼 반복 호출
const repeat = (n,f) => {
  //매개 변수 f에 전달한 인수가 함수가 아니면 TypeError를 발생
  if(typeof f !== 'function') throw new TypeError('f must b a function');

  for(var i = 0; i < n; i++) {
    f(i); //i를 전달하면서 f를 호출
  }
};

try {
    repeat(2,1); //두 번째 인수가 함수가 아니므로 TypeError가 발생(throw)
} catch(err) {
  console.error(err); //TypeError: f must b a function
}

 

47.5 에러의 전파 

 

- 에러는 호출자(caller) 방향으로 전파

- 콜 스택의 아래 방향(실행 중인 실행 컨텍스트가 푸시되기 직전에 푸시된 실행 컨텍스트 방향)으로 전파

const foo = () => {
  throw Error('foo에서 발생한 에러');
};

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

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

try {
  baz();
} catch(err) {
  console.error(err);
}

- baz 함수를 호출하면 bar 함수가 호출되고 그 다음 foo 함수가 호출되고 foo 함수는 에러를 throw함 

- foo 함수가 thorw한 에러는 호출자에게 전파되어 전역에서 캐치 

- throw된 에러를 캐치하지 않으면 호출자 방향으로 전파. throw된 에러를 캐치하여 적절히 대응하면 프로그램을 강제 종료시키지 않고 코드의 실행 흐름을 복구할 수 있음. throw된 에러를 어디에서도 캐치하지 않으면 프로그램은 강제 종료됨