# 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);
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://jakekwak.gitbook.io/nestjs/overview/untitled-2.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
