매일 업데이트
2023-10-17 11:45 7 min

Nest.js 예외 필터를 사용하여 오류를 처리하는 방법

Nest.js에서 예외 필터는 애플리케이션 내에서 발생하는 오류를 효과적으로 관리하는 핵심적인 도구입니다. 이러한 필터는 전역 또는 컨트롤러 수준에서 예외를 감지하고 처리하여 오류 처리 로직을 한 곳에 모으고, 오류 응답 형식을 일관되게 유지하며, 애플리케이션 전체에 걸쳐 통일된 오류 처리 경험을 제공합니다. 지금부터 예외 필터에 대한 심층적인 이해를 바탕으로, 애플리케이션에서 발생할 수 있는 다양한 오류들을 어떻게 효과적으로 처리할 수 있는지 살펴보겠습니다.

Nest.js의 기본 오류 처리 메커니즘

Nest.js는 기본적으로 애플리케이션 코드에서 명시적으로 처리하지 않은 모든 예외를 포착하고 처리하는 오류 처리 레이어를 제공합니다. 이는 개발자가 예기치 않은 오류를 놓치더라도, Nest.js가 자동으로 오류를 처리하여 애플리케이션의 안정성을 유지하는 데 도움을 줍니다.

만약 애플리케이션 내에서 처리되지 않은 오류가 발생하면, Nest.js는 이 오류를 포착하고 클라이언트에게 500 내부 서버 오류를 반환합니다. 이때 Nest.js가 반환하는 JSON 형식의 응답은 다음과 같습니다.

{
  "statusCode": 500,
  "message": "Internal server error"
}

만약 코드에서 발생하는 오류 객체에 'statusCode'와 'message' 속성이 포함되어 있다면, Nest.js는 기본 응답 대신 해당 값을 사용하여 클라이언트에게 더 구체적인 정보를 제공합니다.

그러나 이러한 일반적인 동작만으로는 클라이언트에게 충분한 정보를 제공하지 못할 수 있습니다. 따라서 애플리케이션에서 발생할 수 있는 모든 오류를 세심하게 처리하여 클라이언트에게 더욱 유익하고 정확한 오류 응답을 제공하는 것이 중요합니다. 이를 위해 Nest.js는 내장 예외 필터와 사용자 정의 예외 필터를 모두 지원합니다.

사용자 정의 예외 필터 구현

이제 사용자 정의 예외 필터를 만드는 과정을 단계별로 살펴보겠습니다. 여기서는 모든 HTTP 예외를 처리할 수 있는 필터를 만들 것입니다.

먼저 'http.exception.ts' 파일을 만들고, 필요한 모듈들을 가져옵니다.

import {
  ExceptionFilter,
  Catch,
  ArgumentsHost,
  HttpException,
} from '@nestjs/common';
import { Request, Response } from 'express';

각 모듈의 역할은 다음과 같습니다.

  • ExceptionFilter: 예외 필터가 구현해야 하는 인터페이스를 정의합니다.
  • Catch: 클래스를 Nest.js의 예외 필터로 지정하는 데코레이터입니다.
  • ArgumentsHost: 핸들러에 전달된 인수를 검색하는 데 사용되는 인터페이스입니다. 이를 통해 HTTP, RPC, WebSocket 등 다양한 실행 컨텍스트에서 인수를 검색할 수 있습니다.
  • HttpException: 기본적인 Nest.js HTTP 예외를 정의하는 클래스입니다.
  • Request, Response: 각각 Express.js의 요청 및 응답 객체에 대한 인터페이스입니다.

다음으로, ExceptionFilter 인터페이스를 구현하는 HttpExceptionFilter 클래스를 만들고, HttpException을 처리하도록 Catch 데코레이터로 지정합니다.

@Catch(HttpException)
export class HttpExceptionFilter implements ExceptionFilter {}

이제 catch 메서드를 구현하여 예외를 처리합니다.

catch(exception: HttpException, host: ArgumentsHost) {
  const ctx = host.switchToHttp();
  const response = ctx.getResponse<Response>();
  const request = ctx.getRequest<Request>();
  const status = exception.getStatus();
  response.status(status).json({
    statusCode: status,
    timestamp: new Date().toISOString(),
    path: request.url,
    message:
      exception.message ||
      exception.getResponse()['message'] ||
      'Internal Server Error',
  });
}

