본문 바로가기
Node ( + nest.js)

[nestjs] 02. Pipe - 파이프

by doozzuri 2023. 1. 14.
반응형

1. Pipe -파이프

  • @injecable() 데코레이터로 주석이 달린 클래스.
  • data transformation(데이터 변형)과 data validation(유효성 체크)을 위해 사용.
  • 컨트롤러 경로 처리기에 의해 처리되는 인수에 대해 작동.
  • 메소드가 호출되기 직전(ex. @Get ..) 파이프를 삽입하고 파이프는 메소드로 향하는 인수를 수진하고 이에 대해 작동

 

2. Data Transformation

  • 입력데이터를 원하는 형식으로 변환 (문자 → 정수)
  • 만약 숫자를 받길 원하는데 문자열 형식으로 온다면 파이프에서 자동으로 숫자로 바꿔줌.

ex. string ‘7’ → Integer 7

 

3. Data Validation

  • 입력 데이터를 평가하고 유요한 경우 변경되지 않은 상태로 전달.
  • 그렇지 않으면 데이터가 올바르지 않을때 예외를 발생.

ex. 10이하여야하는데 10자 이상이면 에러 발생.

 

4. Binding Pipes

1) Handler-level Pipes

  • 핸들러 레벨에서 @UsePipes() 를 이용해 사용.
  • 이 파이프는 모든 파라미터에 적용됨 (title, description)
@Post()
@UsePipes(pipe)
createBoard(
	@Body('title') title,
	@Body('description') description
){}
//Controller
@Post()
@UsePipes(ValidationPipe)
createBoard(@Body() createBoadDto: CreateBoardDto): Board{
    return this.boardService.createBoard(createBoadDto);
}

//CreateBoardDto
import { IsNotEmpty } from "class-validator";

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

    @IsNotEmpty()
    description: string;
}

 

2) Parameter-level Pipes

  • 파라미터 레벨의 파이프이기에 특정한 파라미터에만 적용이 되는 파이프.
  • title 만 파라미터 파이프가 적용됨.
@Post()
createBoard(
	@Body('title', PrameterPipe) title,
	@Body('description') description
){}

 

3) Global Pipes

  • 글로벌 파이프로서 애플리케이션 레벨의 파이프.
  • 클라이언트에서 들어오는 모든 요청에 적용됨.
  • 가장 상단 영역인 main.ts에 넣어줌
async function bootstrap(){
	const app = await NestFactory.create(AppModule);
	app.useGlobalPipes(GlobalPipes);
	await app.listen(3000);
}

bootstrap();

 

4) Built-in Pipes

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

ex. ParseIntPipe

@Get(':id')
findOne(@Param('id', ParseIntPipe) id: number){
	return;
}

 

5) Custom Pipe

  • PipeTransform 이라는 인터페이스를 새롭게 만들 Custom Pipe에 구현해줘야함.
  • PipeTransform 인터페이스는 모든 파이프에 구현해줘야하는 인터페이스.
  • 모든 파이프는 transform() 메서드를 필요로함.
  • transform() 메서드는 NestJS가 인자(arguments)를 처리하기 위해 사용됨.
import { ArgumentMetadata, BadRequestException, PipeTransform } from '@nestjs/common'
import { BoardStatus } from '../board.model';

export class BoardStatusValidationPipe implements PipeTransform {

    //외부에서 읽을 순 있지만 변경은 불가.
    readonly StatusOption = [
        BoardStatus.PRIVATE,
        BoardStatus.PUBLIC
    ]

	transform(value: any, metadata: ArgumentMetadata) {		
        value = value.toUpperCase();
    
        if( !this.isStatusValid(value)){
            throw new BadRequestException(`${value} isn't in the status`);
        }
		return value; 
	}

    private isStatusValid(status: any){
        const index = this.StatusOption.indexOf(status);
        return index !== -1;
    }
}
  • transform() 메서드 - 두개의 파라미터를 가짐.

(1) 첫번째 파라미터 : 처리가 된 인자의 값(value)

(2) 두번째 파라미터 : 인자에 대한 메타데이터를 포함한 객체.

  • transform()메서드에서 return된 값은 라우터 핸들러로 전해짐.
  • 만약 예외가 발생하면 클라이언트에 바로전해짐.

 

5. Install

  • class-validator, class-transformer
yarm add class-validator class-transformer
  • menual

GitHub - typestack/class-validator: Decorator-based property validation for classes.

 

6. Exception - service

1) 특정 게시물을 찾을때 없는 경우 예외 처리

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;
}

 

 

2) 없는 게시물을 지우려 할때 예외 처리

deleteBoard(id: string): void {
    const found = this.getBoardById(id);

    if(!found){
        throw new NotFoundException()
    }
    this.boards = this.boards.filter(board => board.id !== found.id);
}
반응형