Middleware

Middleware

λ―Έλ“€μ›¨μ–΄λŠ” 라우트 ν•Έλ“€λŸ¬λ³΄λ‹€ 전에 ν˜ΈμΆœλ˜λŠ” ν•¨μˆ˜μž…λ‹ˆλ‹€. 미듀웨어 κΈ°λŠ₯은 request 및 response에 μ•‘μ„ΈμŠ€ ν•  수 μžˆμŠ΅λ‹ˆλ‹€. μ‘μš© ν”„λ‘œκ·Έλž¨μ˜ μš”μ²­-μ‘λ‹΅μ£ΌκΈ°μ—μ„œ 객체 및 next()미듀웨어 ν•¨μˆ˜. next 미듀웨어 ν•¨μˆ˜λŠ” 일반적으둜 nextλΌλŠ” λ³€μˆ˜λ‘œ ν‘œμ‹œλ©λ‹ˆλ‹€.

Nest λ―Έλ“€μ›¨μ–΄λŠ” 기본적으둜 express 미듀웨어와 λ™μΌν•©λ‹ˆλ‹€. 곡식 Express λ¬Έμ„œμ˜ λ‹€μŒ μ„€λͺ…은 λ―Έλ“€μ›¨μ–΄μ˜ κΈ°λŠ₯을 μ„€λͺ…ν•©λ‹ˆλ‹€.

미듀웨어 κΈ°λŠ₯은 λ‹€μŒ μž‘μ—…μ„ μˆ˜ν–‰ ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

  • μ–΄λ–€ μ½”λ“œλ₯Ό μ‹€ν–‰ν•©λ‹ˆλ‹€.

  • μš”μ²­ 및 응닡 였브젝트λ₯Ό λ³€κ²½ν•©λ‹ˆλ‹€.

  • μš”μ²­-응닡주기λ₯Ό μ’…λ£Œν•©λ‹ˆλ‹€.

  • μŠ€νƒμ—μ„œ λ‹€μŒ 미듀웨어 ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•©λ‹ˆλ‹€.

  • ν˜„μž¬ 미듀웨어 ν•¨μˆ˜κ°€ μš”μ²­-응닡주기λ₯Ό μ’…λ£Œν•˜μ§€ μ•ŠμœΌλ©΄ next()λ₯Ό ν˜ΈμΆœν•˜μ—¬ λ‹€μŒ 미듀웨어 κΈ°λŠ₯으둜 μ œμ–΄λ₯Ό μ „λ‹¬ν•˜μ‹­μ‹œμ˜€. κ·Έλ ‡μ§€ μ•ŠμœΌλ©΄ μš”μ²­μ΄ μ€‘λ‹¨λ©λ‹ˆλ‹€.

ν•¨μˆ˜ λ˜λŠ” @Injectable()λ°μ½”λ ˆμ΄ν„°κ°€ μžˆλŠ” ν΄λž˜μŠ€μ—μ„œ μ‚¬μš©μž μ •μ˜ Nest 미듀웨어λ₯Ό κ΅¬ν˜„ν•©λ‹ˆλ‹€. ν΄λž˜μŠ€λŠ” NestMiddleware μΈν„°νŽ˜μ΄μŠ€λ₯Ό κ΅¬ν˜„ν•΄μ•Ό ν•˜μ§€λ§Œ, ν•¨μˆ˜μ—λŠ” νŠΉλ³„ν•œ μš”κ΅¬ 사항이 μ—†μŠ΅λ‹ˆλ‹€. 클래슀 λ©”μ†Œλ“œλ₯Ό μ‚¬μš©ν•˜μ—¬ κ°„λ‹¨ν•œ 미듀웨어 κΈ°λŠ₯을 κ΅¬ν˜„ν•˜λŠ” κ²ƒμœΌλ‘œ μ‹œμž‘ν•˜κ² μŠ΅λ‹ˆλ‹€.

@@filename(logger.middleware)
import { Injectable, NestMiddleware } from '@nestjs/common';
import { Request, Response } from 'express';

@Injectable()
export class LoggerMiddleware implements NestMiddleware {
  use(req: Request, res: Response, next: Function) {
    console.log('Request...');
    next();
  }
}
@@switch
import { Injectable } from '@nestjs/common';

@Injectable()
export class LoggerMiddleware {
  use(req, res, next) {
    console.log('Request...');
    next();
  }
}

Dependency injection

