에러처리를 깔끔하게 하기
커스텀 에러를 정의한다.
// 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;
에러코드를 한 곳에 정의해놓고 다른곳에서 참조해 사용한다.
이렇게 에러코드와 메시지를 미리 정의해놓으면 유지보수할 때 편하다.
// 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;
콘솔에 뜨는 결과

// 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);
참고