에러가 발생할 경우 에러 예외 처리를 해두지 않으면 서버가 다운되는 상황이 있을 수 있다.
그렇기에 에러 핸들링은 필수적으로 해야한다.
노드JS의 경우 우리가 늘 사용해왔던 것처럼 app.use()를 통해 미들웨어를 사용할 수 있는데 이를 이용하여 에러만 따로 처리하는 미들웨어도 쉽게 사용이 가능하다.
1. Error handling 미들웨어 선언하기
기본적으로 익스프레스에서 오류를 처리하는 공통 미들웨어는 아래와 같이 작성한다.
app.use(function (err, req, res, next) {
console.error(err.stack);
res.status(500).send("알 수 없는 에러가 발생하였습니다. 관리자에게 문의해 주세요.");
});
인자 3개를 선언하면 일반적인 미들웨어고 에러 미들웨어는 인자 4개를 선언한다.
익스프레스-제너레이터로 만들어보면 아래와 같다.
// catch 404 and forward to error handler
app.use(function (req, res, next) {
next(createError(404));
});
// error handler
app.use(function (err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get("env") === "development" ? err : {};
// render the error page
res.status(err.status || 500);
res.render("error");
});
주의할 점은 익스프레스-제너레이터로 만들경우 // 에러 핸들링의 코드는 맨 아래에 배치해야한다.
2. Async Await 사용
익스프레스는 ES6이 나오기 이전에 거의 다 만들어졌기에 비동기 에러를 처리하는데 잘 작동하지 않는다.
프로미스 리젝트 시 에러 처리 미들웨어에서 사용이 되지 않는 것을 볼 수 있다.
app.get("*", function (req, res) {
return new Promise((resolve, reject) => {
setImmediate(() => reject(new Error("에러 발생")));
});
});
app.use(function (error, req, res, next) {
console.log("호출 되지 않음!");
res.json({ message: error.message });
});
(node:6852) UnhandledPromiseRejectionWarning: Error: 에러 발생
at Immediate.<anonymous> (/Users/gim-yohan/Desktop/Projects/nodejs/mysessionApp/app.js:34:20)
at processImmediate (internal/timers.js:456:21)
(node:6852) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 1)
3. 헬퍼 함수 사용하기 비동기 오류 처리하기
function wrapAsync(fn) {
return function (req, res, next) {
// 모든 오류를 .catch() 처리하고 next()로 전달하기
fn(req, res, next).catch(next);
};
}
헬퍼 함수로 wrapAsync를 커스텀으로 만들면 된다. 한줄로 쓸 수도 있다.
const wrapAsync = (fn) => (req, res, next) => fn(req, res, next).catch(next);
app.get(
"*",
wrapAsync(async function (req, res) {
await new Promise((resolve) => setTimeout(() => resolve(), 50));
// 비동기 에러
throw new Error("에러 발생!");
})
);
app.use(function (error, req, res, next) {
res.json({ message: error.message });
});
app.listen(3000);
function wrapAsync(fn) {
return function (req, res, next) {
// 모든 오류를 .catch() 처리하고 체인의 next() 미들웨어에 전달
// (이 경우에는 오류 처리기)
fn(req, res, next).catch(next);
};
}
'[내배캠] TIL, WIL > TIL' 카테고리의 다른 글
| Typescript - 유니온/교차 타입 (0) | 2023.01.29 |
|---|---|
| TypeScript (0) | 2023.01.17 |
| TIL (0) | 2023.01.09 |
| TIL (0) | 2023.01.03 |
| TIL (0) | 2022.12.31 |