[NestJS] - 9. Pipe와 Validator, 요청 데이터 사전 검문하기

2023. 2. 23. 01:00
반응형

이번 포스팅에서는 앞서 만든 REST API를 데이터베이스와 연동하기 이전에 Pipe의 개념과 클래스의 값 유효성을 검증하는 Class-Validator에 대해 간단히 포스팅하고 넘어가려고 한다.


Pipe

NestJS 공식문서

  • @Injectable 데코레이터에 의해 사용되는 Providers에 속하는 클래스
  • 클라이언트의 요청 데이터 인수를 Route Handler에서 작업하기 이전에 사전에 처리해주는 역할을 한다. 파이프를 사용 시 데이터를 사용 가능한지 판별하거나 사용하기 적절하게 가공하는 과정을 거치며, 해당 과정을 통과해야 라우터에 도달하게 된다.
  • 요청값을 원하는 형식으로 바꿔주는 Data Transformation과, 입력값의 자료형 등의 유효성을 판별하는 Data Validation의 역할을 수행한다.

 

 


Validator의 필요성

 

  @Post()
  createProduct(@Body() input: CreateProductInput): boolean {
    return this.productService.create(input);
  }

다음과 같이 상품을 등록하는 API가 있다고 생각해보자. 클라이언트는 Body에 이름, 가격 등을 포함한 상품 모델을 함께 인수로 전달하여, 서버는 해당 인수를 바탕으로 데이터베이스에 Insert하게 될 것이다.

 

그런데 가격이 만약 "안녕"과 같은 문자로 입력받게 된다면 문제가 발생하게 될 것이다. 

클라이언트쪽에서 잘 막아주면 되지 않는가라고 질문할 수 있지만 누군가 백엔드 개발자는 절대 프론트엔드와 클라이언트를 믿지 말라고 했다. 어떠한 기상천외한 방법을 시도할 지 모른다.

 

 


Validator Pipe 사용하기

 

패키지 설치

yarn add class-validator class-transformer

 

 

▶ createProduct.dto.ts

import { IsInt, IsString } from 'class-validator';

export class CreateProductInput {
  @IsString()
  name: string;

  @IsString()
  description: string;

  @IsInt()
  price: number;
}

다음과 같이 클래스 안에 데코레이터를 통해서 클래스 속성에 대한 허용값을 정해준다.

자료형 지정은 물론, NULL 허용여부나 최소값/최댓값 등 다양한 데코레이터들을 지원해준다.

 

하지만 이런다고 끝나는 것은 아니고 해당 Validator을 사용한다고 파이프를 설정해주어야 한다.

 

  @Post()
  @UsePipes(ValidationPipe)
  createProduct(@Body() input: CreateProductInput): boolean {
    return this.productService.create(input);
  }

다음과 같이 @UsePipes(ValidationPipe)를 통해서 Class-Validator를 통해 사전에 검사하겠다고 파이프를 설정해주어야 한다.

참고로 ValidationPipe는 NestJS가 기본적으로 제공해주는 파이프 종류 중 하나이다.

 

price가 String으로 들어오자 400 Error을 반환한다. 모든 값이 유효하므로 라우터에서 해당 요청을 처리하여 결과를 반환하였다.

 

 

 


GlobalPipes 사용하기

 

그렇다면 매번 @UsePipes(ValidationPipe)를 컨트롤러에 매번 붙여주어야 할까? 그렇지는 않다. NestJS에서 전역적으로 파이프를 적용시킬 수도 있다.

 

 

▶ main.ts

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

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  app.useGlobalPipes(new ValidationPipe());
  await app.listen(3000);
}
bootstrap();

다음과 같이 app.useGlobalPipes()를 적용시키면 모든 요청에 ValidationPipe를 적용시키는 것이 가능하다.

 

 

  @Post()
  createProduct(@Body() input: CreateProductInput): boolean {
    return this.productService.create(input);
  }

그러면 데코레이터 없이 Input값에 대해서 Validation Pipe를 적용시키는 것이 가능하다.

 

 

 


해당 강의를 들으면서 학습한 내용을 바탕으로 저만의 프로젝트를 만드는 과정을 기록하여 남기는 것을 목표로 하고 있습니다.

주관적인 생각이 들어가 있을 수 있으므로 혹시 틀린 내용이 있다면 피드백 부탁드립니다.

https://www.inflearn.com/course/%EB%B6%80%ED%8A%B8%EC%BA%A0%ED%94%84-%EB%B0%B1%EC%97%94%EB%93%9C-%EA%B3%A0%EB%86%8D%EC%B6%95-%EC%BD%94%EC%8A%A4/dashboard

 

[인프런x코드캠프] 부트캠프에서 만든 고농축 백엔드 코스 - 인프런 | 강의

코딩과 사랑에 빠져버린 8년차 풀스택 개발자 Captain의 사심이 가득 담긴 커리큘럼이에요. 백엔드의 모든 것을 다 알려주고 싶은 Captain의 마음이 녹아있죠! 이 강의를 듣다보면 '이렇게까지 알려

www.inflearn.com

 

반응형

BELATED ARTICLES

more