관리 메뉴

bright jazz music

nestjs의 Pipe 본문

Framework/NestJS

nestjs의 Pipe

bright jazz music 2024. 11. 10. 23:06
  1. 정의
  • 핸들러에 전달되는 인자를 전달받기 전에 처리하는 중간 단계의 기능
  • PipeTransform 인터페이스를 구현하는 클래스
  • transform() 메서드를 통해 데이터 변환/검증 수행

 

예시

  @Get(':id')  
  async findOne(@Param('id', ParseIntPipe) id: number) {
    // 여기서 pipe는 @Param()이 아니라 ParseIntPipe이다.
    // @Param 데코레이터(실제로는 함수)에 'id'라는 파라미터 이름과 ParseIntPipe를 매개변수로 전달한다.
    // 실행 순서:
    // 1. @Param이 URL에서 'id' 값을 추출 (예: "123" 문자열)
    // 2. 추출된 값이 ParseIntPipe의 transform 메소드로 전달되어 처리 (문자열 → 숫자 변환)
    // 3. 파이프에서 반환된 값(숫자 123)이 findOne() 핸들러의 id:number 매개변수에 할당된다.
    
    console.log(id)  // 123 (number 타입)
    // return this.catsService.findOne(id);
  }

 

파이프의 내부

 

 

 

2. 주요역할

// 1. 데이터 변환 (Transformation)
@Get(':id')
findOne(@Param('id', ParseIntPipe) id: number) {} // string → number

// 2. 데이터 검증 (Validation)
@Post()
create(@Body(ValidationPipe) createCatDto: CreateCatDto) {}

 

 

3. 작동 순서

@Get(':id')
async findOne(@Param('id', ParseIntPipe) id: number) {
  // 1. @Param 데코레이터가 'id' 파라미터 추출 
  // 2. ParseIntPipe의 transform() 메서드가 처리
  // 3. 변환된 값이 핸들러의 매개변수로 전달
}

 

4. 에러처리

@Get(':id')
findOne(@Param('id', new ParseIntPipe({
  errorHttpStatusCode: 400,
  exceptionFactory: (error) => new BadRequestException('숫자만 가능합니다')
})) id: number) {}

 

5. 특징

  • DI가 필요한 경우에만 @Injectable() 데코레이터 필요
  • 여러 파이프를 체이닝할 수 있음
  • 내장 파이프(ParseIntPipe, ValidationPipe 등) 제공
  • 커스텀 파이프 구현 가능

 

장점

  • 핸들러 로직과 데이터 검증/변환 로직 분리
  • 재사용 가능한 검증 로직 구현
  • TypeScript 타입 안정성 보장
  • 일관된 에러 처리 가능

 

 

참고

 

파이프의 내부

import { ArgumentMetadata, PipeTransform } from '../interfaces/features/pipe-transform.interface';
import { ErrorHttpStatusCode } from '../utils/http-error-by-code.util';
/**
 * @publicApi
 */
export interface ParseIntPipeOptions {
    errorHttpStatusCode?: ErrorHttpStatusCode;
    exceptionFactory?: (error: string) => any;
    optional?: boolean;
}
/**
 * Defines the built-in ParseInt Pipe
 *
 * @see [Built-in Pipes](https://docs.nestjs.com/pipes#built-in-pipes)
 *
 * @publicApi
 */
export declare class ParseIntPipe implements PipeTransform<string> {
    protected readonly options?: ParseIntPipeOptions;
    protected exceptionFactory: (error: string) => any;
    constructor(options?: ParseIntPipeOptions);
    /**
     * Method that accesses and performs optional transformation on argument for
     * in-flight requests.
     *
     * @param value currently processed route argument
     * @param metadata contains metadata about the currently processed route argument
     */
    transform(value: string, metadata: ArgumentMetadata): Promise<number>;
    /**
     * @param value currently processed route argument
     * @returns `true` if `value` is a valid integer number
     */
    protected isNumeric(value: string): boolean;
}

 

파이프트랜스폼 인터페이스

import { Type } from '../type.interface';
import { Paramtype } from './paramtype.interface';
export type Transform<T = any> = (value: T, metadata: ArgumentMetadata) => any;
/**
 * Interface describing a pipe implementation's `transform()` method metadata argument.
 *
 * @see [Pipes](https://docs.nestjs.com/pipes)
 *
 * @publicApi
 */
export interface ArgumentMetadata {
    /**
     * Indicates whether argument is a body, query, param, or custom parameter
     */
    readonly type: Paramtype;
    /**
     * Underlying base type (e.g., `String`) of the parameter, based on the type
     * definition in the route handler.
     */
    readonly metatype?: Type<any> | undefined;
    /**
     * String passed as an argument to the decorator.
     * Example: `@Body('userId')` would yield `userId`
     */
    readonly data?: string | undefined;
}
/**
 * Interface describing implementation of a pipe.
 *
 * @see [Pipes](https://docs.nestjs.com/pipes)
 *
 * @publicApi
 */
 
 //!!!!!!!!!!! 여기에 있다 !!!!!!!!!
export interface PipeTransform<T = any, R = any> {
    /**
     * Method to implement a custom pipe.  Called with two parameters
     *
     * @param value argument before it is received by route handler method
     * @param metadata contains metadata about the value
     */
    transform(value: T, metadata: ArgumentMetadata): R;
}
Comments