NestJS request body validation

Peter·2021년 2월 17일
1

nestjs

목록 보기
10/11
post-thumbnail

1. 패키지 설치

yarn add class-validator class-transformer

class-validator 패키지를 설치하면 데코레이터로 간단하게 validation 처리가 가능합니다.

2. 원하는 위치에 데코레이터 추가

  @UsePipes(new ValidationPipe())
  @Post()
  async create(@Body() req: CreateUserDto): Promise<ResponseWrapper<User>> {
    return await this.userService.create(req);
  }

위와 같이 Controller 에서 validation을 적용하고 싶은 엔드포인트에 @UsePipes(new ValidationPipe()) 를 추가합니다.
그리고 Body에 mapping되어 있는 dto class(이 예제에서는 CreateUserDto)에서 validation 적용을 원하는 프로퍼티에 적절한 데코레이터를 추가합니다.

export class CreateUserDto {
  name: string;
  
  phone: string;
  
  @IsOptional()
  @IsEmail()
  email?: string;

  birthday?: string;
}

위와 같이 작성한 뒤, email에 'aaa'와 같이 email format이 아닌 데이터를 입력하여 API를 호출하면 아래와 같이 validator가 작동하여 400 에러 및 에러 메시지를 응답합니다.

3. custom decorator

validatior을 직접 구현하여 decorator로 제공할 수도 있습니다.
다음은 YYYY-MM-DD 형식의 데이터가 들어오도록 validation 하는 로직입니다.

import { registerDecorator, ValidationOptions } from 'class-validator';
import * as dayjs from 'dayjs';

export function IsOnlyDate(validationOptions?: ValidationOptions) {
  return function(object: Record<string, any>, propertyName: string) {
    registerDecorator({
      name: 'IsOnlyDate',
      target: object.constructor,
      propertyName: propertyName,
      constraints: [],
      options: {
        message: 'Please provide only date like 2020-12-08',
        ...validationOptions,
      },
      validator: {
        validate(value: any) {
          const regex = /^\d{4}(-)(((0)[0-9])|((1)[0-2]))(-)([0-2][0-9]|(3)[0-1])$/;
          // return typeof value === 'string' && regex.test(value);
          return typeof value === 'string' && regex.test(value) && dayjs(value).isValid();
        },
      },
    });
  };
}

위와 같이 소스코드를 작성한 뒤, dto class에 @IsOnlyDate 만 추가해주면 날짜 형식(YYYY-MM-DD)에 대한 validation이 적용됩니다.

export class CreateUserDto {
  name: string;
  
  phone: string;
  
  email?: string;

  @IsOnlyDate
  birthday?: string;
}

1개의 댓글

comment-user-thumbnail
2021년 3월 29일

찾고있던 내용인데, 좋은 정보
감사합니다~

답글 달기