카테고리 없음

nestjs에서 사용자 정의 validate 구현하기

lahuman 2024. 6. 13. 17:13
728x90

class-validator에서는 많은 validation 조건을 제공하여 줍니다. 하지만 사용자 정의 옵션이 필요할 때가 있는데, 이때 설정이 생각보다 복잡하네요.

ValidatorConstraintInterface 구현 하기

class-validator ValidatorConstraintInterface interface를 구현해서 사용자 정의 validation 처리를 합니다.

아래는 구현된 예제 입니다.

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

@ValidatorConstraint({ name: 'customText', async: false })
export class CustomTextLength implements ValidatorConstraintInterface {
  validate(text: string, args: ValidationArguments) {
    return text.length > 1 && text.length < 10; // for async validations you must return a Promise<boolean> here
  }

  defaultMessage(args: ValidationArguments) {
    // here you can provide default error message if validation failed
    return 'Text ($value) is too short or too long!';
  }
}

사용 예제

아래는 Post 클래스의 사용자 정의 validate를 사용하는 예제입니다.

import { Validate } from 'class-validator';
import { CustomTextLength } from './CustomTextLength';

export class Post {
  @Validate(CustomTextLength, {
    message: 'Title is too short or long!',
  })
  title: string;
}

nestjs에 적용 하기

위와 같이 설정 후 @Injectable을 사용하면 오류를 확인 할 수 있습니다. How to inject service to validator constraint interface in nestjs using class-validator?를 참고 하면 아래와 같은 컨테이너 처리를 추가 해야 합니다.

// Custom Validate
import {ValidatorConstraint, ValidatorConstraintInterface} from 'class-validator';
import {UsersService} from './user.service';
import {Injectable} from '@nestjs/common';

@ValidatorConstraint({ name: 'isUserAlreadyExist', async: true })
@Injectable() // this is needed in order to the class be injected into the module
export class IsUserAlreadyExist implements ValidatorConstraintInterface {
    constructor(protected readonly usersService: UsersService) {}

    async validate(text: string) {
        const user = await this.usersService.findOne({
            email: text
        });
        return !user;
    }
}

// UserModule 
import {Module} from '@nestjs/common';
import { UsersController } from './user.controller';
import { UsersService } from './user.service';
import { IsUserAlreadyExist } from './user.validator';

@Module({
    controllers: [UsersController],
    providers: [IsUserAlreadyExist, UsersService],
    imports: [],
    exports: []
})
export class UserModule {
}

// main.ts
async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  useContainer(app.select(AppModule), { fallbackOnErrors: true });
...}

위와 같이 설정하면 inject이 정상적으로 처리 되는 것을 확인 할 수 있습니다.

약간 복잡해 보이는 설정인데, 한줄씩 코드로 보면 어렵지 않습니다.

참고 자료

728x90