NestJS의 Pipe에 대해

Younha Lee·2026년 1월 20일

NestJS

목록 보기
2/2


NestJS의 Enhancer 중 Pipe에 대해 정리해보려고해요.
우선 공식문서에는 Pipe가 어떨 때 쓰이는지 다음과 같이 명시되어있어요.

transformation: transform input data to the desired form (e.g., from string to integer)
요청으로 온 데이터를 원하는 형태로 변환 (예: string에서 integer로)
validation : evaluate input data and if valid, simply pass it through unchanged; otherwise, throw an exception
요청 데이터를 평가하고, 유효하면 넘기고 그렇지 않으면 예외를 던짐

Pipe는 Controller에 제공되는 argument들에 적용돼요.
argument 에는 @Body, @Param 등 이미 우리가 보편적으로 사용하고 있는 Annotation들이 포함돼요.
Pipe는 argument 데이터를 가공한 후 Controller 메서드로 값들을 넘겨줘요.

  • 즉, Controller의 메소드들이 실행되기 이전에 pipe가 먼저 실행돼요.

4개의 Pipe

Pipe는 크게 4개의 종류로 나눌 수 있어요.
1. Global Pipe - Class-Validator를 사용할 수 있게 하기 위해서bootstrap 함수 안에 app.useGlobalPipes(new ValidationPipe()); 를 추가할 수 있어요.
2. Controller Pipe - Controller에 적용되는 Pipe, @UsePipes() 안에 적용하고 싶은 pipe를 넣어 사용할 수 있어요
3. Route Pipe - 메서드 위에 UsePipes()를 넣고 적용하고 싶은 pipe를 넣어 사용할 수 있어요.
4. Route Parameter Pipe - @Param() 안에 적용하고 싶은 pipe를 넣어 사용할 수 있어요.

이 중 1번과 4번을 가장 많이 사용하게 돼요.

기본으로 제공되는 Pipe들

  • ValidationPipe - 모든 Validation Annotation 이 적용되도록 해줘요.
  • Parse~~Pipe - ~~ 값으로 변환, 검증해요.
  • 이 기본 파이프에는 Int, Float, Bool, Array, UUID, Enum, File 등이 있어요. (File보다는 Multer를 주로 이용해요.)
  • DefaultValuePipe - 기본값을 설정해요.

    변환까지 할 것인지, 검증만 할 것인지는 개발자가 Pipe를 어떻게 구현하는지에 따라 달라져요.

Custom Pipe

Pipe는 PipeTransform이라는 인터페이스를 통해 구현할 수 있어요.

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

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

PipeTransform 인터페이스는 transform이라는 메서드를 갖는데, 이 메서드 내의 인자인 ArgumentMetadata 타입을 살펴볼게요.

interface ArgumentMetadata {
  type: 'body' | 'query' | 'param' | 'custom';
  metatype?: Type<unknown>;
  data?: string;
}

ArgumentMetadatatype이라는 속성을 갖습니다. Pipe가 어디에 쓰였는지에 따라 type은 그때그때 다른 값이 부여되는데, 만약 @Body() 데코레이터에 쓰였다면 'body', @Query() 데코레이터에 쓰였다면 'query', 웹소켓의 이벤트 리스너에 쓰였다면 'custom'입니다.

여기서 중요한 것은 내부 속성인 type값만 달라질 뿐이지, 동일한 Pipe 구현체를 어디서든 쓸 수 있다는 점이에요.

예시 - ParseIntPipe

string을 받아 int인지 검증하는 ParseIntPipe를 만들어볼게요.

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

@Injectable()
// 제네릭에는 input 받을 타입과 return 할 타입이 들어가요
export class ParseIntPipe implements PipeTransform<string, number> {
  transform(value: string, metadata: ArgumentMetadata): number {
    // 10진수로 변환
    const val = parseInt(value, 10);
    // 숫자가 아닌 경우 Exception 던짐
    if (isNaN(val)) {
      throw new BadRequestException(
        `Validation failed (parameter '${metadata.data}') : ${value} is not a number`
      );
    }
    return val;
  }
}

다음 포스팅에 Custom Pipe가 나올 예정이라 미리 Pipe에 대해 정리해봤어요.

profile
할 땐 하고 놀 땐 노는 일일놀놀입니다.

0개의 댓글