1. 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 : ~
로 원래 데코레이터에 메시지도 오버로딩 가능하다.
- 또 에러메시지도 커스텀 에러메시지를 반환할 수 있다.
참조