[Express] Express에서의 비동기 예외 처리

toto9602·2024년 6월 30일

최근에, Nest.js 프레임워크 없이 Express만 사용하여 서버를 구성할 일이 있었습니다.
Express에는 Nest.js와 달리, 미리 구현되어 있는 예외 처리 계층이 적었기에, 본 포스팅에서는 관련한 기록을 남겨 두고자 합니다!

참고 자료

Express에서 Error handler 추가하여 try, catch 생략하기!
Express.js Error Handling

  • 소스 코드는 typescript로 작성하였습니다!
  • 잘못된 내용에 대한 피드백은 언제든 감사드립니다! (_ _)

0. 기본적인 예외 처리 middleware

우선 가장 기본적인 예외 처리 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);

1. 한계

해당 예외 처리는, 아래와 같은 구성의 비동기 메서드에서 발생한 예외를 잡지 못하는 문제가 있었습니다ㅠ
[ 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되었습니다..

2. 해결

2-1. 비동기 메서드에 대한 Wrapper 함수

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);
  };
}

2-2. Wrapper 함수의 적용

[ sample.routes.ts ]

const router = express.Router();

router.get("/", handleAsyncException(controller.getSamples.bind(controller)));

2-3. 예외 처리 middleware 동작 확인

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

profile
주니어 백엔드 개발자입니다! 조용한 시간에 읽고 쓰는 것을 좋아합니다 :)

0개의 댓글