에러 핸들링이란?
스크립트가 돌다가, 에러를 만나면 프로그램이 죽으면서 콘솔에 에러와 메세지가 출력된다. 프로그램이 에러를 만나도, 꺼지는 것을 방지하기 위해 에러 핸들링을 한다.
자바스크립트에서는 try...catch를 사용하여 "런타임 에러" 핸들링이 가능하다.
- try... catch 구문 리터럴
try {
// 에러가 날 가능성이 있는 코드
// 에러가 없다면, catch 블럭으로 넘어가지 않고 끝까지 코드를 실행
} catch (err){
// try 구문에서 발생한 에러를 핸들링하고, 프로그램을 죽이지는 않음
// 발생한 에러를 err 객체로 받아옴.
// 에러의 주요 프로퍼티는 name과 message가 있으며, 비표준 프로퍼티로 에러가 발생한 스택 번호를 알 수 있는 stack 등이 있음
}
프로그램에서 알아서 에러를 캐치할 수도 있지만, 사용자가 원하는 곳에서 직접 에러 객체를 만들어 던질 수도 있다.
const error = new Error(message)
throw error
throw new Error("에러를 던지자")
/* 표준 에러 객체 생성자
Error
SyntaxError
ReferenceError
TypeError
*/
catch는 처리하도록 정의 된 에러만 처리하고, 그 외의 나머지 에러는 다시 던져야 한다.
function test() {
try {
throw new SyntaxError("catch에서 처리하도록 정의 된 에러")
} catch (err) {
if (err instanceof SyntaxError) {
console.log(err.message)
} else {
throw e // 에러 다시 던지기
}
}
}
try {
test();
} catch (e) {
console.log(e) // test() 함수 안의 try..cat문에서 다시 던진 에러를 여기서 잡음
}
이렇게 다시 던져진 에러는 try...catch문 밖으로 던져지고, 상위 스코프에 try...catch가 없다면 스크립트는 죽는다.
이렇게, 에러를 다시 던지는 방법을 사용하면, 블록 단위로 알고 있는 에러만 처리하고, 알 수 없는 에러는 밖의 블록으로 던질 수 있다.
마지막으로, try..catch..finally가 있다.
finally는 try -> error -> catch -> finally의 순으로 실행되거나, try -> finally 순으로 실행된다.
즉, error 발생의 유무와는 상관 없이, 무조건 finally 블록을 실행한다.
- 아래 예제는 모던 자바스크립트 튜토리얼에서 공수해왔다.
let num = +prompt("양의 정수를 입력해주세요.", 35)
let diff, result;
function fib(n) {
if (n < 0 || Math.trunc(n) != n) {
throw new Error("음수나 정수가 아닌 값은 처리할 수 없습니다.");
}
return n <= 1 ? n : fib(n - 1) + fib(n - 2);
}
let start = Date.now();
try {
result = fib(num);
} catch (e) {
result = 0;
} finally {
diff = Date.now() - start;
}
alert(result || "에러 발생");
alert( `연산 시간: ${diff}ms` );
finally를 사용할 때, 주의 점!
- try...catch 블록에 return이 있어도 finally가 실행된다. => return 값이 밖으로 반환 되기 전, finally 블록을 먼저 호출하고 return을 반환함
- try...finally 문도 가능함 => 이 경우, try 문에서 에러가 발생하면 스크립트가 죽지만, 죽더라도 finally 블록을 완료함
전역 catch
자바스크립트 호스트 환경에서는 대부분 try...catch에서 처리하지 못한 에러를 잡는 방법을 제공한다.
- Node.js의 경우, process.on("uncaughtException")를 통해 예외적이 에러를 처리할 수 있다.
import process from 'node:process';
process.on('uncaughtException', (err, origin) => {
fs.writeSync(
process.stderr.fd,
`Caught exception: ${err}\n` +
`Exception origin: ${origin}`
);
});
setTimeout(() => {
console.log('This will still run.');
}, 500);
// Intentionally cause an exception, but don't catch it.
nonexistentFunc();
console.log('This will not run.');
- 브라우저 환경에서는 window.onerror를 이용해 에러를 처리할 수 있다. window.onerror 프로퍼티에 함수를 할당하면, 에러를 만났을 때 해당 함수를 실행한다. 하지만, 보통 해당 방식으로 에러를 핸들링하지는 않고, 디버깅 용도로만 사용한다고 한다.
- 브라우저에서 에러 핸들링을 위한 상용 서비스는 https://ko.javascript.info/try-catch 페이지 참고
// 뜻밖의 에러를 만났을 때 처리 함수 할당
window.onerror = function(message, url, line, col, error) {
// ...
};
// 보통 에러 디버깅을 위한 사용
window.onerror = function(message, url, line, col, error) {
alert(`${message}\n At ${line}:${col} of ${url}`);
};
'항해99_10기 > 105일의 TIL & WIL' 카테고리의 다른 글
[3주차] [20221201] IP 주소와 port, 그리고 DNS (0) | 2022.12.01 |
---|---|
[3주차] [20221130] MongoDB 스키마 설계 (0) | 2022.11.30 |
[3주차] [20221128] REST API와 RESTful 아키텍처, HTTP PUT과 PATCH 차이점 (0) | 2022.11.28 |
[2주차 WIL] 2022.11.21 ~ 2022.1126 회고 (0) | 2022.11.27 |
[3주차] [20221127] for, for in, for of (0) | 2022.11.27 |