최근에, Nest.js 프레임워크 없이 Express만 사용하여 서버를 구성할 일이 있었습니다.
Express에는 Nest.js와 달리, 미리 구현되어 있는 예외 처리 계층이 적었기에, 본 포스팅에서는 관련한 기록을 남겨 두고자 합니다!
Express에서 Error handler 추가하여 try, catch 생략하기!
Express.js Error Handling
우선 가장 기본적인 예외 처리 middleware로, app.ts에 아래와 같은 함수를 추가해 보았습니다.
[ handle.exception.ts ]
import { NextFunction, Request, Response } from "express";
export function handleExceptions(err: Error, req: Request, res: Response, next: NextFunction) {
const statusCode = err?.status || 500;
const msg = err?.message || "Unexpected Exception";
return res.statsus(statusCode).json({
status: statusCode,
message:msg
});
}
[ app.ts ]
const app = express();
...
...
app.use(handleExceptions);
해당 예외 처리는, 아래와 같은 구성의 비동기 메서드에서 발생한 예외를 잡지 못하는 문제가 있었습니다ㅠ
[ sample.routes.ts ]
const router = express.Router();
router.get("/", controller.getSamples.bind(controller));
[ sample.controller.ts ]
export class SampleController {
public async getSamples() {
throw new Error("비동기 함수에서의 에러");
}
}
실행하면, 예외 응답을 반환하지 못하고 아래와 같이 앱이 crash되었습니다..

route에 연결되는 Controller의 메서드를 감싸 줄, wrapper 함수를 작성합니다.
import { NextFunction, Request, RequestHandler, Response } from "express";
import * as core from "express-serve-static-core";
export function handleAsyncException<
T extends core.ParamsDictionary = core.ParamsDictionary,
R = any,
U extends qs.ParsedQs = qs.ParsedQs,
>(fn: RequestHandler<T, any, R, U>) {
return (req: Request<T, any, R, U>, res: Response, next: NextFunction) => {
// catch 문으로 예외를 잡아주기!
Promise.resolve(fn(req, res, next)).catch(next);
};
}
[ sample.routes.ts ]
const router = express.Router();
router.get("/", handleAsyncException(controller.getSamples.bind(controller)));

앱이 crash되지 않고, 의도한 statusCode와 응답을 반환하는 부분까지 확인할 수 있었습니다!