Bun, Express, TypeScript 환경에서 API를 개발할 때, 요청 헤더의 범위 설정이 잘못되어 오류가 발생할 수 있습니다. 이 경우 416 상태 코드 응답이 반환됩니다. 에러 핸들링 미들웨어를 사용해도 에러를 잡지 못하는 상황이 발생할 수 있는데 그 이유와 해결 방법을 알아보았습니다.
문제: Express 4.x에서 Rejected Promise
문제의 핵심은 Express 4.x가 미들웨어나 에러 핸들러를 통해 rejected promises를 처리하지 않는다는 점입니다. 즉, 함수가 rejected promise를 반환할 때 미들웨어가 이를 잡지 못합니다. 대신, 이를 명시적으로 catch 블록을 사용하여 처리해야 하지만, 이는 코드를 더욱 더럽게..(?) 만듭니다.
예시
const rejectedPromise = new Promise((resolve, reject) => {
console.log(`Rejected!`)
reject()
})
await rejectedPromise.then() //여기서 catch를 해주지 않으면 에러 핸들러를 적용해도 오류가 발생
그렇다고 일일히 catch를 쓸 수도 없는 노릇이고..
해결 방법
이 문제를 해결하는 두 가지 방법이 있습니다:
- express-async-errors 라이브러리 사용
express-async-errors 라이브러리를 사용하면 Express가 자동으로 rejected promises를 잡을 수 있습니다. 이 라이브러리를 통합하면 모든 promise에 catch 블록을 추가할 필요가 없습니다. - 엔트리 포인트에서 unhandledRejection 처리
애플리케이션의 엔트리 포인트에서 unhandledRejection 이벤트를 수신하여 전역적으로 처리되지 않은 promise rejection을 기록하고 처리할 수 있습니다.
1. express-async-errors 사용
express-async-errors 라이브러리는 Express 앱에서 비동기 오류를 처리하는 과정을 훨씬 간단하게 만듭니다. 통합 방법은 다음과 같습니다:
npm install express-async-errors
적용
메인 애플리케이션 파일(e.g., app.ts 또는 index.ts)의 맨 처음에 express-async-errors 패키지를 import합니다:
import 'express-async-errors';
import express from 'express';
import { json, urlencoded } from 'body-parser';
const app = express();
app.use(json());
app.use(urlencoded({ extended: true }));
// 여기서 라우트를 정의합니다
// 오류 처리 미들웨어
app.use((err, req, res, next) => {
console.error(err.stack);
res.status(500).send('Something broke!');
});
app.listen(3000, () => {
console.log('Server is running on port 3000');
});
이 설정을 통해 라우트에서 발생하는 모든 rejected promises가 자동으로 오류 처리 미들웨어에 의해 잡힙니다.
2. entrypoint에 'unhandledRejection' 처리
또 다른 방법은 전역적으로 처리되지 않은 promise rejection을 처리하는 것입니다. 이는 엔트리 포인트 파일에 unhandledRejection 이벤트 리스너를 추가하여 수행할 수 있습니다:
process.on('unhandledRejection', (reason: string, p: Promise<any>) => {
console.error(`Unhandled Rejection at: ${p}, reason: ${reason}`)
})
이 방법을 사용하면 처리되지 않은 rejection의 세부 정보를 기록하고 이를 전역적으로 처리할 수 있어 애플리케이션이 예기치 않게 종료 되는것을 것을 방지할 수 있습니다. 따라서 express-async-errors 사용한다고 하더라도 같이 사용하는것을 추천합니다.
결론
Express 4.x에서 rejected promises를 효과적으로 처리하는 것은 어려울 수 있습니다. 그러나 express-async-errors 라이브러리를 사용하거나 전역적으로 unhandledRejection 핸들러를 추가하면 애플리케이션의 안정성을 높일 수 있습니다.
요약하면:
- express-async-errors 사용: 이 라이브러리는 Express 미들웨어에서 rejected promises를 쉽게 잡을 수 있도록 해줍니다.
- 전역적으로 unhandledRejection 처리: 엔트리 포인트에 이벤트 리스너를 추가하여 애플리케이션 전체에서 처리되지 않은 promise rejection을 관리할 수 있습니다.
둘 다 사용을 추천합니다.
express 5 beta 버전:
https://expressjs.com/en/guide/migrating-5.html#rejected-promises
express-async-errors
https://www.npmjs.com/package/express-async-errors
express promise error
https://velog.io/@younoah/nodejs-express-error
Catching Unhandled Promise Rejections and uncaughtException in Node.js
'에러노트' 카테고리의 다른 글
(AWS EC2)Linux Bun/Sudo Bun 실행 “command not found” 에러 (0) | 2024.07.15 |
---|