Nest λ―Έλ“€μ›¨μ–΄λŠ” Dependency Injection을 μ™„λ²½ν•˜κ²Œ μ§€μ›ν•©λ‹ˆλ‹€. κ³΅κΈ‰μž 및 μ»¨νŠΈλ‘€λŸ¬μ™€ λ§ˆμ°¬κ°€μ§€λ‘œ λ™μΌν•œ λͺ¨λ“ˆ λ‚΄μ—μ„œ μ‚¬μš© κ°€λŠ₯ν•œ 쒅속성을 μ£Όμž… ν•  수 μžˆμŠ΅λ‹ˆλ‹€. ν‰μ†Œμ™€ 같이 이것은 μƒμ„±μžλ₯Ό 톡해 μ΄λ£¨μ–΄μ§‘λ‹ˆλ‹€.

Applying middleware

@Module()λ°μ½”λ ˆμ΄ν„°μ—λŠ” 미듀웨어λ₯Ό μœ„ν•œ 곡간이 μ—†μŠ΅λ‹ˆλ‹€. λŒ€μ‹  λͺ¨λ“ˆ 클래슀의 configure()λ©”μ†Œλ“œλ₯Ό μ‚¬μš©ν•˜μ—¬ μ„€μ •ν•©λ‹ˆλ‹€. 미듀웨어λ₯Ό ν¬ν•¨ν•˜λŠ” λͺ¨λ“ˆμ€ NestModule μΈν„°νŽ˜μ΄μŠ€λ₯Ό κ΅¬ν˜„ν•΄μ•Όν•©λ‹ˆλ‹€. AppModule λ ˆλ²¨μ—μ„œ LoggerMiddlewareλ₯Ό μ„€μ •ν•΄ λ΄…μ‹œλ‹€.

@@filename(app.module)
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');
  }
}
@@switch
import { Module } from '@nestjs/common';
import { LoggerMiddleware } from './common/middleware/logger.middleware';
import { CatsModule } from './cats/cats.module';

@Module({
  imports: [CatsModule],
})
export class AppModule {
  configure(consumer) {
    consumer
      .apply(LoggerMiddleware)
      .forRoutes('cats');
  }
}

μœ„μ˜ μ˜ˆμ—μ„œ μš°λ¦¬λŠ” 이전에 CatsController 내에 μ •μ˜ 된 /cats 라우트 ν•Έλ“€λŸ¬μ— λŒ€ν•΄ LoggerMiddlewareλ₯Ό μ„€μ •ν–ˆμŠ΅λ‹ˆλ‹€. λ˜ν•œ 미듀웨어λ₯Ό ꡬ성 ν•  λ•Œ 경둜 path 및 μš”μ²­ methodλ₯Ό ν¬ν•¨ν•˜λŠ” 였브젝트λ₯Ό forRoutes()λ©”μ†Œλ“œμ— μ „λ‹¬ν•˜μ—¬ 미듀웨어λ₯Ό νŠΉμ • μš”μ²­ λ©”μ†Œλ“œλ‘œ μ œν•œν•  μˆ˜λ„ μžˆμŠ΅λ‹ˆλ‹€. μ•„λž˜ μ˜ˆμ œμ—μ„œ, RequestRequest λ©”μ†Œλ“œ μ—΄κ±° ν˜•μ„ 가져와 μ›ν•˜λŠ” μš”μ²­ λ©”μ†Œλ“œ μœ ν˜•μ„ μ°Έμ‘°ν•˜μ‹­μ‹œμ˜€.

@@filename(app.module)
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 });
  }
}
@@switch
import { Module, RequestMethod } from '@nestjs/common';
import { LoggerMiddleware } from './common/middleware/logger.middleware';
import { CatsModule } from './cats/cats.module';

@Module({
  imports: [CatsModule],
})
export class AppModule {
  configure(consumer) {
    consumer
      .apply(LoggerMiddleware)
      .forRoutes({ path: 'cats', method: RequestMethod.GET });
  }
}

Route wildcards

νŒ¨ν„΄ 기반 κ²½λ‘œλ„ μ§€μ›λ©λ‹ˆλ‹€. 예λ₯Ό λ“€μ–΄ λ³„ν‘œλŠ” μ™€μΌλ“œ μΉ΄λ“œλ‘œ μ‚¬μš©λ˜λ©° λͺ¨λ“  문자 μ‘°ν•©κ³Ό μΌμΉ˜ν•©λ‹ˆλ‹€.

forRoutes({ path: 'ab*cd', method: RequestMethod.ALL });

