Validation Pipe란?
validation pipe
은 class-validator
패키지와 해당 패키지에서 제공하는 데코레이터를 활용하여 요청 데이터의 유효성을 검증하는 기능입니다.
이를 통해 개발자는 간단한 어노테이션을 사용하여 요청 데이터에 대한 검증 규칙을 선언하고, 이를 통해 모든 클라이언트 요청 데이터에 대한 유효성 검사를 간편하게 수행할 수 있습니다.
Validation Pipe 적용
1. 먼저 class-validator
와 class-transformer
를 설치 해줍니다.
npm i --save class-validator class-transformer
2. 다음으로, DTO(Data Transfer Object)
를 만듭니다.
이 DTO는 request body로 들어오는 데이터를 담는 클래스입니다. 예를 들어 다음과 같은 코드가 있을 때,
interface CreateUserDto {
firstName: string;
lastName: string;
email: string;
password: string;
}
이를 class-validator를 이용해 검증하려면 다음과 같이 코드를 작성합니다.
import { IsString, IsEmail } from 'class-validator';
export class CreateUserDto {
@IsString()
readonly firstName: string;
@IsString()
readonly lastName: string;
@IsEmail()
readonly email: string;
@IsString()
readonly password: string;
}
여기서 @IsString()
이나 @IsEmail()
과 같은 데코레이터는 해당 클래스 프로퍼티가 맞는 형식인지 검증합니다.
이를 사용하기 위해서는 class-validator
에서 제공하는 데코레이터를 불러와 사용하면 됩니다.
3. 다음은 validation pipe를 생성 해줍니다.
파이프 옵션으로 whitelist
, errorHttpStatusCode
등의 옵션을 추가할 수 있으며, 전체 옵션에 대한 내용은 공식 문서를 참고하실 수 있습니다.
// 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();
4. 해당 파이프를 사용하기 위해서는 해당 controller의 메소드에 @Body()
데코레이터 안에서 Dto를 사용하면 됩니다.
import { Controller, Post, Body } from '@nestjs/common';
import { CreateUserDto } from './create-user.dto';
@Controller('users')
export class UsersController {
@Post()
async create(@Body() createUserDto: CreateUserDto) {
}
}
유효성 검사에 실패할 경우 아래와 같이 실패 응답(400 Bad Request)을 반환합니다.
{
"statusCode": 400,
"error": "Bad Request",
"message": ["email must be an email"]
}
그 외 사용 방법
정해진 배열 값만 사용
import {
ArrayNotEmpty,
IsArray,
IsIn
} from 'class-validator'
const weekdays = ['monday', 'tuesday', 'wednesday', 'thursday', 'friday'];
export class SpecificString {
@IsArray()
@ArrayNotEmpty()
@IsIn(weekdays)
day: string[]
}
each
는 배열의 모든 값이 유효한 지 체크합니다.@Matches
로 정규식 조건을 사용할 수 있습니다.@Contains
는 문자 또는 숫자를 포함하고 있는 지 체크합니다.import {
ArrayNotEmpty,
Contains,
IsArray,
IsString,
Matches,
MaxLength
} from 'class-validator'
export class StringArray {
@IsArray()
@ArrayNotEmpty()
// each: 배열의 모든 값이 유효한지 체크
@IsString({ each: true })
@MaxLength(6, { each: true })
// 알파벳으로 이루어져있는지 체크
@Matches('^[a-zA-Z\\s]+$', undefined, { each: true })
// 'hello' 문자를 포함하고 있는 지 체크
@Contains('hello', { each: true })
stringArray: string[]
}
Validator Constraint
를 이용하여 Custom Validator
를 생성할 수 있습니다.
// example.dto.ts
import {
IsNumber,
IsNotEmpty,
MinLength,
MaxLength,
ValidatorConstraint,
ValidatorConstraintInterface
} from 'class-validator'
@ValidatorConstraint({ name: 'IsEvenNumber' })
export class IsEvenNumber implements ValidatorConstraintInterface {
validate(value: number): boolean {
if (value {
return value % 2 === 0
}
return false
}
}
export class SpecificNumber {
@IsNumber()
@IsNotEmpty()
// 짝수인지 체크
@Validate(IsEvenNumber, { message: 'No Even Number' })
specificNumber: number
}
참고