미들웨어란 라우트 핸들러 이전에 호출되는 함수입니다. 미들웨어 함수는 애플리케이션의 요청-응답 사이클 내에서 request 및 response 객체와 next()
미들웨어 함수에 접근할 수 있습니다. next 미들웨어 함수는 보통 next
라는 변수명으로 사용됩니다.
Nest 미들웨어는 기본적으로 express 미들웨어와 동일합니다. 다음은 express 문서에서 설명하고 있는 미들웨어의 역할입니다.
- 미들웨어 함수는 다음과 같은 일을 할 수 있습니다.
- 코드 실행
- request, reponse 객체 요청 변경
- 요청-응답 사이클 종료
- 스택 내 다음 미들웨어 함수 호출
- 현재 미들웨어 함수가 요청-응답 사이클을 종료하지 않으면
next()
를 반드시 호출하여 다음 미들웨어 함수로 권한을 넘겨야 합니다.
함수 또는 @Injectable()
데코레이터를 사용한 클래스 내에서 Nest 미들웨어를 구현할 수 있습니다. 클래스는 NestMiddleware
인터페이스를 실행해야 하지만 함수에는 특별한 조건은 없습니다. 클래스 메소드를 사용하여 다음과 같이 간단한 미들웨어를 만들 수 있습니다.
# 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();
}
}
디펜던시 인젝션
Nest 미들웨어는 디펜던시 인젝션을 완전히 지원합니다. 프로바이더와 컨트롤러를 통해 동일한 모듈 내에 디펜던시 인젝션을 할 수 있습니다. 이는 보통 constructor
를 사용합니다.
미들웨어 사용하기
@Module()
데코레이터 내에는 미들웨어가 없습니다. 그 대신 우리는 모듈 클래스의 configure()
메소드를 사용하여 이를 설정했습니다. 미들웨어를 포함하고 있는 모듈은 반드시 NestModule
인터페이스를 사용합니다. AppModule
레벨에서 LoggerMiddleware
를 설정해보도록 하겠습니다.
# 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');
}
}
위 예시는 앞서 CatsController
내에서 정의한 /cats
라우트 핸들러의 LoggerMiddleware
를 설정하는 예시입니다. 마지막 .forRoutes('cats')
부분을 .forRoutes('\*')
로 변경하면 와일드카드 형식으로 사용할 수 있습니다.
미들웨어를 설정할 때 라우트 path
와 요청 method
를 forRoute()
메소드에 전달하여 미들웨어를 통제할 수도 있습니다. 아래의 예시는 RequestMethod
enum을 불러와 원하는 요청 메소드 유형을 참조합니다.
# app.module.ts
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 });
}
}
NestJS답게 로그 찍기
미들웨어를 구현했다면 관련 로그를 console.log()
를 통해 찍어볼 수도 있지만 다음과 같이 NestJS 내에서 제공하는 방법을 활용할 수도 있습니다.
#logger.middleware.ts
import { Injectable, Logger, NestMiddleware } from '@nestjs/common';
import { NextFunction, Request, Response } from 'express';
@Injectable()
export class LoggerMiddleware implements NestMiddleware {
private logger = new Logger('HTTP');
use(req: Request, res: Response, next: NextFunction) {
res.on('finish', () => {
this.logger.log(
`${req.ip} ${req.method} ${res.statusCode}`,
req.originalUrl
);
});
next();
}
}
참고 자료
'개발 > NestJS' 카테고리의 다른 글
NestJS 기초 (9) 예외 처리 (0) | 2022.10.09 |
---|---|
NestJS 기초 (7) 환경 변수 관리하기 (0) | 2022.10.06 |
NestJS 기초 (6) 모듈 (0) | 2022.10.04 |