따라하면서 배우는 NestJS #3 - Pipe, Validation Check, Exception

Jina Kim·2022년 10월 12일
0

NestJS

목록 보기
4/6
post-thumbnail

Pipe

데이터 transformation(변환)과 데이터 유효성 체크를 위해서 사용
메소드가 호출되기 직전에 파이프 삽입

data transformation

데이터를 원하는 형식으로 변환
ex) string to integer

data validation

입력 데이터 유효하지 않은 경우 에러 반환
ex) 입력 글자가 10자 이상이어야 하는데, 10자 미만일 경우 error 반환

@UsePipes

핸들러 레벨에서 @UsePipes 데코레이터를 이용해서 사용

ParameterPipe

파라미터 레벨에서 사용

Global Pipes

애플리케이션 레벨에서 사용
ex) useGlobalPipes

built-in Pipes

nestJS에는 기본적으로 6개의 Pipe가 있다.

  1. ValidationPipe
  2. ParseIntPipe
  3. ParseBoolPipe
  4. ParseArrayPipe
  5. ParseUUIDPipe
  6. DefaultValuePipe

class-validator 패키지

https://github.com/nestjs/class-validator
데이터 유효성 체크를 위한 패키지

$ npm install class-validator class-transformer --save

위의 cmd를 통해 class validator와 class transformer 패키지를 설치한다.

게시물 생성시 pipe를 이용하여 유효성 체크

dto 코드

import { IsNotEmpty } from 'class-validator';

export class CreateBoardDto {
  @IsNotEmpty()
  title: string;

  @IsNotEmpty()
  description: string;
}

class-validator 패키지의 @IsNotEmpty 데코레이터를 사용하여
입력값이 not empty인지 체크.
(입력값이 empty이면 error 반환)

controller 코드

  @Post()
  @UsePipes(ValidationPipe)
  createBoard(@Body() createBoardDto: CreateBoardDto): Board {
    return this.boardsService.createBoard(createBoardDto);
  }

@UsePipes(ValidationPipe) 를 통해 validation을 체크한다.

결과값

title과 description이 빈 값이면 400 error를 뱉어낸다.

Exception 1

게시물을 id로 호출했는데, id에 해당하는 게시물이 없을 경우 예외처리를 해보자.

service 코드

  getBoardById(id: string): Board {
    const found = this.boards.find((board) => board.id === id);

    if (!found) {
      throw new NotFoundException(`Can't find Board with Id ${id}`);
    }
    return found;
  }

throw new NotFoundException() 만 하면 message가 나오지 않는다.
괄호 안에 Can't find Board with Id ${id} 를 넣어주면 message까지 같이 나온다.

결과값

1231234라는 id의 게시물이 없을 경우 exception 처리에 대한 404 메시지 노출.

Exception 2

없는 게시물을 지우려고 할 때, 예외처리를 해보자.

service 코드

  deleteBoard(id: string): void {
    const found = this.getBoardById(id);
    this.boards = this.boards.filter((board) => board.id !== found.id);
  }

이미 위의 getBoardById(id) 에서 예외처리가 되어있어서 this.boards.filter를 실행하기 전에
예외처리 로직이 실행된다.

결과값

커스텀 파이프

기본적으로 구현되어 있는 파이프 말고, 원하는 파이프를 만들고 싶을 때는 정해진 규칙이 있다.

class SomethingPipe implements PipeTransform

implements PipeTransform을 붙여줘야 한다.

여기에 transform() 메소드를 같이 사용한다.

transform()

첫번째 파라미터는 인자 value
두번째 파이터는 인자에 대한 메타데이터

return값은 route 핸들러로 전해진다.

커스텀 파이프 만들기

먼저 커스텀 파이프를 만들어보자.

boards 폴더 아래에 pipes 폴더 생성 후, board-status-validation.pipe.ts 파일 생성

board-status-validation.pipe.ts 코드

import { ArgumentMetadata, PipeTransform } from '@nestjs/common';

export class BoardStatusValidationPipe implements PipeTransform {
  transform(value: any, metadata: ArgumentMetadata) {
    console.log('value', value);
    console.log('metadata', metadata);

    return value;
  }
}

일단 value와 metadata를 찍어보는 pipe를 생성한다.

controller 코드

  @Patch('/:id/status')
  updateBoardStatus(
    @Param('id') id: string,
    @Body('status', BoardStatusValidationPipe) status: BoardStatus,
  ) {
    return this.boardsService.updateBoardStatus(id, status);
  }

게시물 상태 업데이트 하는 펑션에 @Body('status', BoardStatusValidationPipe) 를 추가한다.
(BoardStatusValidationPipe는 위에서 정의한 pipe 클래스다.)

결과값

펑션 호출하면 값은 업데이트가 되고

console 로 찍은 결과는 이렇게 나온다.

이젠 validation용 파이프를 다시 재정의해보자.

board-status-validation.pipe.ts 코드

import { BadRequestException, PipeTransform } from '@nestjs/common';
import { BoardStatus } from '../board.model';

export class BoardStatusValidationPipe implements PipeTransform {
  readonly StatusOptions = [BoardStatus.PRIVATE, BoardStatus.PUBLIC];

  transform(value: any) {
    value = value.toUpperCase();

    if (!this.isStatusValid(value)) {
      throw new BadRequestException(`${value} isn't in the status options`);
    }

    return value;
  }

  private isStatusValid(status: any) {
    const index = this.StatusOptions.indexOf(status);
    return index !== -1;
  }
}

StatusOptions에 BoardStatus의 PRIVATE, PUBLIC을 정의해준다.
isStatusValid는 요청인자 status가 해당 StatusOptions의 값이 아니면 -1 리턴하는 펑션.
transform에 isStatusValid의 리턴값이 -1일 경우, BadRequestException 예외 처리를 하도록 한다.

결과값

1111 isn't in the status options 라고 Bad Request 처리한다.

profile
Hello, World!

0개의 댓글