[NestJS] - Class Validator

morecodeplease·2024년 11월 29일
0

NestJS TIL

목록 보기
3/9
post-thumbnail

1. Class Validator란?

https://github.com/typestack/class-validator class validator 깃허브


  • class-validator는 데코레이터와 타입스크립트 클래스를 기반으로 객체의 유효성을 검사하는 라이브러리이다.
  • class-validator를 사용하여 들어오는 요청 데이터를 검증한다.
  • 동기, 비동기 방식 모두를 지원한다.
  • 중첩으로 validation이 가능하다!

사용 방법 (main.ts)

import { ValidationPipe } from '@nestjs/common';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  app.useGlobalPipes(new ValidationPipe());
  await app.listen(3000);
}
bootstrap();
  • NestJS에서는 파이프(Pipe)를 사용하여 데이터의 변환과 유효성 검사를 수행한다.
  • 애플리케이션 전반에 걸쳐 들어오는 요청을 자동으로 검증하려면 main.ts 파일에서 app.useGlobalPipes(new ValidationPipe());를 등록한다.

DTO

export class UpdateMovieDto {
  @IsNotEmpty()
  @IsOptional()
  title?: string;

  @IsNotEmpty()
  @IsOptional()
  genre?: string;
  }
  • 위의 예시처럼 dto에서 애노테이션을 달아서 사용한다. 이제 class-validtor의 종류와 사용 예시들을 알아보자

기본 Validator

  // 기본 validator
  // null || undefined 인지구분
  // @IsDefined() >> 해당 속성이 undefined가 아닌지 확인
  // @IsOptional() >> 해당 속성이 선택적임을 알려줌(선택 입력)
  // @Equals('zero') >> 괄호안의 값만 넣을 수 있음
  // @NotEquals('zero') >> 괄호안의 값 제외한 값을 넣을 수 있음
  // @IsEmpty() //>> null || undefined || '' 인 값을 찾는다.
  // @IsNotEmpty() >> // IsEmpty반대

타입 Validator

  // 타입 validator
  // Array
  // @IsIn(['action', 'fantasy']) // >> action과 fantasy만 넣을 수 있음
  // @IsNotIn(['action', 'fantasy']) // >> action과 fantasy는 제외한 값만 가능
  // @IsBoolean() // 불리언값만 가능
  // @IsString() // string 값만 가능
  // @IsNumber() // number 값만 가능
  // @IsInt() // 정수만 가능
  // @IsArray() // array만 가능
  // @IsEnum(MovieGenre) // 괄호안에 Enum값만 가능
  // @IsDateString() // 2024-07-07T12:00:00.000Z << ISO 8601 date string 형식인지 확인 ####-##-##T시간:초.msZ는 UTC타임을 알려줌

숫자 Validator

// 숫자 validator
// @IsDivisibleBy(5) // 괄호 안의 값으로 나눌 수 있는 값인지 확인
// @IsPositive() // 양수인지 확인
// @IsNegative() // 음수인지 확인
// @Min(100) // 괄호 안의 값이 최솟값
// @Max(200) // 괄호 안의 값이 최댓값

문자 Validator

// 문자 validator
// @Contains('hello') // 괄호안의 값이 문자로 담겨있어야함 앞뒤에 다른문자있어도 상관없음 담겨있기만하면 ok
// @NotContains('hello') // 괄호안의 값이 문자로 담겨있으면 안됨
// @IsAlphanumeric() // 알파벳과 숫자로 이루어져 있어야함 공백도x 한글도x
// @IsCreditCard() // ####-####-####-#### >> 카드유형 구분 신뢰성은?모르게씀
// @IsHexColor() // Hex값 인지 확인
// @MaxLength(16) // 괄호안의 값이 최대 길이
// @MinLength(8) // 괄호안의 값이 최소 길이
// @IsUUID() // UUID인지 확인
// @IsLatLong() // 위도 경도 포맷 확인

2. Custom Validator

  • 수많은 Validator들을 class-validator에서 제공해주지만 내가 원하는 기능이 없거나 여러개의 validator를 중첩시켜야 할 때가 있다.
  • 이 때 Custom-validator를 만들어서 내 입맛에 맞게 만들 수 있다!😊
  • 하나의 함수와 하나의 클래스로 만들 수 있다.
  • 클래스만 만들면 Validate() 괄호안에 넣어야하고 , 그냥 애노테이션만 쓰고 싶으면 함수로 만들어야한다!

사용 예시 (1)

@ValidatorConstraint({
 async: true, // << 이 옵션으로 비동기로도 validation 가능
})

class PasswordValidator implements ValidatorConstraintInterface {
 validate(
   value: any,
   validationArguments?: ValidationArguments,
 ): Promise<boolean> | boolean {
   // 비밀번호 길이는 4-8
   return value.length > 4 && value.length < 8;
 }
 defaultMessage?(validationArguments?: ValidationArguments): string {
   return '비밀번호의 길이는 4~8자 입니다. 입력된 값은 ($value)';
 }
}

@Validate(PasswordValidator)
password: string;
  • ValidatorConstraintInterface를 확장해서 위의 예시처럼 custom-validator를 만들어서 @Validate() 안에 만든 데코레이터를 넣어주면 된다.
  • ValidatorConstraint옵션에서 async : true를 하면 비동기여도 validation이 가능하다.

사용 예시 (2)

@ValidatorConstraint({
  async: true, // << 이 옵션으로 비동기로도 validation 가능
})
class PasswordValidator implements ValidatorConstraintInterface {
  validate(
    value: any,
    validationArguments?: ValidationArguments,
  ): Promise<boolean> | boolean {
    // 비밀번호 길이는 4-8
    return value.length > 4 && value.length < 8;
  }
  defaultMessage?(validationArguments?: ValidationArguments): string {
    return '비밀번호의 길이는 4~8자 입니다. 입력된 값은 ($value)';
  }
}

function IsPasswordValid(validationOptions?: ValidationOptions) {
  return function (object: Object, propertyName: string) {
    registerDecorator({
      target: object.constructor,
      propertyName,
      options: validationOptions,
      validator: PasswordValidator,
    });
  };
}

  @IsPasswordValid()
  password: string;
  • 위의 예시에서 IsPasswordValid라는 함수를 선언해서 ValidationOptions를 받아서 registerDecorator로 커스텀 decorator + validator를 사용해서 애노테이션만 바로 쓸 수 있게 만들 수 있다.
  • 이 방식이 조금 귀찮을 수 있지만 애노테이션 하나만 사용한다는 점에서 직관적인 것 같다.
  @IsPasswordValid({
  message: "비밀번호가 너무 짧습니다!"
  })
  password: string;
  • 바로 위의 코드처럼 message : ~ 로 원래 데코레이터에 메시지도 오버로딩 가능하다.
  • 또 에러메시지도 커스텀 에러메시지를 반환할 수 있다.

참조

profile
Everyday's a lesson

0개의 댓글