안녕하세요 오늘은 Nest.js에서 전역으로 에러 처리하기라는 주제로 글을 작성해보도록 하겠습니다.
기존에 많이 사용했던 Express.js에서는 일일히 try / catch를 걸어주면서 검증 오류인지, 서버 오류인지를 판단하는 과정이 있었는데, Nest.js를 이용하면 해당 과정을 편리하게 작업할 수 있어서 적어봅니다.
가장 먼저 에러 관련 파일들을 생성하겠습니다. 저는 src/exception 폴더 경로에 HttpError.ts라는 파일을 만든 다음, 에러를 던져주는 클래스를 만들어 주도록 하겠습니다. 에러를 던져주는 형식은 아래와 같습니다.
throw new HttpError(404, '존재하지 않는 사용자')
해당 클래스는 원래 nestjs/common에서 제공하는 HttpException 클래스를 사용하여 던져도 되지만, 저는 HttpException 클래스를 상속받아서 제가 원하는 방식으로 바꿔주었습니다.
(사실 별 차이는 없습니다 😀)
// HttpError.ts
import { HttpException } from "@nestjs/common";
export default class HttpError extends HttpException {
public statusCode: number = 0;
public message: string = '';
constructor(status: number, message: string) {
super(message, status);
this.statusCode = status;
this.message = message;
}
}
이제 throw new HttpError(404, '존재하지 않는 사용자')
와 같은 형식으로 에러를 생성하는것이 가능해졌습니다.
두번째로, CatchException.ts라는 파일을 만들어준 다음, 아래의 코드를 추가하였습니다.
해당 클래스는 전역으로 에러 필터를 걸어줄 때 필요로 하는 클래스이므로, 중요합니다.
// CatchException.ts
import { ArgumentsHost, Catch, ExceptionFilter, HttpException } from "@nestjs/common";
import { HttpArgumentsHost } from "@nestjs/common/interfaces";
@Catch()
export default class CatchException implements ExceptionFilter {
// ExceptionFilter 인터페이스를 구현해야 하는 함수
catch(exception: HttpException, host: ArgumentsHost) {
const ctx: HttpArgumentsHost = host.switchToHttp();
const response = ctx.getResponse();
let httpError = null;
console.log(exception);
if (exception instanceof HttpException) {
// status: XXX, message: 'XXX' 형식의 에러인지 판단합니다.
httpError = {
status: exception.getStatus(), // throw new HttpError()로 던진 첫번째 매개변수 status 값
message: exception.message, // throw new HttpError()로 던진 두번째 매개변수 message 값
};
}
else {
// XXXX() is not a function와 같은 서버 자체에서의 오류일때, 서버 오류로 처리합니다.
httpError = {
status: 500,
message: '서버 오류입니다.',
};
}
const { status, message } = httpError;
// 클라이언트에게 응답을 넘겨줍니다. (위 조건분기에 따른 객체의 값들)
return response.status(status).json({
status,
message,
});
}
}
에러 클래스도 만들어 주었으니 이제 클래스를 전역 에러처리에 넣어주도록 하겠습니다. app.module.ts 파일을 열어준다음, providers 객체를 아래의 코드처럼 수정해줍니다.
import { APP_FILTER } from '@nestjs/core';
import CatchException from 'exception/CatchException';
// app.module.ts
@Module({
imports: [],
controllers: [],
providers: [{
provide: APP_FILTER,
useClass: CatchException,
}],
})
export class AppModule {}
이제 코드상으로 throw new HttpError() 형식의 오류를 던진다음, 정상적으로 에러가 출력되는지 확인하실 수 있습니다. 저같은 경우에는 자동으로 오류를 처리해주었으니, controller 파일들에서 쓰던
try / catch를 없애줄 수 있었어서 참 편리했던 것 같아요.
오늘은 이상으로 짧게 글을 마치도록 하겠습니다. 궁금한사항이 생기시면 댓글로 남겨주세요! 감사합니다.