[NestJS] Validation

Hocaron·2021년 12월 13일
0

NestJS

목록 보기
3/12
post-custom-banner

언제 사용할까?

에러핸들링

create-user.dto.ts

export class JoinRequestDto {
  readonly email: string;
  readonly nickname: string;
  readonly password: string;
}

user.controller.ts

@Controller('user')
export class UserController {
  constructor(private readonly userService: UserService) {}
  
  ...
  
  @Post()
  create(@Body() joinRequestDto: JoinRequestDto) {
    return this.userService.create(joinRequestDto);
  }
}

🙅‍♀️정의한 type에 맞지 않거나, 필요한데 request에 없을 때 하나 하나 에러 처리를 해줄 수도 있지만

if (!email) {
	throw new BadRequestException('이메일이 없네요');
}
if (!nickname) {
	throw new BadRequestException('닉네임이 없네요');
}
if (!password) {
	throw new BadRequestException('비밀번호이 없네요');
}

🙆‍♀️자동으로 검증하는 기능을 Nest에서 제공하고 있다.

import { IsNotEmpty } from 'class-validator';

export class JoinRequestDto {
  @IsNotEmpty()
  email: string;

  @IsNotEmpty()
  nickname: string;

  @IsNotEmpty()
  password: string;
}

response를 보면 자동으로 클라이언트에 에러 메시지를 보내주고 있다.

{
  "statusCode": 400,
  "error": "Bad Request",
  "message": ["email should not be empty",
	      "nickname should not be empty",
	      "password should not be empty"
	]
}

형변환

🙆‍♀️ 검증과 함께 array로 변환하여 사용할 수 있다.

@Get()
findByIds(
  @Query('ids', new ParseArrayPipe({ items: Number, separator: ',' }))
  ids: number[],
) {
  return 'This action returns users by ids';
}

너무 유용하잖아? 그럼 자세히 공부해보자😀

Validation

  • 웹 애플리케이션으로 전송된 데이터의 정확성을 검증하는 것이 좋다.
  • 수신 요청을 자동으로 검증하기 위해 Nest는 즉시 사용할 수 있는 여러 파이프를 제공한다.
    • ValidationPipe
    • ParseIntPipe
    • ParseBoolPipe
    • ParseArrayPipe
    • ParseUUIDPipe

ValidationPipe (암시적 형변환)

종속성 설치

$ npm i --save class-validator class-transformer

기본제공 옵션

export interface ValidationPipeOptions extends ValidatorOptions {
  transform?: boolean;
  // true로 설정하면 유효성 검사 오류가 클라이언트에 반환되지 않습니다.
  disableErrorMessages?: boolean;
  // 유효성 검사 오류의 배열을 가져오고 throw할 예외 개체를 반환합니다.
  exceptionFactory?: (errors: ValidationError[]) => any; 
 
}

📢 이 외에도 다양한 옵션들이 있다.

Auto-validation

  • 애플리케이션 수준에서 ValidationPipe을 바인딩하여, 모든 엔드포인트에 적용한다.
    main.ts
async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  app.useGlobalPipes(new ValidationPipe());
  await app.listen(3000);
}
bootstrap();
  • 데코레이터를 사용하여, 유효성 검사 규칙을 추가한다.
import { IsEmail, IsNotEmpty } from 'class-validator';

export class JoinRequestDto {
  @IsNotEmpty()
  @IsEmail()
  email: string;

  @IsNotEmpty()
  nickname: string;

  @IsNotEmpty()
  password: string;
}
  • 엔드포인트에 도달하면 애플리케이션이 다음 응답 본문과 함께 400 Bad Request 코드로 자동 응답한다.
{
  "statusCode": 400,
  "error": "Bad Request",
  "message": ["email must be an email"]
}

📢 이 외에도 다양한 유효성 검사 규칙들이 있다.

다른 요청 객체와도 사용

import { IsNumberString } from 'class-validator';

export class FindOneParams {
  @IsNumberString()
  id: number;
}
@Get(':id')
findOne(@Param() params: FindOneParams) {
  return 'This action returns a user';
}

자동으로 형변환

  • 메서드 수준에서 수행
@Post()
@UsePipes(new ValidationPipe({ transform: true }))
async create(@Body() createCatDto: CreateCatDto) {
  this.catsService.create(createCatDto);
}
  • 전역으로 활성화
  • 기본적으로 모든 경로 매개 변수와 쿼리 매개 변수는 네트워크를 통해 string으로 제공되지만, number로 지정해놓으면 ValidationPipe가 자동 변환해준다.
app.useGlobalPipes(
  new ValidationPipe({
    transform: true,
  }),
);

Parse*Pipe (명시적 형변환)

  • (자동 변환이 비활성화 된 상태에서) ParseIntPipe 또는 ParseBoolPipe를 사용하여 명시적으로 값을 캐스팅할 수 있다.
@Get(':id')
findOne(
  @Param('id', ParseIntPipe) id: number,
  @Query('sort', ParseBoolPipe) sort: boolean,
) {
  console.log(typeof id === 'number'); // true
  console.log(typeof sort === 'boolean'); // true
  return 'This action returns a user';
}

배열의 유효성 검사

@Get()
findByIds(
  @Query('ids', new ParseArrayPipe({ items: Number, separator: ',' }))
  ids: number[],
) {
  return 'This action returns users by ids';
}
  • HTTP GET 요청에서 들어오는 쿼리 매개변수의 유효성을 검사한다.
GET /?ids=1,2,3
profile
기록을 통한 성장을
post-custom-banner

0개의 댓글