백앤드(Back-End)/Nest.js

[Nest.js] Nest.js API 만들기 (4) - 미들웨어(Middleware)

RyanSin 2021. 11. 11. 02:12
반응형

- 개요

안녕하세요. 이번 시간에는 미들웨어(Middleware)에 대해 알아보겠습니다.

 

Express에서 미들웨어를 사용하신 분들은 어렵게 느껴지지 않으시겠지만, 미들웨어 개념을 모르시는 분들도 있기 때문에 최대한 열심히 설명하겠습니다.

 

- 개념

미들웨어(Middleware)란 무엇일까요? 단어를 나눠보면 Middle - 가운데, ware - 물건 = 가운데 물건?...

해석이 좀 이상 하지만 정확히 말하면 소프트웨어 사이에 중간 매개체 역할을 하는 소프트웨어라고 생각하시면 됩니다.

 

미들웨어(Middleware)

미들웨어를 왜 사용할까요? 특정 라우터에 접근 시 "인증&검증, 로그성 데이터를 기록할 때" 꼭! 거쳐야 하는 로직이 있을 때 사용합니다.

 

- 사용법

간단하게 인증 미들웨어를 만들어 활용해보는 시간을 가져보겠습니다.(실제 서비스에서 이렇게 사용하시면 안돼요... 참고!)

 

middleware 폴더와 그 하위로 auth.middleware.ts 파일을 만들겠습니다.

 

auth.middleware.ts

 

- auth.middleware.ts

import {
  Injectable,
  NestMiddleware,
  UnauthorizedException,
} from '@nestjs/common';
import { Request, Response, NextFunction } from 'express';

@Injectable()
export class AuthMiddleware implements NestMiddleware {
  use(req: Request, res: Response, next: NextFunction) {
    // 논리합 연산자 -> 왼쪽 피연산자가 false라면 오른쪽 피연산자가 실행
    const name: string = req.query.name || req.body.name;

    if (name == 'Ryan') {
      next();
    } else {
      // Ryan 유저가 아니라면 허가 받지 않은 유저이기 때문에 401 Error를 반환
      throw new UnauthorizedException();
    }
  }
}

위처럼 간단한 미들웨어를 만들었습니다. 제일 중요한 부분은 use(req: Request, res: Response, next: NextFunction)입니다.

 

req: 사용자에게 요청 정보를 받을 때 사용

req: 사용자에게 응답 시 사용

next: 다음 라우터로 이동시 사용

 

이제 app.module.ts 파일에 해당 미들웨어를 등록하면 됩니다.

 

- app.module.ts

import {
  Module,
  NestModule,
  MiddlewareConsumer,
  RequestMethod,
} from '@nestjs/common';
import { UserModule } from './user/user.module';
import { AuthMiddleware } from './middleware/auth.middleware';
import { UserController } from './user/user.controller';

@Module({
  imports: [UserModule],
  controllers: [],
  providers: [],
})
export class AppModule implements NestModule {
  configure(consumer: MiddlewareConsumer) {
    consumer
      .apply(AuthMiddleware)
      //exclude 함수는 제외 하고싶은 라우터를 등록합니다.
      .exclude({ path: 'user/create_user', method: RequestMethod.POST }) // 유저 생성
      .exclude({ path: 'user/user_all', method: RequestMethod.GET }) // 유저 전체 조회
      .forRoutes(UserController); // 1.유저 컨트롤러 등록
    // .forRoutes('user'); // 2.유저 컨트롤러 경로 등록 -> 위 1번과 동일
  }
}

위 소스 코드를 보면 이해하시는데 어렵지 않으실 겁니다.

 

AuthMiddleware 미들웨어를 apply를 통해 등록하고 forRoutes로 컨트롤러를 등록합니다.

- 요청 확인

유저 전체 조회

 

단일 유저 조회

 

"전체 유저 조회"는 제외한 라우터이기 때문에 미들웨어를 거치지 않고 컨트롤러에 바로 접근합니다.

하지만 "단일 유저 조회"허가받지 않은 클라이언트가 접근하면 허가받지 않았다고 Error를 반환합니다.

 

- 글로벌 미들웨어

미들웨어를 Global로 설정하고 싶으면 main.ts 파일에서 app.use()를 통해 등록하면 됩니다.

 

cors 또는 helmet 미들웨어 같은 애플리케이션 전체에서 사용되는 미들웨어는 Global 미들웨어로 등록합니다.

 

import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { ValidationPipe } from '@nestjs/common';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);

  //Global Middleware 설정 -> Cors 속성 활성화
  app.enableCors({
    origin: '*',
    methods: 'GET,HEAD,PUT,PATCH,POST,DELETE,OPTIONS',
    optionsSuccessStatus: 200,
  });

  app.useGlobalPipes(
    new ValidationPipe({
      /**
       * whitelist: DTO에 없은 속성은 무조건 거른다.
       * forbidNonWhitelisted: 전달하는 요청 값 중에 정의 되지 않은 값이 있으면 Error를 발생합니다.
       * transform: 네트워크를 통해 들어오는 데이터는 일반 JavaScript 객체입니다.
       *            객체를 자동으로 DTO로 변환을 원하면 transform 값을 true로 설정한다.
       * disableErrorMessages: Error가 발생 했을 때 Error Message를 표시 여부 설정(true: 표시하지 않음, false: 표시함)
       *                       배포 환경에서는 true로 설정하는 걸 추천합니다.
       */
      whitelist: true,
      forbidNonWhitelisted: true,
      transform: true,
      disableErrorMessages: true,
    }),
  );
  await app.listen(3000);
}
bootstrap();

 

Nest.js에서 cors를 설정 활성화하고 싶다면 enableCors()를 호출하면 됩니다.

 

이번 시간에는 미들웨어에 대해 알아봤습니다. 꼭 실습을 통해 이해해보시는 걸 추천드리겠습니다.

 

소스 저장소

github: https://github.com/Ryan-Sin/Node_Nest/tree/v4

 

GitHub - Ryan-Sin/Node_Nest

Contribute to Ryan-Sin/Node_Nest development by creating an account on GitHub.

github.com