> For the complete documentation index, see [llms.txt](https://jakekwak.gitbook.io/nestjs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://jakekwak.gitbook.io/nestjs/overview/untitled-2.md).

# Middleware

## Middleware

미들웨어는 라우트 핸들러보다 **전에** 호출되는 함수입니다. 미들웨어 기능은 [request](http://expressjs.com/en/4x/api.html#req) 및 [response](http://expressjs.com/en/4x/api.html#res)에 액세스 할 수 있습니다. 응용 프로그램의 요청-응답주기에서 객체 및 `next()`미들웨어 함수. **next** 미들웨어 함수는 일반적으로 `next`라는 변수로 표시됩니다.

![](https://docs.nestjs.com/assets/Middlewares_1.png)

&#x20;Nest 미들웨어는 기본적으로 [express](http://expressjs.com/en/guide/using-middleware.html) 미들웨어와 동일합니다. 공식 Express 문서의 다음 설명은 미들웨어의 기능을 설명합니다.

> &#x20;미들웨어 기능은 다음 작업을 수행 할 수 있습니다.
>
> * 어떤 코드를 실행합니다.
> * 요청 및 응답 오브젝트를 변경합니다.
> * 요청-응답주기를 종료합니다.
> * 스택에서 다음 미들웨어 함수를 호출합니다.
> * 현재 미들웨어 함수가 요청-응답주기를 종료하지 않으면 `next()`를 호출하여 다음 미들웨어 기능으로 제어를 전달하십시오. 그렇지 않으면 요청이 중단됩니다.

함수 또는 `@Injectable()`데코레이터가 있는 클래스에서 사용자 정의 Nest 미들웨어를 구현합니다. 클래스는 `NestMiddleware` 인터페이스를 구현해야 하지만, 함수에는 특별한 요구 사항이 없습니다. 클래스 메소드를 사용하여 간단한 미들웨어 기능을 구현하는 것으로 시작하겠습니다.

```typescript
@@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`를 설정해 봅시다.

```typescript
@@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 메소드 열거 형을 가져와 원하는 요청 메소드 유형을 참조하십시오.

```typescript
@@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

패턴 기반 경로도 지원됩니다. 예를 들어 별표는 **와일드 카드**로 사용되며 모든 문자 조합과 일치합니다.

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

`ab*cd` 라우트 경로는 `abcd`, `ab_cd`, `abecd` 등과 일치합니다. `?`, `+`, `*`및 `()`문자는 라우트 경로에 사용될 수 있으며 정규 표현식의 하위 집합입니다. 하이픈 (`-`)과 점 (`.`)은 문자 그대로 문자열 기반 경로로 해석됩니다.

## Middleware consumer

`MiddlewareConsumer`는 헬퍼 클래스입니다. 미들웨어를 관리하기위한 몇 가지 기본 제공 방법을 제공합니다. 이들 모두는 [유창한 스타일](https://en.wikipedia.org/wiki/Fluent_interface)에서 간단하게 **사슬**로 묶을 수 있습니다. `forRoutes()` 메소드는 단일 문자열, 다중 문자열, `RouteInfo` 오브젝트, 제어기 클래스 및 다중 제어기 클래스를 사용할 수 있습니다. 대부분의 경우 아마도 **컨트롤러** 목록을 쉼표로 구분하여 전달할 것입니다. 아래는 단일 컨트롤러를 사용한 예입니다.

```typescript
@@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()` 메소드는 단일 미들웨어 또는 여러 인수를 사용하여  [다중 미들웨어](https://app.gitbook.com/s/-LpOhNvIYtogx8UUAkWn/overview/middleware#multiple-middleware)를 지정할 수 있습니다.

미들웨어가 적용되지 않도록 특정 경로를 **제외** 할 수 있습니다.  [기능 미들웨어](https://app.gitbook.com/s/-LpOhNvIYtogx8UUAkWn/overview/middleware#functional-middleware) 대안을 사용하는 대신 지금까지했던 것처럼 클래스를 사용하여 미들웨어를 정의 할 때를 `exclude()` 메소드 사용하여 특정 경로를 쉽게 제외 할 수 있습니다. 이 방법은 아래와 같이 경로와 메소드를 식별하는 하나 이상의 객체를 제외시킵니다.

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

위의 예에서 `LoggerMiddleware`는 `exclude()`메소드에 전달 된 두 경로를 **제외**하고 `CatsController` 내에 정의 된 모든 경로에 바인딩됩니다. `exclude()`메소드는 기능 미들웨어 (클래스가 아닌 함수에 정의 된 미들웨어; 자세한 내용은 아래 참조)와 **작동하지 않습니다**. 또한 이 방법은 보다 일반적인 경로 (예: 와일드 카드)에서 경로를 제외하지 않습니다. 해당 레벨의 제어가 필요한 경우 경로 제한 로직을 미들웨어에 직접 배치하고 요청의 URL에 액세스하여 미들웨어 로직을 조건부로 적용해야합니다.

## Functional middleware

우리가 사용한 `LoggerMiddleware` 클래스는 매우 간단합니다. 멤버, 추가 메소드 및 종속성이 없습니다. 클래스 대신 간단한 함수로 정의할 수 없는 이유는 무엇입니까? 사실 우리는 할 수 있습니다. 이 유형의 미들웨어를 **기능적 미들웨어**라고합니다. 로거 미들웨어를 클래스 기반에서 기능적 미들웨어로 변환하여 차이점을 설명해 보겠습니다.

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

그리고`AppModule` 내에서 사용하십시오:

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

> info **힌트** 미들웨어에 종속성이 필요하지 않을 때마다 더 간단한 **기능적 미들웨어** 대안을 사용하는 것이 좋습니다.

## Multiple middleware

위에서 언급 한 것처럼 순차적으로 실행되는 여러 미들웨어를 바인딩하려면 `apply()`메소드 안에 쉼표로 구분 된 목록을 제공하십시오.

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

## Global middleware

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

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