1. Middleware ์ด๋ก

RequestMiddleware- Global Middleware
- Module Middleware
Guard- Global Guards
- Controller Guards
- Route Guards
Interceptors- Global Interceptors
- Controller Interceptors
- Route Interceptors
Pipes- Global Pipes
- Controller Pipes
- Route Pipes
- Route Parameter Pipes
ControllerServiceInterceptor- Router Interceptor
- Controller Interceptor
- Global Interceptor
Exception Filters- Route
- Controller
- Global
Response
๋ฏธ๋ค์จ์ด๋ ๊ฐ์ฅ ์ฝ๊ณ ๊ฐ์ฅ ๋จ์ํ๊ณ ๊ฐ์ฅ ์ด๋ป๊ฒ ๋ณด๋ฉด ์์ด์ ์ธ ๊ธฐ๋ฅ์ด๋ค.

- ๊ณต์๋ฌธ์ : https://docs.nestjs.com/middleware
- ์ ๊ทธ๋ฆผ์ ๋ณด๋ฉด, ํด๋ผ์ด์ธํธ ์ฌ์ด๋์์ ์์ฒญ์ ๋ฃ๊ณ , ๋ผ์ฐํธ ํธ๋ค๋ฌ๊น์ง ๊ฐ๊ธฐ ์ ์ ๋ฏธ๋ค์จ์ด๋ฅผ ๊ฑฐ์น๋ค.
- ์ ์ฒด ๊ทธ๋ฆผ์ ๋ดค์ ๋๋, ๋ฏธ๋ค์จ์ด๊ฐ ๊ฐ์ฅ ๋จผ์ ์์ฒญ์ ๋ฐ๋ ์ญํ ์ ํ๋ค.
Middleware๋ ๋ผ์ฐํธ ํธ๋ค๋ฌ๊ฐ ์คํ๋๊ธฐ ์ ์ ์คํ๋๋ค. Request์ Response ๊ฐ์ฒด์ ์ ๊ทผ ํ ์ ์๋ค.
Middleware๋ ๋ค์๊ณผ ๊ฐ์ ์์ ์ ํ ์ ์๋ค.
- ์์ ๋กญ๊ฒ ์ฝ๋ ์คํ
- ์์ฒญ๊ณผ ์๋ต ๊ฐ์ฒด๋ฅผ ๋ณ๊ฒฝ
- ์์ฒญ ์๋ต ์ฌ์ดํด ์ค๋จ
- ๋ค์ ๋ฏธ๋ค์จ์ด ์คํํ๊ธฐ
1.1 Middleware๋?
Nest ๋ฏธ๋ค์จ์ด๋ ๊ธฐ๋ณธ์ ์ผ๋ก Express ๋ฏธ๋ค์จ์ด์ ๋์ผํ๋ค. ๊ณต์ ๋ฌธ์์ ๋ค์ ์ค๋ช ์ ๋ฏธ๋ค์จ์ด์ ๊ธฐ๋ฅ์ ์ค๋ช ํ๋ค.
๋ฏธ๋ค์จ์ด ํจ์๋ ๋ค์ ์์ ์ ์ํํ ์ ์์ต๋๋ค.
- execute any code (์ด๋ค ์ฝ๋๋ ์คํํ ์ ์๋ค.)
- make changes to the request and the response objects.
- ์์ฒญ ๋ฐ ์๋ต ๊ฐ์ฒด์ ๋ณํ๋ฅผ ๋ง๋ค์ด ์ค ์ ์๋ค.
- ๋ฌด์ธ๊ฐ๋ฅผ ์ถ๊ฐํ๊ฑฐ๋ ์ญ์ , ์ ๋ฐ์ดํธ ํ ์ ์๋ค๋ ์๋ฏธ
- end the request-response cycle.
- ์์ฒญ์ด ๋๋๊ฒ ์ค๊ฐ์ ์ค์งํ ์ ์๋ค.
- ์ผ์ข ์ guard ์ญํ ๋ ํ ์ ์๋ค๋ ์๋ฏธ
- call the next middleware function in the stack.
- ์คํ์์ ๋ค์ ๋ฏธ๋ค์จ์ด ํจ์๋ฅผ ํธ์ถํ๋ค.
- ์ฌ๋ฌ ๊ฐ์ ๋ฏธ๋ค์จ์ด๋ฅผ ์์๋๋ก ์ ์ฉํ ์ ์๋๋ฐ, ์ ์ฉ๋ ์์๋๋ก ์คํ๋๋ค.
- ์ฆ, ๋ฏธ๋ค์จ์ด๋ฅผ ์ฌ๋ฌ ๊ฐ๋ฅผ ์ฎ์ ์ ์๋ค๋ ์๋ฏธ
- if the current middleware function does not end the request-response cycle,
- it must call
next()to pass control to the next middleware function.- Otherwise, the request will be left hanging.
- ํ์ฌ ๋ฏธ๋ค์จ์ด ํจ์๊ฐ ์์ฒญ-์๋ต ์ฃผ๊ธฐ๋ฅผ ์ข ๋ฃํ์ง ์๋ ๊ฒฝ์ฐ, (=> ์๋ฌ๋ฅผ ๋์ง์ง ์๋๋ค๋ฉด,)
- ๋ค์ ๋ฏธ๋ค์จ์ด ํจ์์ ์ ์ด๋ฅผ ์ ๋ฌํ๊ธฐ ์ํด
next()ํธ์ถํด์ผ ํ๋ค.- ๊ทธ๋ ์ง ์์ผ๋ฉด ์์ฒญ์ด ์ค๋จ๋ ์ํ๋ก ๋จ๊ฒ ๋ฉ๋๋ค.
2. Middleware ์ฌ์ฉ๋ฒ
2.1 Middleware ์ ์ธ๋ฒ
1import { Injectable, NestMiddleware } from '@nestjs/common'2import { Request, Response, NextFunction } from 'express'34@Injectable()5export class LogMiddleware implements NestMiddleware {6use(req: Request, res: Response, next: NextFunction) {7console.log(`[REQ] ${req.method} ${req.url} ${new Date().toLocaleString('kr')}`)8next()9}10}
2.2 Middleware ์ ์ฉ๋ฒ
์ ์ฉ๋ฒ 1 : ๋ชจ๋์ ์ ์ฉ
1import { Module, NestModule, MiddlewareConsumer } from '@nestjs/common'2import { LoggerMiddleware } from './common/middleware/logger.middleware'3import { CatsModule } from './cats/cats.module'45@Module({6imports: [CatsModule],7})8export class AppModule implements NestModule {9configure(consumer: MiddlewareConsumer) {10consumer.apply(LoggerMiddleware).forRoutes('cats')11}12}
1import { Module, NestModule, RequestMethod, MiddlewareConsumer } from '@nestjs/common'2import { LoggerMiddleware } from './common/middleware/logger.middleware'3import { CatsModule } from './cats/cats.module'45@Module({6imports: [CatsModule],7})8export class AppModule implements NestModule {9configure(consumer: MiddlewareConsumer) {10consumer.apply(LoggerMiddleware).forRoutes({ path: 'cats', method: RequestMethod.GET })11}12}
์ ์ฉ๋ฒ 2 : ์ปจํธ๋กค๋ฌ์ ์ ์ฉ
1forRoutes({ path: 'cats', method: RequestMethod.ALL })
1consumer2.apply(LoggerMiddleware)3.exclude(4{ path: 'cats', method: RequestMethod.GET }, //5{ path: 'cats', method: RequestMethod.POST },6'cats/(.*)',7)8.forRoutes(CatsController)
1consumer.apply(cors(), helmet(), logger).forRoutes(CatsController)
์ ์ฉ๋ฒ 3 : ๊ธ๋ก๋ฒ ๋ฏธ๋ค์จ์ด์ ์ ์ฉ
1const app = await NestFactory.create(AppModule)2app.use(logger)3await app.listen(3000)
3. Middleware ์ฌ์ฉ
common/middleware/log.middleware.ts ํ์ผ์ ๋ง๋ ๋ค.
1import { Injectable, NestMiddleware } from '@nestjs/common'2import { NextFunction } from 'express'34@Injectable()5export class LogMiddleware implements NestMiddleware {6use(req: Request, res: Response, next: NextFunction) {7console.log(`[REQ] ${req.method} ${req.url} ${new Date().toLocaleString('kr')}`)8next()9}10}
์ ํํ ๋ก๊ทธ๋ฅผ ํ์ธํ๊ธฐ ์ํด posts ์ปจํธ๋กค๋ฌ์ ์ ์ฉํ Interceptors์ Filter๋ฅผ ์ฃผ์์ฒ๋ฆฌํ๋ค.
1/*** 1) GET /posts2* ๋ชจ๋ post๋ฅผ ๋ค ๊ฐ์ ธ์จ๋ค3*/4@Get()5// @UseInterceptors(LogInterceptor)6// @UseFilters(HttpExceptionFilter)7getPosts(@Query() query: PaginatePostDto) {8// throw new BadRequestException('์๋ฌ ํ ์คํธ')9return this.postsService.paginatePosts(query)10}
๋ฏธ๋ค์จ์ด๋ ๋ชจ๋์๋ค๊ฐ ์ ์ฉํด์ผ ํ๋ค. posts ๋ชจ๋์ ์์ ์์ฑํ ๋ฏธ๋ค์จ์ด๋ฅผ ์ ์ฉํ๋ค.
1// posts.module.ts ์๋ต2export class PostsModule implements NestModule {3configure(consumer: MiddlewareConsumer) {4consumer.apply(LogMiddleware).forRoutes({5path: 'posts*', // posts ๋ค์ ์ด๋ค ๊ธ์์ด๋ ์ ์ฉ(์์ผ๋์นด๋)6// method: RequestMethod.ALL, // ๋ชจ๋ ์์ฒญ์ ์ ์ฉ7method: RequestMethod.GET, // GET ์์ฒญ๋ง ์ ์ฉ8})9}10}
๊ทธ๋ฐ๋ฐ ์ด๋ ๊ฒ ํน์ ๋ชจ๋์๋ง ์๋๋ผ ๋ชจ๋ ๋ชจ๋์ ์ ์ฉํ ์ ์๋ค.
- ์์์ ์์ฑํ ์ฝ๋๋ฅผ ๋ค์ ์๋๋๋ก
export class PostsModule{}๋ง ๋จ๊ธด๋ค. - ์ด๋ ๊ฒ ํ๋ฉด ์ฑ ์ ์ฒด ๋ชจ๋ ๋ผ์ฐํธ์ ๋ฏธ๋ค์จ์ด๋ฅผ ์ ์ฉํด, ์์ฒญ์ ๋ก๊ทธ๋ฅผ ์ฐ์ ์ ์๋ค.
- ๋์ฉ๋ ํธ๋ํฝ์ด ๋ค์ด์ค๋ ํธ๋ํฝ๋ค์ ๋ชจ๋ํฐ๋ง ์์คํ ์ ๋ฏธ๋ค์จ์ด๋ก ๋ง๋ค๋ฉด ์ ์ฉํ๋ค.
1// app.module.ts ์๋ต2export class AppModule implements NestModule {3configure(consumer: MiddlewareConsumer) {4consumer.apply(LogMiddleware).forRoutes({5path: '*', // ๋ค์ ์ด๋ค ๊ธ์์ด๋ ์ ์ฉ(์์ผ๋์นด๋)6method: RequestMethod.ALL, // ๋ชจ๋ ์์ฒญ์ ์ ์ฉ7})8}9}