ab*cd 라우트 κ²½λ‘œλŠ” abcd, ab_cd, abecd λ“±κ³Ό μΌμΉ˜ν•©λ‹ˆλ‹€. ?, +, *및 ()λ¬ΈμžλŠ” 라우트 κ²½λ‘œμ— μ‚¬μš©λ  수 있으며 μ •κ·œ ν‘œν˜„μ‹μ˜ ν•˜μœ„ μ§‘ν•©μž…λ‹ˆλ‹€. ν•˜μ΄ν”ˆ (-)κ³Ό 점 (.)은 문자 κ·ΈλŒ€λ‘œ λ¬Έμžμ—΄ 기반 경둜둜 ν•΄μ„λ©λ‹ˆλ‹€.

Middleware consumer

MiddlewareConsumerλŠ” 헬퍼 ν΄λž˜μŠ€μž…λ‹ˆλ‹€. 미듀웨어λ₯Ό κ΄€λ¦¬ν•˜κΈ°μœ„ν•œ λͺ‡ κ°€μ§€ κΈ°λ³Έ 제곡 방법을 μ œκ³΅ν•©λ‹ˆλ‹€. 이듀 λͺ¨λ‘λŠ” μœ μ°½ν•œ μŠ€νƒ€μΌμ—μ„œ κ°„λ‹¨ν•˜κ²Œ μ‚¬μŠ¬λ‘œ 묢을 수 μžˆμŠ΅λ‹ˆλ‹€. forRoutes() λ©”μ†Œλ“œλŠ” 단일 λ¬Έμžμ—΄, 닀쀑 λ¬Έμžμ—΄, RouteInfo 였브젝트, μ œμ–΄κΈ° 클래슀 및 닀쀑 μ œμ–΄κΈ° 클래슀λ₯Ό μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€. λŒ€λΆ€λΆ„μ˜ 경우 μ•„λ§ˆλ„ 컨트둀러 λͺ©λ‘μ„ μ‰Όν‘œλ‘œ κ΅¬λΆ„ν•˜μ—¬ 전달할 κ²ƒμž…λ‹ˆλ‹€. μ•„λž˜λŠ” 단일 컨트둀러λ₯Ό μ‚¬μš©ν•œ μ˜ˆμž…λ‹ˆλ‹€.

@@filename(app.module)
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(CatsController);
  }
}
@@switch
import { Module } from '@nestjs/common';
import { LoggerMiddleware } from './common/middleware/logger.middleware';
import { CatsModule } from './cats/cats.module';

@Module({
  imports: [CatsModule],
})
export class AppModule {
  configure(consumer) {
    consumer
      .apply(LoggerMiddleware)
      .forRoutes(CatsController);
  }
}

info 힌트 apply() λ©”μ†Œλ“œλŠ” 단일 미듀웨어 λ˜λŠ” μ—¬λŸ¬ 인수λ₯Ό μ‚¬μš©ν•˜μ—¬ 닀쀑 미듀웨어λ₯Ό μ§€μ •ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

미듀웨어가 μ μš©λ˜μ§€ μ•Šλ„λ‘ νŠΉμ • 경둜λ₯Ό μ œμ™Έ ν•  수 μžˆμŠ΅λ‹ˆλ‹€. κΈ°λŠ₯ 미듀웨어 λŒ€μ•ˆμ„ μ‚¬μš©ν•˜λŠ” λŒ€μ‹  μ§€κΈˆκΉŒμ§€ν–ˆλ˜ κ²ƒμ²˜λŸΌ 클래슀λ₯Ό μ‚¬μš©ν•˜μ—¬ 미듀웨어λ₯Ό μ •μ˜ ν•  λ•Œλ₯Ό exclude() λ©”μ†Œλ“œ μ‚¬μš©ν•˜μ—¬ νŠΉμ • 경둜λ₯Ό μ‰½κ²Œ μ œμ™Έ ν•  수 μžˆμŠ΅λ‹ˆλ‹€. 이 방법은 μ•„λž˜μ™€ 같이 κ²½λ‘œμ™€ λ©”μ†Œλ“œλ₯Ό μ‹λ³„ν•˜λŠ” ν•˜λ‚˜ μ΄μƒμ˜ 객체λ₯Ό μ œμ™Έμ‹œν‚΅λ‹ˆλ‹€.

consumer
  .apply(LoggerMiddleware)
  .exclude(
    { path: 'cats', method: RequestMethod.GET },
    { path: 'cats', method: RequestMethod.POST }
  )
  .forRoutes(CatsController);

