개인의 기록
  • 소개
  • 프로젝트
  • 글
  • 링크

© 2026 newgirok

← 글 목록

NestJS Pipe — 입력 데이터의 검증과 변환을 담당하는 파이프

2025년 3월 12일
NestJSPipeValidationPipeParseIntPipeTransform

NestJS에서 클라이언트가 보내는 데이터는 항상 신뢰할 수 없다. Pipe는 Controller에 도달하기 전에 데이터를 검증(Validation)하거나 원하는 타입으로 변환(Transformation)하는 역할을 담당한다. 잘못된 입력을 Controller 안쪽까지 끌고 들어가는 대신, 경계에서 즉시 차단하거나 정제하는 것이 핵심이다.

Pipe의 실행 위치

Client Request
     │
     ▼
[ Middleware ]
     │
     ▼
[ Guard ]
     │
     ▼
[ Interceptor (before) ]
     │
     ▼
  [ Pipe ]  ◀── 여기서 검증 / 변환
     │
     ▼
[ Controller Handler ]

Pipe는 Guard 이후, Controller Handler 직전에 실행된다. 검증 실패 시 Handler는 아예 호출되지 않고 예외가 즉시 반환된다.

PipeTransform 인터페이스

모든 Pipe는 PipeTransform 인터페이스를 구현해야 한다. transform(value, metadata) 메서드 하나로 구성된다.

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

@Injectable()
export class UpperCasePipe implements PipeTransform {
  transform(value: string, metadata: ArgumentMetadata): string {
    return value.toUpperCase();
  }
}

ArgumentMetadata — type('body' | 'query' | 'param' | 'custom'), metatype, data(데코레이터에 전달된 키 이름)를 포함한다.

transform이 값을 반환하면 그 값이 Handler에 전달되고, 예외를 던지면 즉시 에러 응답이 반환된다.

내장 Pipe

NestJS는 자주 쓰이는 변환 Pipe를 기본 제공한다.

Pipe역할
ParseIntPipe문자열을 정수로 변환, 실패 시 400 반환
ParseUUIDPipeUUID 형식 검증
ParseBoolPipe'true'/'false' 문자열을 boolean으로 변환
DefaultValuePipe값이 undefined일 때 기본값 설정
ValidationPipeclass-validator 데코레이터 기반 전체 검증
@Get(':id')
findOne(@Param('id', ParseIntPipe) id: number) {
  return this.usersService.findOne(id);
}

'abc'처럼 정수로 변환 불가능한 값이 오면 ParseIntPipe가 자동으로 400 Bad Request를 반환한다.

ValidationPipe와 class-validator 연동

ValidationPipe는 class-validator와 class-transformer 라이브러리를 활용해 DTO 클래스에 선언된 데코레이터를 기반으로 검증을 수행한다.

npm install class-validator class-transformer
// create-user.dto.ts
import { IsString, IsEmail, MinLength } from 'class-validator';

export class CreateUserDto {
  @IsString()
  @MinLength(2)
  name: string;

  @IsEmail()
  email: string;
}
// users.controller.ts
@Post()
create(@Body(ValidationPipe) dto: CreateUserDto) {
  return this.usersService.create(dto);
}

class-validator — 데코레이터 방식으로 클래스 프로퍼티에 검증 규칙을 선언하는 라이브러리. class-transformer와 함께 사용해야 plain object를 클래스 인스턴스로 변환할 수 있다.

@UsePipes로 범위 지정

Pipe는 메서드 단위, 컨트롤러 단위, 전역 단위로 적용할 수 있다.

// 전역 적용 — main.ts
app.useGlobalPipes(new ValidationPipe({ whitelist: true, forbidNonWhitelisted: true }));

// 컨트롤러 또는 메서드 단위
@UsePipes(new ValidationPipe())
@Post()
create(@Body() dto: CreateUserDto) { ... }

whitelist: true는 DTO에 정의되지 않은 프로퍼티를 자동으로 제거한다. forbidNonWhitelisted: true를 함께 설정하면 허용되지 않은 필드가 포함될 경우 400 에러를 반환해 보안성을 높인다.

커스텀 Pipe에서 예외 던지기

변환에 실패했을 때 직접 예외를 제어하려면 BadRequestException을 던진다.

@Injectable()
export class ParsePositiveIntPipe implements PipeTransform {
  transform(value: string): number {
    const val = parseInt(value, 10);
    if (isNaN(val) || val <= 0) {
      throw new BadRequestException(`${value}는 양의 정수가 아닙니다.`);
    }
    return val;
  }
}

Controller 안에서 if 분기로 같은 처리를 반복하는 대신, Pipe 하나로 재사용 가능한 검증 단위를 만들 수 있다.

← 이전 글NestJS Guard — 인증과 인가를 처리하는 실행 가드
다음 글 →NestJS Interceptor — Controller 전후를 가로채는 방법