๐ŸŽ‰ berenickt ๋ธ”๋กœ๊ทธ์— ์˜จ ๊ฑธ ํ™˜์˜ํ•ฉ๋‹ˆ๋‹ค. ๐ŸŽ‰
Back
NestJs
29-exception-filter

1. Exception Filter ์†Œ๊ฐœ

nestjs-request-life-cycle

  • Exception Filter์—์„œ ์ˆ˜ํ–‰ํ•œ ๋ถ€๋ถ„๋“ค์€ interceptor์—์„œ ์ถ”๊ฐ€ ๋กœ์ง์„ ๋˜ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค.
  • Exception Filter๋Š” ๋ง ๊ทธ๋Œ€๋กœ ์˜ˆ์™ธ๋ฅผ ํ•„ํ„ฐ๋ง ํ•˜๋Š” ๊ธฐ๋Šฅ์ด๋‹ค.
    • NestJS์—์„œ๋Š” ์ž์ฒด์ ์œผ๋กœ ์˜ˆ์™ธ ๋ ˆ์ด์–ด๋ฅผ ๊ด€๋ฆฌํ•œ๋‹ค.
    • ์„œ๋ฒ„์—์„œ ๋ฐœ์ƒํ•œ ์˜ˆ์™ธ๊ฐ€ ๋”ฐ๋กœ ํ•ธ๋“ค๋ง ๋˜์ง€ ์•Š์œผ๋ฉด NestJS ์˜ˆ์™ธ ๋ ˆ์ด์–ด์—์„œ ์—๋Ÿฌ๋ฅผ ์‚ฌ์šฉ์ž ์นœํ™”์ ์œผ๋กœ ๋ณ€ํ™˜ํ•ด์„œ ์‘๋‹ต ํ•  ์ˆ˜ ์žˆ๋‹ค
  • ์‘๋‹ต์„ ๋ณ€ํ˜•ํ•˜๋Š” ๋ถ€๋ถ„์€ ์‚ฌ์‹ค ํฌ๊ฒŒ ์“ธ ์ผ์ด ๋งŽ์ง€๋Š” ์•Š๋‹ค.
  • ์™œ๋ƒ๋ฉด์€ ์˜ˆ์™ธ๋ผ๋Š” ๊ฒƒ ์ž์ฒด๊ฐ€ ์˜ˆ์™ธ๊ฐ€ ๋˜์ ธ์กŒ์„ ๋•Œ,
    • ๋˜์ ธ์ง„ ์˜๋„ ๊ทธ๋Œ€๋กœ ์‚ฌ์šฉ๋˜์–ด์•ผ ํ”„๋ก ํŠธ์—”๋“œ์—์„œ๋„ ์˜๋ฏธ๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋˜๊ฒŒ ๋งŽ๋‹ค.
    • ๊ทธ๋ž˜์„œ ์˜ˆ์™ธ ์ฒ˜๋ฆฌ๋ฅผ ๋งŽ์ด ๋ณ€ํ˜•ํ•˜๋Š” ๊ฒฝ์šฐ๋Š” ํฌ๊ฒŒ ์—†๋‹ค.
  • Exception Filter๊ฐ€ ๋˜๊ฒŒ ์œ ์šฉํ•œ ๊ฒฝ์šฐ
    • ์—๋Ÿฌ๊ฐ€ ์ƒ๊ฒผ์„ ๋•Œ TGS ์„œ๋ฒ„ ๋‚ด๋ถ€์—์„œ ๋กœ๊ทธ๋ฅผ ๋‚จ๊ธฐ๊ฑฐ๋‚˜
    • ์•„๋‹ˆ๋ฉด ๋ชจ๋‹ˆํ„ฐ๋ง ํ•  ์ˆ˜ ์žˆ๋Š” ์‹œ์Šคํ…œํ•œํ…Œ ์•Œ๋ ค์ฃผ๋Š” ๋กœ์ง์„ ์ž‘์„ฑํ•  ๋–„

Filter_1

  • ๊ณต์‹๋ฌธ์„œ : https://docs.nestjs.com/exception-filters
  • ๊ณต์‹๋ฌธ์„œ์˜ ๊ทธ๋ฆผ์„ ๋ณด๋ฉด, ํด๋ผ์ด์–ธํŠธ ์‚ฌ์ด๋“œ์—์„œ ์š”์ฒญ์„ ๋ณด๋‚ด๊ณ ,
    • ์‘๋‹ต์„ ๋ฐ›์„ ๋–„, Filter๊ฐ€ ์ ์šฉ๋œ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค.
  • https://docs.nestjs.com/exception-filters#built-in-http-exceptions
  • ์ด Exceptions๋“ค์€ ๋ชจ๋‘ HTTP Exceptions์„ Extend๋ฅผ ํ•˜๊ณ  ์žˆ๋‹ค.
    • ๊ทธ๋ž˜์„œ ๋‚˜์ค‘์— Exception ํ•„ํ„ฐ ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค ๋•Œ,
    • HTTP Exceptions์— ํ•ด๋‹น๋˜๋Š” Exceptions๋“ค๋งŒ ์žก๋Š” Exception ํ•„ํ„ฐ๋ฅผ ๋งŒ๋“ญ๋‹ˆ๋‹ค.

1.1 Exception Filter ๊ตฌํ˜„๋ฐฉ๋ฒ•