μœ„μ˜ μ˜ˆμ—μ„œ LoggerMiddlewareλŠ” exclude()λ©”μ†Œλ“œμ— 전달 된 두 경둜λ₯Ό μ œμ™Έν•˜κ³  CatsController 내에 μ •μ˜ 된 λͺ¨λ“  κ²½λ‘œμ— λ°”μΈλ”©λ©λ‹ˆλ‹€. exclude()λ©”μ†Œλ“œλŠ” κΈ°λŠ₯ 미듀웨어 (ν΄λž˜μŠ€κ°€ μ•„λ‹Œ ν•¨μˆ˜μ— μ •μ˜ 된 미듀웨어; μžμ„Έν•œ λ‚΄μš©μ€ μ•„λž˜ μ°Έμ‘°)와 μž‘λ™ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€. λ˜ν•œ 이 방법은 보닀 일반적인 경둜 (예: μ™€μΌλ“œ μΉ΄λ“œ)μ—μ„œ 경둜λ₯Ό μ œμ™Έν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€. ν•΄λ‹Ή 레벨의 μ œμ–΄κ°€ ν•„μš”ν•œ 경우 경둜 μ œν•œ λ‘œμ§μ„ 미듀웨어에 직접 λ°°μΉ˜ν•˜κ³  μš”μ²­μ˜ URL에 μ•‘μ„ΈμŠ€ν•˜μ—¬ 미듀웨어 λ‘œμ§μ„ μ‘°κ±΄λΆ€λ‘œ μ μš©ν•΄μ•Όν•©λ‹ˆλ‹€.

Functional middleware

μš°λ¦¬κ°€ μ‚¬μš©ν•œ LoggerMiddleware ν΄λž˜μŠ€λŠ” 맀우 κ°„λ‹¨ν•©λ‹ˆλ‹€. 멀버, μΆ”κ°€ λ©”μ†Œλ“œ 및 쒅속성이 μ—†μŠ΅λ‹ˆλ‹€. 클래슀 λŒ€μ‹  κ°„λ‹¨ν•œ ν•¨μˆ˜λ‘œ μ •μ˜ν•  수 μ—†λŠ” μ΄μœ λŠ” λ¬΄μ—‡μž…λ‹ˆκΉŒ? 사싀 μš°λ¦¬λŠ” ν•  수 μžˆμŠ΅λ‹ˆλ‹€. 이 μœ ν˜•μ˜ 미듀웨어λ₯Ό κΈ°λŠ₯적 λ―Έλ“€μ›¨μ–΄λΌκ³ ν•©λ‹ˆλ‹€. 둜거 미듀웨어λ₯Ό 클래슀 κΈ°λ°˜μ—μ„œ κΈ°λŠ₯적 λ―Έλ“€μ›¨μ–΄λ‘œ λ³€ν™˜ν•˜μ—¬ 차이점을 μ„€λͺ…ν•΄ λ³΄κ² μŠ΅λ‹ˆλ‹€.

@@filename(logger.middleware)
export function logger(req, res, next) {
  console.log(`Request...`);
  next();
};

그리고AppModule λ‚΄μ—μ„œ μ‚¬μš©ν•˜μ‹­μ‹œμ˜€:

@@filename(app.module)
consumer
  .apply(logger)
  .forRoutes(CatsController);

info 힌트 미듀웨어에 쒅속성이 ν•„μš”ν•˜μ§€ μ•Šμ„ λ•Œλ§ˆλ‹€ 더 κ°„λ‹¨ν•œ κΈ°λŠ₯적 미듀웨어 λŒ€μ•ˆμ„ μ‚¬μš©ν•˜λŠ” 것이 μ’‹μŠ΅λ‹ˆλ‹€.

Multiple middleware

μœ„μ—μ„œ μ–ΈκΈ‰ ν•œ κ²ƒμ²˜λŸΌ 순차적으둜 μ‹€ν–‰λ˜λŠ” μ—¬λŸ¬ 미듀웨어λ₯Ό λ°”μΈλ”©ν•˜λ €λ©΄ apply()λ©”μ†Œλ“œ μ•ˆμ— μ‰Όν‘œλ‘œ ꡬ뢄 된 λͺ©λ‘μ„ μ œκ³΅ν•˜μ‹­μ‹œμ˜€.

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

Global middleware

λ“±λ‘λœ λͺ¨λ“  λΌμš°νŠΈμ— 미듀웨어λ₯Ό ν•œ λ²ˆμ— λ°”μΈλ”©ν•˜λ €λ©΄ INestApplication μΈμŠ€ν„΄μŠ€μ—μ„œ μ œκ³΅ν•˜λŠ”use()λ©”μ†Œλ“œλ₯Ό μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

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

Last updated

Was this helpful?