[Nest js] basic - Pipe

giyeon·2022년 3월 12일
0

nest js - basic

목록 보기
7/8


이 포스팅은 Youtube 'John Ahn'의 '따라하면서 배우는 NestJS'를 참고했습니다.

⚙️ Pipe ?


Nest js에서 파이프란 @Injectable() 데코레이터 주석이 달린 class를 말해요.

📕 pipe 왜 써요?

  1. Data transformation
  2. Data validation

파이프는 클라이언트가 보내준 데이터에 대한 변형과 유효성체크를 위해서 사용됩니다.
미들웨어 같은 너낌..

파이프는 컨트롤러 경로 처리기에 의해 처리되는 인수에 대해 작동합니다.

Nest js는 메소드가 호출되기 직전에 파이프를 삽입하고, 파이프는 메소드로 향하는 인수를 수신하고 이에 대해 작동합니다.

예를 하나 들어볼게요.
board라는 게시물을 새로 생성하기 위해 클라이언트는 title과 description값을 서버로 보내줍니다.
이런 클라이언트가 보내준 데이터들이 컨트롤러에 가기 전에 한 단계를 거치게 되는데 이것을 Pipe라고 합니다.

Pipe에서 받아온 데이터를 원하는 형식으로 변환시키거나, 정해놓은 규칙에 맞는지 검사를 하고나서 이상이 없다면 컨트롤러에 전달해줘요.

만약 Int값이 와야 하는데 String type인 '7'이 왔다면 이에대해 정수값으로 변환해주거나, title값이 너무 길다 싶으면 에러를 내주는 역할 등을 하고 있어요.


📕 Pipe 사용법

파이프의 범위는 세 가지로 구분이 돼요.

  1. Handler-level
    핸들러 레벨은 아래와 같이 하나의 Handler 요청에 파이프를 넣어주는 방식이에요. @UsePipes 데코레이터를 사용합니다.
  @Post()
  @UsePipes(pipe)
  createBoard(@Body() createBoardDto: CreateBoardDto): Board {
    return this.boardsService.createBoard(createBoardDto);
  }
  1. Parameter-level
    파라미터 레벨은 Handler전체가 아닌 파라미터 하나에 대한 파이프를 말해요.
 @Post()
 createBoard(@Body('title', ParameterPipe) title,): Board {
   return ...
 }
  1. Global-level
    글로벌 레벨은 어플리케이션 전체레벨의 파이프에요.
    클라이언트에서 들어오는 모든 요청이 적용됩니다.
    가장 상단 영역인 main.ts에 넣어주면 적용이 돼요.
async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  app.useGlobalPipes(GlobalPipes);
  await app.listen(3000);
}
bootstrap();

📕 Built-in Pipes

당연히 파이프를 직접 만들어서 사용할 수도 있지만 Nest js에서는 친절하게도 기본적으로 사용할 수 있게끔 미리 만들어놓은 6가지 파이프가 있어요.

  • ValidationPipe
  • ParseIntPipe
  • ParseBoolPipe
  • ParseArrayPipe
  • ParseUUIDPipe
  • DefaultValuePipe

이름을 보면 그대로 기능을 유추할 수 있어요


📕 ValidationPipe from DTO

이번에는 dto 파일에서 유효성 검사를 하고, createBoard() 라는 새로운 board 생성 method에서 Pipe를 적용해보겠습니다.

우선 손쉬운 validation을 지원해주는 라이브러리리 두개가 필요해요.

npm i class-validator class-transformer

설치 후, dto 파일로 가볼게요.

create-board.dto.ts

import { IsNotEmpty } from 'class-validator';

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

@IsNotEmpty()로 클라이언트가 만약 빈값을 보내면 걸러줄 수 있도록 설정했어요.

이게 끝이 아니라 controller에서도 pipe를 적용해주어야 끝이나요.

boards.controller.ts

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

@UsePipes를 통해서 ValidationPipe 를 지정해주면, dto에서 정해놓은 유효성검사 적용이 완료됩니다.


📕 Custom Pipe

이번에는 Nest js 에서 제공하는 Pipe가 아닌 직접 Pipe를 만들어서 적용해볼게요.

파이프를 직접만들려면 PipeTransform이라는 인터페이스를 새롭게 만들 커스텀 파이프에 구현해주어야 해요.
이 PipeTransform 인터페이스는 모든 파이프에서 구현해주어야 하는 필수적인 인터페이스입니다.

그리고 이것과 함께, 모든 파이프에는 transform() method가 있어야 해요. 이 method는 Nest Js가 인자를 처리하기 위해서 사용됩니다.

즉, 파이프를 커스텀하려면

PipeTransform interface

transform() method

이 두개가 필수적으로 들어가야 해요.

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

@Injectable()
export class ValidationPipe implements PipeTransform {
  transform(value: any, metadata: ArgumentMetadata) {
    return value;
  }
}

👀 transform () method
이 메소드는 두 개의 파라미터를 가지게 돼요.
첫번째로 value 라는 처리된 인자의 값과,
두번째로 인자에 대한 메타 데이터를 포함한 객체 입니다.
transform() 메소드에서 return 된 값은 route 핸들러로 전해지고, 만약 예외(Exception)이 발생한다면 코드를 멈추고 클라이언트에 바로 전해져요.
value는 처리된 인자값 이라고 표현을 했는데 그냥 클라이언트가 보내준 값이라고 생각하면 편할것 같아요.

profile
Web , App developer wannabe 🧑🏻‍💻

0개의 댓글