Express에서 비동기 오류 처리하기: 안전하고 효율적인 방법
Express에서 비동기 오류를 처리하는 것은 중요하며, 적절한 방식으로 처리하지 않으면 오류가 누락되거나 서버가 멈출 수 있습니다. 아래는 Express에서 비동기 오류를 처리하는 방법과 원리를 자세히 설명합니다.
1. 비동기 코드에서 오류가 발생하는 이유
Express는 기본적으로 동기적인 미들웨어와 라우트 핸들러에서 발생하는 오류를 처리하도록 설계되었습니다. 하지만 비동기 코드(예: async/await 또는 Promise)에서 발생한 오류는 기본적인 try-catch 없이 자동으로 Express의 오류 처리 미들웨어로 전달되지 않습니다.
2. 전통적인 방법: try-catch 사용
비동기 핸들러에서 try-catch를 사용하여 오류를 잡고, next()를 호출해 Express의 오류 처리 미들웨어로 전달할 수 있습니다.
const express = require('express');
const app = express();
app.get('/async-route', async (req, res, next) => {
try {
const result = await someAsyncFunction();
res.json(result);
} catch (err) {
next(err); // 오류를 Express의 오류 처리 미들웨어로 전달
}
});
// 오류 처리 미들웨어
app.use((err, req, res, next) => {
console.error(err.stack);
res.status(500).json({ error: 'Something went wrong!' });
});
app.listen(3000, () => console.log('Server running on port 3000'));
3. 반복적인 try-catch를 줄이는 방법
(1) 비동기 유틸리티 함수 작성
공통적인 패턴을 줄이기 위해 비동기 핸들러를 감싸는 유틸리티 함수를 사용할 수 있습니다.
const asyncHandler = (fn) => (req, res, next) => {
Promise.resolve(fn(req, res, next)).catch(next);
};
// 사용 예시
app.get('/async-route', asyncHandler(async (req, res) => {
const result = await someAsyncFunction();
res.json(result);
}));
이 방식은 중복되는 try-catch를 제거하고, 가독성을 높여줍니다.
(2) 외부 라이브러리 활용
express-async-errors 라이브러리는 비동기 핸들러에서 발생한 오류를 자동으로 Express의 오류 처리 미들웨어로 전달합니다.
설치
npm install express-async-errors
사용법
require('express-async-errors');
const express = require('express');
const app = express();
app.get('/async-route', async (req, res) => {
const result = await someAsyncFunction();
res.json(result);
});
// 오류 처리 미들웨어
app.use((err, req, res, next) => {
console.error(err.stack);
res.status(500).json({ error: 'Something went wrong!' });
});
app.listen(3000, () => console.log('Server running on port 3000'));
express-async-errors를 사용하면 추가적인 코드 없이 비동기 오류를 처리할 수 있습니다.
4. 오류 처리 미들웨어
Express에서 오류 처리 미들웨어는 반드시 네 가지 인자를 가져야 합니다.
app.use((err, req, res, next) => {
console.error(err.stack); // 로그 출력
res.status(err.status || 500).json({ error: err.message || 'Internal Server Error' });
});
주요 특징
err객체는 비동기 핸들러에서next(err)로 전달된 오류를 포함합니다.status속성이 정의된 경우, 이를 사용하여 상태 코드를 설정합니다.
5. 전역 처리
Express에서 처리되지 않은 모든 오류를 마지막으로 처리하려면 전역 오류 처리기를 정의해야 합니다.
예제
process.on('unhandledRejection', (reason, promise) => {
console.error('Unhandled Rejection:', reason);
// 로그 기록 또는 알림 전송 등
});
process.on('uncaughtException', (err) => {
console.error('Uncaught Exception:', err);
// 로그 기록 또는 서버 종료 등
process.exit(1); // 필요에 따라 프로세스 종료
});
6. Best Practices
- 가능한 경우
asyncHandler또는express-async-errors와 같은 도구를 사용하여 오류 처리를 단순화합니다. - 공통적인 오류 형식을 정의하고, 클라이언트에 의미 있는 응답을 반환하도록 합니다.
- 로그와 모니터링 시스템을 통해 오류를 추적하고 분석합니다.
위의 방법을 사용하면 Express 애플리케이션에서 비동기 코드의 오류를 안전하고 효과적으로 처리할 수 있습니다.
Leave a comment