NestJS 에서 class-validator 를 활용한 데이터 검증 방법

2023. 6. 26. 15:05Backend Development/NestJS

반응형

데이터 검증은 안정적이고 안전한 웹 애플리케이션을 개발하기 위해 필수적인 요소입니다. NestJS는 class-validatorclass-transformer 라이브러리를 활용하여 강력하고 유연한 데이터 검증을 제공합니다. 이 글에서는 기본 설정부터 고급 활용 사례까지 자세히 살펴보겠습니다.


1. class-validatorclass-transformer 설치

먼저, 데이터 검증에 필요한 라이브러리를 설치합니다:

npm install class-validator class-transformer

2. DTO 정의 및 데코레이터 사용

DTO(Data Transfer Object)는 데이터 검증을 위해 사용됩니다. DTO 클래스의 필드에 class-validator 데코레이터를 추가하여 유효성 검사를 정의합니다.

예제: UserDto

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

export class UserDto {
  @IsString()
  @Length(2, 30)
  name: string;

  @IsEmail()
  email: string;

  @IsInt()
  @Min(18)
  age: number;
}

주요 데코레이터

  • @IsString(): 값이 문자열인지 확인.
  • @Length(min, max): 문자열의 길이가 주어진 범위인지 확인.
  • @IsEmail(): 유효한 이메일 형식인지 확인.
  • @IsInt(): 값이 정수인지 확인.
  • @Min(value): 값이 최소값 이상인지 확인.

3. ValidationPipe 설정

NestJS는 ValidationPipe를 사용하여 데이터 검증을 수행합니다. 검증은 다음과 같은 수준에서 설정할 수 있습니다:

3.1. 특정 파라미터에 대한 검증

@Post('create')
createUser(@Body(new ValidationPipe()) userDto: UserDto) {
  return this.userService.create(userDto);
}

3.2. 특정 경로에 대한 검증

@UsePipes(new ValidationPipe())
@Post('create')
createUser(@Body() userDto: UserDto) {
  return this.userService.create(userDto);
}

3.3. 컨트롤러 전체에 대한 검증

@UsePipes(new ValidationPipe())
@Controller('users')
export class UserController {
  @Post('create')
  createUser(@Body() userDto: UserDto) {
    return this.userService.create(userDto);
  }
}

3.4. 애플리케이션 전역 검증

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

4. 고급 옵션 활용

ValidationPipe는 옵션을 통해 동작을 세부적으로 조정할 수 있습니다.

4.1. 자동 변환 활성화

자동 변환은 입력 데이터를 DTO 인스턴스로 변환합니다.

app.useGlobalPipes(new ValidationPipe({ transform: true }));

4.2. 유효하지 않은 속성 제거

검증되지 않은 속성을 자동으로 제거하려면 다음과 같이 설정합니다:

app.useGlobalPipes(new ValidationPipe({ whitelist: true }));

4.3. 허용되지 않은 속성 처리

허용되지 않은 속성이 포함된 요청을 차단하려면 다음 옵션을 추가합니다:

app.useGlobalPipes(new ValidationPipe({ whitelist: true, forbidNonWhitelisted: true }));

5. 커스텀 검증 데코레이터 만들기

class-validator를 사용하면 커스텀 검증 로직을 쉽게 추가할 수 있습니다.

예제: 중복 이메일 확인 데코레이터

import {
  registerDecorator,
  ValidationOptions,
  ValidatorConstraint,
  ValidatorConstraintInterface,
} from 'class-validator';

@ValidatorConstraint({ async: true })
export class IsEmailUniqueConstraint implements ValidatorConstraintInterface {
  async validate(email: string) {
    // 여기에 이메일 중복 확인 로직 추가 (예: DB 조회)
    const isUnique = await checkEmailUniqueness(email); 
    return isUnique;
  }
}

export function IsEmailUnique(validationOptions?: ValidationOptions) {
  return function (object: Object, propertyName: string) {
    registerDecorator({
      target: object.constructor,
      propertyName: propertyName,
      options: validationOptions,
      constraints: [],
      validator: IsEmailUniqueConstraint,
    });
  };
}

사용법

export class UserDto {
  @IsEmail()
  @IsEmailUnique({ message: '이미 존재하는 이메일입니다.' })
  email: string;
}

6. 유효성 검사 실패 시 예외 처리

NestJS는 기본적으로 BadRequestException을 발생시킵니다. 그러나 사용자 정의 예외 메시지를 설정할 수도 있습니다.

예제: 커스텀 메시지

export class UserDto {
  @IsString({ message: '이름은 문자열이어야 합니다.' })
  @Length(2, 30, { message: '이름은 2자 이상, 30자 이하여야 합니다.' })
  name: string;
}

마무리

class-validatorclass-transformer를 활용하면 NestJS에서 강력한 데이터 검증을 구현할 수 있습니다. 기본적인 검증 설정부터 고급 옵션 및 커스텀 데코레이터 활용까지, 이 가이드를 통해 데이터 검증의 모든 측면을 다룰 수 있습니다.

NestJS 애플리케이션의 안정성과 데이터 무결성을 강화하기 위해 이 가이드를 참고하여 검증 로직을 설계해 보세요!

반응형