nest js

NestJs 미들웨어

호리둥절 2023. 4. 6. 15:55

미들웨어란?

미들웨어는 http요청과 응답사이 즉 라우터 핸들러 이전에 호출되는 함수 입니다.

다시말해서 클라이언트 요청을 라우터 핸들러가 받기전에 가로채서 다른작업을 수행할 수 있습니다.

다음과 같은 특징들이 있습니다.

  • 요청에 대한 검증, 로깅, 인증, 권한 체크, 캐싱 등의 작업을 수행 할 수 있습니다.
  • 다수의 미들웨어 등록을 통해 다양한 작업을 순차적으로 처리할 수 있습니다.
  • next 함수 호출을 통해 미들웨어 체인을 연결합니다. next 함수를 호출하면 다음 미들웨어가 실행되며, 호출하지 않으면 다음 미들웨어가 실행되지 않습니다.
  • NestJS는 전역 미들웨어(Global Middleware)와 로컬 미들웨어(Local Middleware)를 지원합니다. 전역 미들웨어는 모든 요청과 응답에 적용되며, 로컬 미들웨어는 특정 라우터에만 적용됩니다.

미들웨어 사용법

1. 미들웨어 생성하기

@Injectable() 데코레이터를 사용하여 클래스를 생성해야 합니다. 이 클래스는 NestMiddleware 인터페이스를 구현해야 하며,  use() 메서드를 구현하여 미들웨어 로직을 작성합니다.

간단하게 cli를 통해 코드를 작성해봅시다.

 

아래의 코드는 요청과 응답 정보를 로그로 출력하는 Logger 미들웨어입니다.

nest generate middleware Logger
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(`[${new Date().toLocaleString()}] ${req.method} ${req.originalUrl}`);
    res.on('finish', () => {
      console.log(`[${new Date().toLocaleString()}] ${req.method} ${req.originalUrl} ${res.statusCode}`);
    });
    next();
  }
}

위 코드에서는 use 메서드를 이용해 미들웨어를 구현합니다. use 메서드의 매개변수로 req, res, next를 받습니다. req는 요청 객체, res는 응답 객체, next는 다음 미들웨어를 호출하는 함수입니다.

use 메서드에서는 요청 정보를 출력하고, 응답 완료 후에는 응답 코드를 출력합니다. 이때 res.on('finish', callback) 메서드를 사용하여 응답 완료 이벤트를 등록합니다.

 

2. 미들웨어 등록하기

export class AppModule implements NestModule {
  configure(consumer: MiddlewareConsumer) {
    consumer
      .apply(LoggerMiddleware)
      .forRoutes('*'); //전역에 등록
      // .forRoutes('users'); //user 경로에만 등록
      // .forRoutes({ path: 'users', method: RequestMethod.GET }); //users 경로에서 GET 요청에만 등록
      // .forRoutes({ path: 'ab*cd', method: RequestMethod.ALL }); //패턴 기반 경로
  }
}

위으 코드에서 consumer.apply 메서드를 사용하여 미들웨어를 등록하고, forRoutes 메서드를 사용하여 적용할 경로를 설정합니다 `*`를 사용하면 모든 경로에 미들웨어가 적용됩니다.

 

get 요청후 출력된 코드를 봅시다.

[2023. 4. 6. 오후 3:30:38] GET /user
[2023. 4. 6. 오후 3:30:38] GET /user 200

 

이를 포함하여 MiddlewareConsumer은 여러스타일로 미들웨어를 설정할 수 있습니다

내장모듈 - MiddlewareConsumer

아래와 같이 컨트롤러도 등록할수 있습니다.

export class AppModule implements NestModule {
  configure(consumer: MiddlewareConsumer) {
    consumer
      .apply(LoggerMiddleware)
      .forRoutes(UserController);
  }
}

아래와 같이 특정 경로를 제외할수도 있습니다.

consumer
  .apply(LoggerMiddleware)
  .exclude(
    { path: 'user', method: RequestMethod.GET },
    { path: 'user', method: RequestMethod.POST },
    'user/(.*)',
  )
  .forRoutes(UserController);

 

Function Middleware

Function Middleware는 함수 형태로 작성된 미들웨어입니다.

class Middleware 와 Function Middleware를 비교한 코드 예시입니다.

@Injectable()
export class CustomMiddleware implements NestMiddleware {
  use(req: Request, res: Response, next: NextFunction) {
    console.log('Request...');
    next();
  }
}

export function customFunctionMiddleware(req: Request, res: Response, next: NextFunction) {
  console.log('Request...');
  next();
}

싱글톤 함수로 구현하면 되며 @injectable() 데코레이터 없이 사용 가능합니다.

consumer
  .apply(logger)
  .forRoutes(UserController);

 

여러개의 미들웨어 사용

다음과같이 apply() 메서드를 사용하여 여러개의 미들웨어를 사용할수 있습니다.

consumer.apply(cors(), helmet(), logger).forRoutes(userController);

 

global 미들웨어

등록된 모든 경로에 미들웨어를 한 번에 바인딩하려면 use()인스턴스에서 제공하는 메서드를 사용할 수 있습니다

const app = await NestFactory.create(AppModule);
app.use(logger);
await app.listen(3000);

전역 미들웨어에서 DI 컨테이너에 액세스하는 것은 불가능합니다. .NET을 사용할 때 대신 기능적 미들웨어를 사용할 수 있습니다 app.use(). 또는 클래스 미들웨어를 사용하고 (또는 다른 모듈) .forRoutes('*')내 에서 사용할 수 있습니다

 

 

'nest js' 카테고리의 다른 글

NestJs custom pipe 에 대해 알아보자  (0) 2023.04.06
NestJs Pipe에 대하여 알아보자  (0) 2023.04.06
NestJs Provider(공급자)  (0) 2023.04.06
NestJs controller에 대해 이해하기  (0) 2023.04.06
NestJs cli 명령어 모음  (0) 2023.04.06