에러노트

Express 4.x에서 express-async-errors로 Rejected Promise 처리하기

JohnnyDeveloper 2024. 6. 25. 15:35

 

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를 쓸 수도 없는 노릇이고..

해결 방법

이 문제를 해결하는 두 가지 방법이 있습니다:

  1. express-async-errors 라이브러리 사용
    express-async-errors 라이브러리를 사용하면 Express가 자동으로 rejected promises를 잡을 수 있습니다. 이 라이브러리를 통합하면 모든 promise에 catch 블록을 추가할 필요가 없습니다.
  2. 엔트리 포인트에서 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-async-errors

Async/await error handling support for expressjs. Latest version: 3.1.1, last published: 6 years ago. Start using express-async-errors in your project by running `npm i express-async-errors`. There are 491 other projects in the npm registry using express-a

www.npmjs.com

 

express promise error

https://velog.io/@younoah/nodejs-express-error

 

express의 동기와 비동기 에러처리

express에서 동기와 비동기 에러처리에 대해 알아보자.

velog.io

 

Catching Unhandled Promise Rejections and uncaughtException in Node.js

https://dev.to/superiqbal7/catching-unhandled-promise-rejections-and-uncaughtexception-in-nodejs-2403