[NestJS 공식문서 정독하기] Overview - Middleware
2022. 7. 1. 02:00ㆍWeb/NestJS
반응형
🔗 https://docs.nestjs.com/middleware
Documentation | NestJS - A progressive Node.js framework
Nest is a framework for building efficient, scalable Node.js server-side applications. It uses progressive JavaScript, is built with TypeScript and combines elements of OOP (Object Oriented Progamming), FP (Functional Programming), and FRP (Functional Reac
docs.nestjs.com
Middleware
- 미들웨어는 route 핸들러 전에 호출되는 함수임
- 미들웨어 함수는 요청, 응답 객체에 접근할 수 있음
- 요청/응답 사이클상의 다음 미들웨어 함수인
next()
함수에도 접근 가능 - NestJS의 미들웨어는 기본적으로 express의 미들웨어와 동일함
Express 미들웨어에서 할 수 있는 것 (NestJS와 동일)
- 코드 실행
- 요청, 응답 객체 수정
- 요청/응답 사이클 종료
- 다음 미들웨어 호출
NestJS 미들웨어 구현 방법
import { Injectable, NestMiddleware } from '@nestjs/common';
import { Request, Response, NextFunction } from 'express';
@Injectable()
export class LoggerMiddleware implements NestMiddleware {
use(req: Request, res: Response, next: NextFunction) {
console.log('Request...');
next();
}
}
- 함수 또는 클래스로 구현할 수 있음
- 클래스로 구현하면
@Injectable
데코레이터와 함께NestMiddleware
인터페이스를 구현해야 함 - DI 가능
미들웨어 적용
import { Module, NestModule, MiddlewareConsumer } from '@nestjs/common';
import { LoggerMiddleware } from './common/middleware/logger.middleware';
import { CatsModule } from './cats/cats.module';
@Module({
imports: [CatsModule],
})
export class AppModule implements NestModule {
configure(consumer: MiddlewareConsumer) {
consumer
.apply(LoggerMiddleware)
.forRoutes('cats');
}
}
@Module()
데코레이터 내부에서는 설정 불가능- 따라서 모듈 클래스의
configure()
메소드로 설정함 - 해당 메소드를 구현하기 위해
NestModule
인터페이스를 구현해야함
forRoutes({ path: 'cats', method: RequestMethod.GET });
- 위와 같이
forRoutes
에서 경로 뿐만 아니라 요청 메소드도 설정할 수 있음
forRoutes({ path: 'ab*cd', method: RequestMethod.ALL });
- 패턴 기반 설정도 가능함 (wildcard)
- 위 패턴은
abcd
,ab_cd
,abecd
등과 매칭됨 - fastify는 * wildcard를 더이상 지원하지 않아서
(.*)
,:splat*
와 같은 파라미터를 사용해야 함
Middleware consumer
import { Module, NestModule, MiddlewareConsumer } from '@nestjs/common';
import { LoggerMiddleware } from './common/middleware/logger.middleware';
import { CatsModule } from './cats/cats.module';
import { CatsController } from './cats/cats.controller';
@Module({
imports: [CatsModule],
})
export class AppModule implements NestModule {
configure(consumer: MiddlewareConsumer) {
consumer
.apply(LoggerMiddleware)
.forRoutes(CatsController);
}
}
MiddlewareConsumer
는 helper 클래스임- 메소드 체이닝으로 설정함
forRoutes()
메소드는 단순 문자열, 여러개의 문자열,RouteInfo
객체, Controller 클래스를 받을 수 있음- Controller 클래스는 하나 또는 여러개의 배열을 받을 수도 있음
apply()
메소드도 단일 혹은 여러개의 미들웨어를 받을 수 있음
경로 제외하기
consumer
.apply(LoggerMiddleware)
.exclude(
{ path: 'cats', method: RequestMethod.GET },
{ path: 'cats', method: RequestMethod.POST },
'cats/(.*)',
)
.forRoutes(CatsController);
exclude()
메소드로 미들웨어가 적용되는 경로를 제외할 수 있음
함수형 미들웨어
import { Request, Response, NextFunction } from 'express';
export function logger(req: Request, res: Response, next: NextFunction) {
console.log(`Request...`);
next();
};
consumer
.apply(logger)
.forRoutes(CatsController);
- 미들웨어를 클래스로 선언하지 않고 함수로 구현해서 적용할 수 있음
- 로직에 추가 의존성이 필요 없을 때 사용하면 좋음
여러개의 미들웨어
consumer.apply(cors(), helmet(), logger).forRoutes(CatsController);
글로벌 미들웨어
const app = await NestFactory.create(AppModule);
app.use(logger);
await app.listen(3000);
- 글로벌 미들웨어에서는 DI 컨테이너를 사용할 수 없음
- 따라서 글로벌 미들웨어는 함수형 미들웨어를 사용할 수 있음
- DI 컨테이너를 사용하기 위한 대안으로 클래스 미들웨어를 AppModule에
forRoutes('*')
로 설정할 수 있음
반응형