[NestJS] DTO Validator

woogiemon·2023년 3월 15일
0
post-thumbnail
export class DecideProductReqListRequest {
  @ApiProperty()
  @IsNumber()
  productReqListId: number;

  @ApiProperty()
  @IsString()
  status: string;

  @ApiProperty()
  @IsString()
  reason?: string;
}

나는 이 Request DTO의 status 의 값이 'Approved, Rejected, Delayed' 이 셋 중 하나만 입력되게 하고 싶다.

삽질

employee.service.ts

async decideProductReqList(
    employeeId: number,
    request: DecideProductReqListRequest,
  ): Promise<ProductReqListEntity> {
    const productReqInfo = await this.productReqListRepository.findOne({
      where: { id: request.productReqListId },
      relations: ['user', 'employee'],
    });

    ...

    if (
      request.status != 'Approved' &&
      request.status != 'Rejected' &&
      request.status != 'Delayed'
    ) {
      throw new BadRequestException('status 값이 올바르지 않습니다.');
    }
  }

처음에는 Service 단에서 throw new BadRequestException으로 잡았다. 근데 이렇게 하면 controller 를 넘어서 service 의 맨 마지막 문장까지 와서야 잡히게 된다. 내가 원하는건 request 에 내가 원하는 값이 들어오지 않으면 튕기는 것이다.

그래서 여태 써오던 class-validator 에서 request 를 잡아줄 데코레이터가 있는지 검색해서 @IsIn 을 찾았다.

export class DecideProductReqListRequest {
  @ApiProperty()
  @IsNumber()
  productReqListId: number;

  @ApiProperty()
  @IsIn(['Approved', 'Rejected', 'Delayed'])
  status: string;

  @ApiProperty()
  @IsString()
  reason?: string;
}

근데 적용이 안된다. 뭐가 문제일지 생각을 해보다가, 설마 다른 class-validator 도 적용이 안되는건가 하고 class-validator 적용하는 방법을 찾아봤는데, 유효성 검사를 전역으로 적용하려면 main.ts 의 코드에 추가해줄 것이 있었다.

main.ts

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

app.useGlobalPipes(new ValidationPipe());

main.ts 를 수정하고 status 에 원하지 않는 값을 넣어보니 class-validator 가 정상적으로 동작했다.

{
  "statusCode": 400,
  "message": [
    "status must be one of the following values: Approved, Rejected, Delayed"
  ],
  "error": "Bad Request"
}

여태 유효성이 검증되는지도 확인 안해봤었구만..

profile
삽질 기록..

0개의 댓글