1
import { ExceptionFilter, Catch, ArgumentsHost, HttpException } from '@nestjs/common'
2
import { Request, Response } from 'express'
3
4
@Catch(HttpException)
5
export class HttpExceptionFilter implements ExceptionFilter {
6
catch(exception: HttpException, host: ArgumentsHost) {
7
const ctx = host.switchToHttp()
8
const response = ctx.getResponse<Response>()
9
const request = ctx.getRequest<Request>()
10
const status = exception.getStatus()
11
12
response.status(status).json({
13
statusCode: status,
14
message: exception.message,
15
timestamp: new Date().toLocaleString('kr'),
16
})
17
}
18
}

2. HttpExceptionFilter ๋งŒ๋“ค๊ธฐ

common/exception-filter/http.exception-filter.ts ํŒŒ์ผ์„ ๋งŒ๋“ ๋‹ค.

common/exception-filter/http.exception-filter.ts
1
import { ArgumentsHost, Catch, ExceptionFilter, HttpException } from '@nestjs/common'
2
3
@Catch(HttpException)
4
export class HttpExceptionFilter implements ExceptionFilter {
5
catch(exception: HttpException, host: ArgumentsHost) {
6
const ctx = host.switchToHttp()
7
const response = ctx.getResponse()
8
const request = ctx.getRequest()
9
const status = exception.getStatus()
10
11
/**** Filter ์ „์—ญ ์„ค์ •
12
* ๋กœ๊ทธ ํŒŒ์ผ์„ ์ƒ์„ฑํ•˜๊ฑฐ๋‚˜,
13
* ์—๋Ÿฌ ๋ชจ๋‹ˆํ„ฐ๋ง ์‹œ์Šคํ…œ์— API ์š”์ฒญํ•˜๊ธฐ ๊ธฐ๋Šฅ์„ ๋งŒ๋“ค๊ณ 
14
* globalํ•˜๊ฒŒ ์“ธ ์ˆ˜๋„ ์žˆ์Œ(main.ts)
15
*/
16
17
response.status(status).json({
18
statusCode: status,
19
message: exception.message,
20
timestamp: new Date().toLocaleString('kr'),
21
path: request.url,
22
})
23
}
24
}

์ด์ œ ์ž‘์„ฑํ•œ Filter๋ฅผ posts ์ปจํ‹€๋กœ๋Ÿฌ์— getPosts์— ์ ์šฉํ•ด๋ณธ๋‹ค.

posts.controller.ts
1
// posts.controller.ts ์ƒ๋žต
2
/*** 1) GET /posts
3
* ๋ชจ๋“  post๋ฅผ ๋‹ค ๊ฐ€์ ธ์˜จ๋‹ค
4
*/
5
@Get()
6
@UseInterceptors(LogInterceptor)
7
@UseFilters(HttpExceptionFilter)
8
getPosts(@Query() query: PaginatePostDto) {
9
throw new BadRequestException('์—๋Ÿฌ ํ…Œ์ŠคํŠธ')
10
return this.postsService.paginatePosts(query)
11
}

์ด์ œ ์ผ๋ถ€๋Ÿฌ ์—๋Ÿฌ๋ฅผ ๋‚ด๋ฉด, ์šฐ๋ฆฌ๊ฐ€ ์ •์˜ํ•œ๋Œ€๋กœ ์‘๋‹ต์ด ์˜จ ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

1
{
2
"statusCode": 400,
3
"message": "์—๋Ÿฌ ํ…Œ์ŠคํŠธ",
4
"timestamp": "2024. 1. 7. ์˜คํ›„ 5:44:51",
5
"path": "/posts?order__createdAt=DESC&take=5"
6
}

์ฐธ๊ณ ๋กœ main.ts์—์„œ Filter๋ฅผ ๊ธ€๋กœ๋ฒŒํ•˜๊ฒŒ ์ ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

  • ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์•ฑ ์ „์ฒด์—์„œ nhttp exception ๊ด€๋ จ๋œ ๋ชจ๋“  exception์ด ๋ฐœ์ƒ์„ ํ•  ๋•Œ๋งˆ๋‹ค,
  • ๋กœ๊ทธ ๋ชจ๋‹ˆํ„ฐ๋ง ํ•  ์ˆ˜ ์žˆ๋Š” ๋กœ์ง์„ ์ž‘์„ฑ์„ ํ–ˆ๋‹ค๊ณ  ๊ฐ€์ •์„ ํ–ˆ์„ ๋•Œ,
  • ์—๋Ÿฌ๊ฐ€ ๋‚  ๋•Œ๋งˆ๋‹ค ๋ชจ๋“  ์—๋Ÿฌ๋“ค์— ๋Œ€ํ•ด์„œ ์ „๋ถ€ http exception ํ•„ํ„ฐ๋ฅผ ์‹คํ–‰์„ ํ•ด์ค„ ์ˆ˜๊ฐ€ ์žˆ๋‹ค.
  • ์ง€๊ธˆ์€ ๊ธ€๋กœ๋ฒŒํ•˜๊ฒŒ ๊ทธ๋‹ฅ ์“ธ ํ•„์š”๊ฐ€ ์—†์œผ๋‹ˆ๊นŒ, ์ผ๋‹จ์€ ์ฃผ์„ ์ฒ˜๋ฆฌํ•œ๋‹ค.
main.ts
1
// ์ƒ๋žต
2
async function bootstrap() {
3
// ์ƒ๋žต
4
app.useGlobalFilters(new HttpExceptionFilter()) // ์ฃผ์„ ์ฒ˜๋ฆฌ
5
await app.listen(3000)
6
}
7
bootstrap()