먼저 클래스형 미들웨어는 다음과 같다.
// /src/common/middleware/logger.middleware.ts
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();
}
}
다음으로 함수형 미들웨어는 다음과 같다.
// /src/common/middleware/logger.middleware.ts
import { Request, Response, NextFunction } from 'express';
export function logger(req: Request, res: Response, next: NextFunction) {
console.log(`Request...`);
next();
};
그런데 공식문서에 의하면 위와 같은 상황에서는 멤버가 없고, 추가 메서드도 없고, 의존성도 없으므로 함수형으로 만드는 방법이 더 좋다고 한다.(막연하게만 알겠어)
예시를 통해 살펴보자
// app.module.ts
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');
}
}
아래의 예시는 Get요청에서 미들웨어가 작동하게 한 모습니다.
import { Module, NestModule, RequestMethod, 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({
path: 'cats',
method: RequestMethod.GET,
});
}
}
consumer.apply(
cors(),
helmet(),
logger
).forRoutes(CatsController);
즉, 위 예시에서는 cors(),helmet(),logger의 순서로 작동한다는 이야기이다.
다음과 같은 방법으로 활용할 수 있다고 한다.
consumer
.apply(LoggerMiddleware)
.exclude(
{ path: 'cats', method: RequestMethod.GET },
{ path: 'cats', method: RequestMethod.POST },
'cats/(.*)',
)
.forRoutes(CatsController);
위 예시에서는 '/cats'라는 라우팅 핸들러에서 Get,Post 요청을 제외하고 미들웨어를 실행하는 것으로 보인다.
const app = await NestFactory.create(AppModule);
app.use(logger);
await app.listen(3000);
추가적으로 다음과 같은 문구가 공식문서에 존재한다.
use() 메서드로 등록하는 전역 미들웨어는 DI 컨테이너 접근이 불가합니다. 따라서 의존성 주입이 되지 않으니, use() 메서드로는 함수형 미들웨어를 등록하는게 좋습니다. 의존성 주입이 필요한 클래스형 미들웨어를 전역으로 등록하려면 루트 모듈에서 .forRoutes('*') 로 미들웨어를 등록하는 등의 다른 방법을 쓰세요.
즉, 함수형의 경우 위와 같은 방법을 이용하고 클래스형의 경우에는 App모듈에 .forRoutes('*') 을 통해 등록하라는 이야기처럼 보인다.
참고: 네스트 공식문서