이 코드는 ArgumentsHost 객체에서 요청 및 응답 객체를 가져오고, 예외에서 필요한 정보를 추출하여 구조화된 JSON 형태의 오류 응답을 클라이언트에게 반환합니다. 이 응답에는 오류 상태 코드, 발생 시간, 요청 경로, 오류 메시지 등이 포함되어 있습니다.

예외 필터 바인딩

사용자 정의 예외 필터를 생성했으면, 컨트롤러 또는 애플리케이션 전역에 필터를 바인딩해야 합니다. 필터의 바인딩 위치에 따라 오류 처리 범위가 결정됩니다.

전역적으로 예외 필터를 바인딩하려면 'main.ts' 파일에서 예외 필터를 가져온 다음, app.useGlobalFilters 메서드에 필터 인스턴스를 전달합니다.

import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { HttpExceptionFilter } from './exception/http.exception';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  app.useGlobalFilters(new HttpExceptionFilter());
  await app.listen(4050);
}

bootstrap();

특정 컨트롤러에만 필터를 바인딩하려면, @UseFilters 데코레이터를 사용하여 컨트롤러 클래스를 장식하고, 예외 필터 인스턴스를 인자로 전달합니다.

@Controller()
@UseFilters(new HttpExceptionFilter())
export class AppController {}

컨트롤러에 바인딩된 필터는 해당 컨트롤러 내에서만 적용되며, 전역 필터는 애플리케이션 전체에 적용됩니다.

내장 예외 클래스를 이용한 오류 발생

Nest.js는 다양한 종류의 오류를 발생시킬 수 있는 내장 예외 클래스를 제공합니다. 이러한 클래스를 활용하면 오류 처리를 더욱 명확하고 효율적으로 수행할 수 있습니다.

예를 들어, NotFoundException 클래스를 사용하여 404 상태 코드의 오류를 발생시킬 수 있습니다.

getUserById(id: number) {
  const user = users.find((user) => user.id === id);
  if (!user) {
    throw new NotFoundException({
      message: `User with id ${id} not found`,
    });
  }
}

위 코드는 특정 ID의 사용자를 검색하고, 해당 사용자가 존재하지 않으면 NotFoundException을 발생시켜 404 오류를 클라이언트에게 알립니다.

자주 사용되는 내장 예외 클래스

Nest.js에서 제공하는 주요 내장 예외 클래스는 다음과 같습니다.

  • BadRequestException: 클라이언트 요청이 유효하지 않거나 형식이 잘못된 경우, 상태 코드 400 오류를 발생시킵니다.
  • UnauthorizedException: 사용자가 인증되지 않았거나 리소스에 접근할 권한이 없는 경우, 상태 코드 401 오류를 발생시킵니다.
  • ForbiddenException: 사용자가 인증되었지만 특정 작업을 수행할 권한이 없는 경우, 상태 코드 403 오류를 발생시킵니다.
  • RequestTimeoutException: 요청 처리 시간이 초과된 경우, 상태 코드 408 오류를 발생시킵니다.
  • ConflictException: 클라이언트 요청이 리소스의 현재 상태와 충돌하는 경우, 상태 코드 409 오류를 발생시킵니다.
  • InternalServerErrorException: 서버 내부에서 예기치 않은 오류가 발생한 경우, 상태 코드 500 오류를 발생시킵니다.

Nest.js 오류 처리 모범 사례

Nest.js에서 효과적인 오류 처리를 위해서는 다음 모범 사례들을 따르는 것이 좋습니다.

예외 필터를 사용하여 예외를 포착하고 처리하며, 전역 또는 컨트롤러 수준에서 필터를 바인딩하여 오류 처리 범위를 설정합니다. 또한, 특정 예외 유형에 대한 사용자 정의 필터를 생성하여 더욱 세분화된 오류 처리를 구현할 수 있습니다.

적절한 내장 예외 클래스를 활용하여 의미 있는 오류를 발생시키고, 클라이언트에게 정확한 오류 정보를 제공하는 것이 중요합니다. 이러한 실천은 Nest.js 애플리케이션의 안정성과 사용자 경험을 향상시키는 데 크게 기여할 수 있습니다.

저자
Korea

기술 트렌드와 실용적인 팁을 전하는 लेखक입니다.