미들웨어 (Middleware) 란?
- 라우트 핸들러 앞에 호출되는 함수
- 요청-응답에서 요청 및 응답 객체와
next()
미들웨어 함수에 접근 가능 - 다음 미들웨어 함수는 일반적으로
next
라는 변수로 표기됨 - 기본적으로 express 의 미들웨어와 동일
express 의 미들웨어 소개
- 어떤 코드든 실행한다.
- 요청-응답 객체를 변환한다.
- 요청-응답 사이클을 종료한다.
- 스택에서 다음 미들웨어 함수를 호출한다.
- 다음 미들웨어 함수에 제어권을 넘기기 위해
next()
를 호출해야 한다. 그렇지 않으면 요청이 중단된 채로 유지된다.next()
를 꼭 불러줘야 한다는 점이Interceptor
나Guard
와 같은 것과 구분된다.
미들웨어는 요청에 제공하는 기능 중 올인원 솔루션 같은 느낌이다.
제약받지 않고 많은 기능을 구현할 수 있다.Guard
나Interceptor
에서 했던 것들을Middleware
를 통해 구현할 수는 있지만, 목적에 맞게 사용하는 것이 좋음
미들웨어가 가장 많이 쓰이는 순간은?
- 자바스크립트에 미리 구현되어 있는 CORS 모듈이나 helmet 모듈은 미들웨어로 구현된 경우가 많다.
- 미리 구현된 범용 미들웨어들을 이용하는 경우가 많다.
다이어그램
라이프사이클
구현
- 함수 혹은
@Injectable()
데코레이터가 있는 클래스에서 사용자 정의 Nest 미들웨어를 구현한다.- 함수라면, 특별한 요구사항이 없다.
- 클래스라면,
NestMiddleware
인터페이스를 구현해야 한다.
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
를 세팅하는 코드다.
cats
경로에 로거 미들웨어를 적용하는 예제 코드
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");
}
}
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 });
}
}
참고
- 위에선
configure()
메서드가 동기 함수지만async
를 통해 비동기로도 가능하다. MiddlewareConsumer
를 통해 미들웨어를 커스터마이즈 하고 싶다면 글로벌 미들웨어를 꺼야 한다.NestFactory.create()
를 통해 앱을 생성할 때bodyParser
에false
플래그를 주면 된다.
라우트 와일드카드 (Route wildcards)
- 아래처럼 경로를 패턴으로 매칭시켜도 잘 동작한다.
- 정규표현식 쓰듯이 쓰면 된다.
forRoutes({ path: "ab*cd", method: RequestMethod.ALL });
Middleware consumer (미들웨어 컨슈머, 소비자)
- 헬퍼 클래스다.
- 미들웨어를 관리하기 위한 몇가지 내장 메서드를 제공한다.
forRoutes()
는 복수의 문자열을 받을 수도 있고,RouteInfo
오브젝트를 받을 수도 있다.apply()
도 여러 개의 미들웨어를 받을 수 있다.
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);
}
}
Excludes
- 특정 경로가 미들웨어에 적용되지 않도록 제외할 수 있다.
- path-to-regexp 규칙을 통해 정규표현식으로 제외할 수 있다.
consumer
.apply(LoggerMiddleware)
.exclude(
{ path: "cats", method: RequestMethod.GET },
{ path: "cats", method: RequestMethod.POST },
"cats/(.*)"
)
.forRoutes(CatsController);
Functional Middleware (함수형 미들웨어)
- 간단한 미들웨어를 작성할 때 굳이 클래스로 작성할 필요 없이 함수형 미들웨어를 이용할 수 있다.
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);
글로벌 미들웨어
main.ts
에서app.use()
를 통해 적용하면 글로벌로 적용된다.- 글로벌 미들웨어에서는 DI 컨테이너에 접근할 수 없다.
const app = await NestFactory.create(AppModule);
app.use(logger);
await app.listen(3000);
레퍼런스
반응형
'프레임워크 > Nest.js' 카테고리의 다른 글
Nest.js 웹소켓 (WebSockets) 이란? + 사용법 (0) | 2024.02.11 |
---|---|
Nest.js 인터셉터 (Interceptor) 란? (0) | 2024.02.07 |
Nest.js 의 Class Validator 란? (0) | 2024.02.02 |
Nest.js 의 가드(Guard) 란? (0) | 2024.02.02 |
Nest.js 의 파이프(Pipes) 란? (0) | 2024.01.13 |