Pipe

이재홍·2022년 5월 19일
0

Pipe 사용 목적

  1. 변환 - 라우터 핸들러에 전달되기전 요청 객체를 원하는 형식으로 변환
  2. 유효성 검사 - 요청 객체가 정한 기준에 부합하지 않는 경우 예외처리

@nest/common 패키지 기본제공 내장파이프

  1. ValidationPipe
  2. ParseIntPipe
  3. ParseBoolPipe
  4. ParseArrayPipe
  5. ParseUUIDPipe
  6. DefaultValuePipe
@Get(':id')
findOne(@Param('id', ParseIntPipe) id: number) {}

@Param 데코레이터의 2번째 인자로 파이프를 넘겨 전달된 인자의 타입을 검사 및 형변환 해주어 현재 실행컨텍스트(ExecutionContext)에 바인딩할 수 있다. (형변환 할 수 없는 문자등이 올 경우 에러처리)

클래스를 전달하지 않고 파이프 인스턴스를 직접 생성 후 전달할 수도있다.

@Get(':id')
findOne(@Param('id', new ParseIntPipe({
	errorHttpStatusCode: HttpStatus.NOT_ACCEPTABLE
})) id: number) {}

DefaultValuePipe는 인자의 기본값을 설정한다.
쿼리 파라미터가 생략된 경우 유용하게 사용된다.

@Get()
findAll(
	@Query('offset', new DefaultValuePipe(0), ParseIntPipe) offset: number,
  	@Query('limit', new DefaultValuePipe(10), ParseIntPipe) limit: number
) {}
// 생략시 기본값으로 데이터 생략없이 10개의 데이터를 가져온다.

기본제공해주는 ValidationPipe를 커스텀파이프처럼 직접 구현해보기

import {
  ArgumentMetadata,
  BadRequestException,
  Injectable,
  PipeTransform,
} from '@nestjs/common';
import { plainToClass } from 'class-transformer';
import { validate } from 'class-validator';

// 기본제공해주는 ValidationPipe를 커스텀파이프처럼 직접 구현해보기
@Injectable()
export class ValidationPipe implements PipeTransform<any> {
  async transform(value: any, { metatype }: ArgumentMetadata) {
    // 인자로 전달된 값의 메타데이터의 메타타입(라우터핸들러에 정의된 인자의 타입)이 파이프가 지원하는 타입인지 검사
    if (!metatype || !this.toValidate(metatype)) {
      return value;
    }
    // 네트워크 요청을 통해 들어온 데이터는 역직렬화 과정에서 본문의 객체가 타입정보를 잃어버리기에 유효성검사불가능, plainToClass로 순수 자바스크립트객체를 타입을 가진 클래스의 객체로 변환
    const object = plainToClass(metatype, value);
    const errors = await validate(object); // 유효성 검사
    if (errors.length > 0) {
      throw new BadRequestException('유효성 검사 실패');
    }
    return value;
  }

  private toValidate(metatype: Function): boolean {
    const types: Function[] = [String, Boolean, Number, Array, Object];
    return !types.includes(metatype);
  }
}

적용

@Post()
  async createUser(@Body(ValidationPipe) dto: CreateUserDto): Promise<void> {
    const { name, email, password } = dto;
    await this.usersService.createUser(name, email, password);
  }

검증에 실패시 에러반환.

@UsePipes(ValidationPipe) 로 메서드,컨트롤러등에서 파라미터 전체적용
main.ts에서 app.useGlobalPipes(new ValidationPipe()) 로 전역에서 적용가능

0개의 댓글