Express Error Handling

하람·2024년 9월 26일

Express 서버

목록 보기
6/7

에러처리를 깔끔하게 하기

CustomError

커스텀 에러를 정의한다.

// src\lib\error\customError.ts
import { TErrorCode } from "./errorCode";

class CustomError extends Error {
  statusCode: number;
  errorCode: number;

  constructor(errorCode: TErrorCode) {
    super(errorCode.message);
    this.errorCode = errorCode.code;
    this.statusCode = errorCode.statusCode;

    // Maintaining the prototype chain when extending built-ins like Error
    Object.setPrototypeOf(this, CustomError.prototype);
  }
}

export { CustomError };


//---------------------------------------------
// src\lib\error\errorCode.ts
import HttpStatusCodes from "../../common/HttpStatusCodes";

export type TErrorCode = {
  code: number;
  statusCode: number;
  message: string;
};

// Error Codes
const ErrorCode: { [key: string]: TErrorCode } = {
  PRISMA_INTERNAL_SERVER_ERROR: {
    code: 1001,
    statusCode: HttpStatusCodes.INTERNAL_SERVER_ERROR, // 500
    message: "internal server error: prisma DB error",
  },
};

export default ErrorCode;

에러코드를 한 곳에 정의해놓고 다른곳에서 참조해 사용한다.
이렇게 에러코드와 메시지를 미리 정의해놓으면 유지보수할 때 편하다.

ErrorHandler

// src\lib\middlewares\errorHandler.ts
import { Request, Response, NextFunction } from "express";
import HttpStatusCodes from "../../common/HttpStatusCodes";
import { logError } from "./logger";

const errorHandlerMiddleware = (
  err: any,
  req: Request,
  res: Response,
  next: NextFunction
) => {
  const error = {
    // 에러가 발생했지만, 기본적인 에러 코드나 에러 메세지가 존재하지 않을 경우를 대비한 default 에러 코드 및 에러 메세지
    statusCode: err.statusCode || HttpStatusCodes.INTERNAL_SERVER_ERROR, // 500
    errorCode: err.errorCode || 0,
    message: err.message || "unknown error accrued",
  };

  logError(`(${error.errorCode}) ${error.message}`);

  return res
    .status(error.statusCode)
    .json({ message: error.message, errorCode: error.errorCode });
};

export default errorHandlerMiddleware;

콘솔에 뜨는 결과

async wrapper

// src\lib\middlewares\async.ts
import { Request, Response, NextFunction } from "express";

const asyncWrapper = (
  fn: (req: Request, res: Response, next: NextFunction) => Promise<void>
) => {
  return async (
    req: Request,
    res: Response,
    next: NextFunction
  ): Promise<void> => {
    try {
      await fn(req, res, next);
    } catch (error) {
      next(error);
    }
  };
};

export { asyncWrapper };

예제

// src\app.ts
app.get("/", (req: Request, res: Response) => {
  throw new CustomError(ErrorCode.PRISMA_INTERNAL_SERVER_ERROR);
});

// error handler, must be after routers
app.use(errorHandler);

참고

profile
강하고 담대하라 두려워하지 말라

0개의 댓글