Exception filters
Last updated
Last updated
Nest에는 애플리케이션에서 처리되지 않은 모든 예외를 처리하는 내장 예외 레이어가 제공됩니다. 응용 프로그램 코드에서 예외를 처리하지 않으면이 계층에서 예외를 포착하여 적절한 사용자 친화적인 응답을 자동으로 보냅니다.
기본적으로 이 동작은 내장 된 전역 예외 필터에 의해 수행되는데, 이 예외는 HttpException
유형 (및 그 하위 클래스)의 예외를 처리합니다. 예외가 unrecognized 인 경우 ( HttpException
또는 HttpException
에서 상속되는 클래스가 아님) 클라이언트는 다음과 같은 기본 JSON 응답을받습니다.
내장 된 HttpException
클래스는 @nestjs/common
패키지에서 공개됩니다.
CatsController
에는 findAll()
메소드 (GET
경로 핸들러)가 있습니다. 어떤 이유로 이 라우트 핸들러에서 예외가 발생한다고 가정해 봅시다. 이를 설명하기 위해 다음과 같이 하드 코딩합니다.
info 힌트 여기서는
HttpStatus
를 사용했습니다. 이것은@nestjs/common
패키지에서 가져온 헬퍼 열거형입니다.
클라이언트가 이 엔드 포인트를 호출하면 응답은 다음과 같습니다.
HttpException
생성자는 응답을 결정하는 두 가지 필수 인수를 사용합니다.
response
인수는 JSON 응답 본문을 정의합니다. 아래에 설명 된대로 문자열
또는 객체
일 수 있습니다.
status
인수는 HTTP 상태 코드를 정의합니다.
기본적으로 JSON 응답 본문에는 두 가지 속성이 있습니다.
statusCode
: status
인수에 제공된 HTTP 상태 코드로 기본 설정
message
: 상태
에 기반한 HTTP 에러에 대한 간단한 설명
JSON 응답 본문의 메시지 부분 만 재정의하려면 response
인수에 문자열을 제공하십시오.
전체 JSON 응답 본문을 재정의하려면 response
인수에 객체를 전달하십시오. Nest는 객체를 직렬화하여 JSON 응답 본문으로 반환합니다.
두 번째 생성자 인자 status
는 유효한 HTTP 상태 코드 여야합니다. 모범 사례는@nestjs/common
에서 가져온 HttpStatus
열거 형을 사용하는 것입니다.
다음은 전체 응답 본문을 재정의 하는 예입니다.
위의 방법을 사용하면 다음과 같이 응답이 나타납니다.
예외 계층 구조를 직접 만드는 것이 좋습니다. 이것은 사용자 정의 HTTP 예외가 기본 HttpException
클래스에서 상속되어야 함을 의미합니다. 결과적으로 Nest는 예외를 인식하고 자동으로 오류 응답을 처리합니다. 그러한 커스텀 예외를 구현해 봅시다 :
ForbiddenException
은 기본 HttpException
을 확장하므로 내장 예외 핸들러와 완벽하게 작동하므로 findAll()
메소드 내에서 사용할 수 있습니다.
상용구 코드를 작성할 필요성을 줄이기 위해 Nest는 코어 HttpException
에서 상속되는 사용 가능한 예외 세트를 제공합니다. 이들 모두는 @nestjs/common
패키지에서 공개됩니다:
BadRequestException
UnauthorizedException
NotFoundException
ForbiddenException
NotAcceptableException
RequestTimeoutException
ConflictException
GoneException
PayloadTooLargeException
UnsupportedMediaTypeException
UnprocessableEntityException
InternalServerErrorException
NotImplementedException
BadGatewayException
ServiceUnavailableException
GatewayTimeoutException
기본 (내장) 예외 필터가 많은 경우를 자동으로 처리 할 수 있지만 예외 레이어를 완전히 제어 할 수 있습니다. 예를 들어, 일부 동적 요인에 따라 로깅을 추가하거나 다른 JSON 스키마를 사용할 수 있습니다. 예외 필터는 이 목적을 위해 설계되었습니다.
HttpException
클래스의 인스턴스인 예외를 포착하고 이에 대한 사용자 정의 응답 로직을 구현하는 예외 필터를 작성해 봅시다.
info 힌트 모든 예외 필터는 일반
ExceptionFilter <T>
인터페이스를 구현해야 합니다. 이를 위해서는catch (exception: T, host: ArgumentsHost)
메소드에 표시된 서명을 제공해야 합니다.T
는 예외 유형을 나타냅니다.
@Catch (HttpException)
데코레이터는 필요한 메타 데이터를 예외 필터에 바인딩하여 이 특정 필터가 HttpException
유형의 예외를 찾고 있음을 Nest에게 알려줍니다. @Catch()
데코레이터는 단일 매개 변수 또는 쉼표로 구분된 목록을 사용할 수 있습니다. 이를 통해 여러 유형의 예외에 대한 필터를 한 번에 설정할 수 있습니다.
catch()
메소드의 매개 변수를 보자. exception
매개 변수는 현재 처리중인 예외 객체입니다. host
매개 변수는 ArgumentsHost
객체입니다. ArgumentsHost
는 original 요청 핸들러 (예외가 발생한 곳)에 전달된 인수를 감싸는 래퍼입니다. 여기에는 응용 프로그램 및 사용중인 플랫폼의 유형에 따라 특정 인수 배열이 포함됩니다. 다음은 ArgumentsHost
의 모습입니다 :
ArgumentsHost
는 다양한 애플리케이션 컨텍스트에서 기본 배열에서 올바른 인수를 선택하는 데 도움이 되는 편리한 메소드 세트를 제공합니다. 다시 말해, ArgumentsHost
는 인자 배열에 지나지 않습니다. 예를 들어, HTTP 애플리케이션 컨텍스트 내에서 필터를 사용하면 ArgumentsHost
에 [request, response]
배열이 포함됩니다. 그러나 현재 컨텍스트가 웹 소켓 애플리케이션인 경우 해당 컨텍스트에 적합한 [client, data]
배열이 포함됩니다. 이 방법을 사용하면 사용자 정의 catch()
메소드에서 원래 핸들러로 전달되는 인수에 액세스 할 수 있습니다.
새로운 HttpExceptionFilter
를 CatsController
의 create()
메소드에 묶어 봅시다.
info 힌트
@UseFilters()
데코레이터는@nestjs/common
패키지에서 가져옵니다.
우리는@UseFilters()
데코레이터를 사용했습니다. @Catch()
데코레이터와 유사하게 단일 필터 인스턴스 또는 쉼표로 구분된 필터 인스턴스 목록을 사용할 수 있습니다. 여기서는 HttpExceptionFilter
인스턴스를 작성했습니다. 또는 인스턴스 대신 클래스를 전달하여 프레임 워크에 인스턴스화에 대한 책임을 남기고 종속 주입을 활성화 할 수 있습니다.
info 힌트 가능한 경우 인스턴스 대신 클래스를 사용하여 필터를 적용하는 것이 좋습니다. Nest가 전체 모듈에서 동일한 클래스의 인스턴스를 쉽게 재사용할 수 있으므로 메모리 사용량이 줄어 듭니다.
위의 예에서 HttpExceptionFilter
는 단일 create()
라우트 핸들러에만 적용되어 메소드 범위가 됩니다. 예외 필터는 메소드 범위, 컨트롤러 범위 또는 전역 범위의 다른 수준으로 범위를 지정할 수 있습니다. 예를 들어, 필터를 컨트롤러 범위로 설정하려면 다음을 수행하십시오.
이 구조는 CatsController
안에 정의된 모든 경로 핸들러에 대해 HttpExceptionFilter
를 설정합니다.
전역 범위 필터를 만들려면 다음을 수행하십시오.
warning 경고
useGlobalFilters ()
메소드는 게이트웨이 또는 하이브리드 애플리케이션에 대한 필터를 설정하지 않습니다.
전역 범위 필터는 모든 컨트롤러와 모든 경로 처리기에 대해 전체 응용 프로그램에서 사용됩니다. 의존성 주입의 관점에서, 모듈 외부에서 등록 된 전역 필터 (위의 예에서와 같이useGlobalFilters()
로)는 모듈의 컨텍스트 외부에서 수행되기 때문에 의존성을 주입할 수 없습니다. 이 문제를 해결하기 위해 다음 구성을 사용하여 모든 모듈에서 직접 전역 필터를 등록 할 수 있습니다.
info 힌트 이 접근 방식을 사용하여 필터에 대한 의존성 주입을 수행할 때 이 구성이 사용되는 모듈에 관계없이 필터는 실제로 전역적입니다. 어디에서 해야 합니까? 필터 (위 예에서
HttpExceptionFilter
)가 정의 된 모듈을 선택하십시오. 또한 커스텀 프로 바이더 등록을 다루는 유일한 방법은useClass
가 아닙니다. 여기에 대해 자세히 알아보십시오.
이 기술을 사용하여 필요한만큼 필터를 추가 할 수 있습니다. 간단히 공급자 배열에 각각을 추가하십시오.
처리되지 않은 예외 (예외 유형에 관계없이)를 모두 잡으려면 @Catch()
데코레이터의 매개 변수 목록을 비워 두십시오 (예: @Catch()
).
위의 예에서 필터는 유형 (클래스)에 관계없이 발생 된 각 예외를 포착합니다.
일반적으로 응용 프로그램 요구 사항을 충족하도록 제작된 완전히 사용자 지정된 예외 필터를 만듭니다. 그러나 내장된 기본 전역 예외 필터를 단순히 확장하고 특정 요인에 따라 동작을 재 정의하려는 경우 사용 사례가 있을 수 있습니다.
예외 처리를 기본 필터에 위임하려면 BaseExceptionFilter
를 확장하고 상속 된 catch()
메소드를 호출해야합니다.
warning 경고
BaseExceptionFilter
를 확장하는 메서드 범위 및 컨트롤러 범위 필터는new
로 인스턴스화하면 안됩니다. 대신 프레임 워크에서 자동으로 인스턴스화하십시오.
위의 구현은 접근 방식을 보여주는 쉘일뿐입니다. 확장 예외 필터 구현에는 맞춤형 비즈니스 논리 (예: 다양한 조건 처리)가 포함됩니다.
전역 필터 는 기본 필터를 확장 할 수 있습니다. 이것은 두 가지 방법 중 하나로 수행 할 수 있습니다.
첫 번째 방법은 커스텀 글로벌 필터를 인스턴스화 할 때 HttpServer
참조를 삽입하는 것입니다.
두 번째 방법은 여기에 표시된 APP_FILTER
토큰을 사용하는 것입니다.