nestjs class-validation

양진영·2023년 2월 13일
0

nestJs

목록 보기
10/10

예전에 개발하면서 맞닥들였던 문제중에 하나가 type alias를 사용하여 union type을 입혀 enum 대신 사용하려 한적이있었다. 자동차 연료 타입을 지정하는 것이었는데 별 문제없이 진행될줄알았다. 당시 코드를 기억해보자면 아래와 같았다.

export type FuelType = "전기" | "가솔린" | "하이브리드" | "LPG" | "디젤"

@Entity()
export class Car {
	...중략

	@Column()
	FuelType:FuelType

}

fuelType이라는 프로퍼티에 들어갈수있는 타입으로 위에서 만들어둔 FuelType으로 지정해주고 postman을 이용해서 값을 전달해주니까 잘들어갔었다. 근데 혹시나 해서 지정해둔 타입말고 다른 값을 넣어주니 그것도 잘들어 갔었다... 그때 참 혼란스러웠었다. 그런데 나중에 알고보니 빌드하는순간 ts로 설정해둔것들이 날라가 버려 type 지정해둔것이 사라져 버려 타입체크가 안됫던 것이다. 그래서 그때 찾아보다가 class-validator를 사용했었어야 됫다는걸 깨달었던것 같다.

필요한 패키지: class-validator 그리고 class-transformer(이건 왜필요한지 모르겠지만 없으면 깔아주라고 에러를 뱉었었다.)

user.entity.ts
import { ApiProperty } from '@nestjs/swagger';
import { IsEmail, IsNotEmpty, IsString } from 'class-validator';
import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm';

@Entity()
export class User {
  @PrimaryGeneratedColumn()
  id: number;

  @IsEmail()
  @IsNotEmpty()
  @ApiProperty({
    required: true,
    description: 'email',
    example: 'abc@gmail.com',
  })
  @Column()
  email: string;

  @IsString()
  @IsNotEmpty()
  @ApiProperty({
    required: true,
    description: 'nickanme',
    example: 'cookieyam',
  })
  @Column()
  nickname: string;

  @IsString()
  @IsNotEmpty()
  @ApiProperty({
    required: true,
    description: 'write first name',
    example: 'Jinyoung',
  })
  @Column()
  firstName: string;

  @IsString()
  @IsNotEmpty()
  @ApiProperty({
    required: true,
    description: 'write last name',
    example: 'Yang',
  })
  @Column()
  lastName: string;

  @IsString()
  @IsNotEmpty()
  @ApiProperty({
    required: true,
    description: 'wrtie password',
    example: '1q2w3e4r',
  })
  @Column()
  password: string;
}

@Is~ 로 프로퍼티값을 validate하는것이 가능하다. 위의 예시는 entity에 입혔지만 entity에 안입히고 dto에 입혀도 상관없다. 만약 클라이언트에서 내가 지정한 validation에 어긋난 타입의 데이터를 보낸다면 에러가 발생될것이다. 그리고 이때 발생한 에러는 우리가 지정한 exception filter의 포맷대로 리턴시킬수도 있다. 참고로 validation또한 main.ts에 app.useGlobalPipe(new ValidationPipe())로 등록 시켜야 한다.

exception-filter.ts

import {
  ExceptionFilter,
  Catch,
  ArgumentsHost,
  HttpException,
} from '@nestjs/common';
import { Request, Response } from 'express';

@Catch(HttpException)
export class HttpExceptionFilter implements ExceptionFilter {
  catch(exception: HttpException, host: ArgumentsHost) {
    const ctx = host.switchToHttp();
    const response = ctx.getResponse<Response>();
    const request = ctx.getRequest<Request>();
    const status = exception.getStatus();

    const err = exception.getResponse() as
      | string
      | { error: string; statusCode: 400; message: string[] }; // class validator가 이런식으로 mesg를 준다.

    if (typeof err !== 'string' && err.error === 'Bad Request') {
      return response.status(status).json({
        success: false,
        code: status,
        data: err.message,
      });
    }

    response.status(status).json({
      success: false,
      code: status,
      data: err,
    });
  }
}

class-validator 공부하면서 예전에 부딪혔던 에러가 생각나서 뭔가 재밋기도 하고 좀더 흥미로웠던것 같다. 나중에 그 때 만들던 기능 한번 다시 확인하고 class-validator 입혀보면 좀 신기할것같기도 하다.

profile
왜? 라는 질문을 중요시하는 서버 개발자입니다

0개의 댓글