[NestJS] Pipe 이용

올리브수
|2024. 1. 15. 23:04
728x90

Pipe?

  • @Injectable() 로 주석이 달린 클래스
  • data transformation
    • 입력 데이터를 원하는 형식으로 변환
  • data validation
    • 입력 데이터를 평가하고 유효성을 검사
  • 메소드가 호출되기 직전에 파이프를 삽입하고 파이프는 메소드로 향하는 인수를 수신하고 이에 대해 작동

 

Binding Pipes

  1. Handler-level Pipes
    1. 핸들러 레벨에서 @UsePipes 를 이용해서 사용한다.
  2. Parameter-level Pipes
    1. 파라미터 하나에만 해당
  3. Global Pipes
    1. 클라이언트에서 들어오는 모든 요청에 적용되며 bootstrap(main.ts) 코드에 삽입한다.

 

Built-in Pipes

  • Nest JS의 기본적으로 사용할 수 있게 만들어 놓은 6가지 파이프
  1. ValidationPipe
  2. ParseIntPipe
  3. ParseBoolPipe
  4. ParseArrayPipe
  5. ParseUUIDPipe
  6. DefaultValuePipe

 

Set up

$ yarn add class-validator class-transformer

 

Validation Pipe

  • handler level pipe
  • 값 삽입시, title , description 값이 있는지 유효성 검사

📄 boards.controller.ts

...

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

...

 

📄 create-board.dto.ts

import { IsNotEmpty } from 'class-validator';

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

 

 

⌛ Test

  • request body
    • HTTP/1.1 POST /boards
{
    "title": "",
    "description": ""
}

 

  • response body
{
    "message": [
        "title should not be empty",
        "description should not be empty"
    ],
    "error": "Bad Request",
    "statusCode": 400
}

 

에러 표출

  • 예외 인스턴스를 생성해서 적용해준다.
  • 다음과 같이 에러 인스턴스를 생성할 수 있다.
    • 이때, 내가 원하는 메시지를 출력하려면 인자로 해당 메시지를 넣어준다.
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;
  }

 

커스텀 파이프

  • PipeTransform 인터페이스를 새로 만들 커스텀 파이프에 구현해줘야한다.
  • PipeTransform 인터페이스는 모든 파이프에서 구현해줘야하는 인터페이스이며 모든 파이프는 transform() 을 필요로 한다.
  • 커스텀 파이프 transform() 의 파라미터
    • value : 실제로 넘어오는 값
    • metadata : type, data와 같은 값
import { PipeTransform, ArgumentMetadata } from '@nestjs/common';

export class BoardStatusValidationPipe implements PipeTransform {
  transform(value: any, metadata: ArgumentMetadata) {
    console.log('value', value); // value what
    console.log('metadata', metadata); // metadata { metatype: [Function: String], type: 'body', data: 'status' }

    return value;
  }
}

 

readonly class property

  • readonly prefix?
    • 클래스 외부에서 접근은 할 수 있지만 변경은 하지 못한다.

 

커스텀 파이프 실제 구현하기

  • 상태(status)가 PUBLICPRIVATE 만 올 수 있게끔 커스텀 파이프를 생성한다.

 

📄 board-status-validation.pipe.ts

import { PipeTransform, BadRequestException } from '@nestjs/common';
import { BoardStatus } from '../boards.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 a valid board status`);
    }

    return value;
  }

  private isStatusValid(status: any) {
    const index = this.StatusOptions.indexOf(status); // 값이 없으면 -1 리턴
    return index !== -1;
  }
}
  • StatusOptions 로 일정한 값만 들어올 수 있게 정의한다.
  • 맞지 않는 값이 들어오게 되면 BadRequestException 리턴

 

  • ❌ Error Case
  • Request Body
{
    "status": "what"
}
  • Response Body
{
    "message": "WHAT isn't a valid board status",
    "error": "Bad Request",
    "statusCode": 400
}

 

  • ⭕ Correct Case
  • Request Body
{
    "status": "PRIVATE"
}
  • Response Body
{
    "id": "2887e410-1be1-11ee-9f95-21c62dc8381f",
    "title": "test",
    "description": "test description",
    "status": "PRIVATE"
}

 

 

 

728x90

'🏠 Framework > NestJS' 카테고리의 다른 글

[NestJS] TypeORM  (21) 2024.01.15
[NestJS] CRUD 구현  (0) 2024.01.15
[NestJS] NestJS 기본 요소  (20) 2024.01.15
[NestJS] Overview  (0) 2023.06.28