View

TIL | NestJS_REST_API_Validation

Melody:) 2021. 10. 11. 18:44

Validation

 

 movieData와 updateData의 데이터 타입에 따른 예외처리

 

1. movieData

DTO(데이터 전송 객체 , Data Transfer Object) 생성

dto 폴더 생성 및 create-movie.dto.ts 파일생성하여 dto 타입을 지정해준다.

// 클라이언트가 보낼수 있는 전송객체
export class CreateMovieDto {
    readonly  title: string;
    readonly  year: number;
    readonly  genres: string[];
}

유효성 검사 1 : ValidationPipe()

main.ts에 ValidationPipe추가
app.useGlobalPipes(new ValidationPipe());

import { ValidationPipe } from '@nestjs/common';
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  app.useGlobalPipes(new ValidationPipe());
  await app.listen(3000);
}
bootstrap();

유효성 검사 2 : class-validator

  1. 설치
npm i class-validator class-transformer
  1. dto/create-movie.dto.ts에 class-validator 추가하여 유효성 검사.
import { IsNumber, IsString } from "class-validator";

export class CreateMovieDto {  
@IsString()  
readonly title: string;  
@IsNumber()  
readonly year: number;  
@IsString({each : true}) // Validation 옵션  
readonly genres: string\[\];  
}

결과는 아래와 같으며, value의 type error를 잡아준다.

하지만, 보는 것처럼 잘못된 키가 들어왔을 경우에 대한 Validation을 하지 못한다.

{  
"123" : "123"  
}  
//결과  
{  
"statusCode": 400,  
"message": \[  
"title must be a string",  
"year must be a number conforming to the specified constraints",  
"each value in genres must be a string"  
\],  
"error": "Bad Request"  
}

{  
"title" : "기생충",  
"director": "봉준호",  
"year" : "2019",  
"genre" : "스릴러"  
}  
//결과  
{  
"statusCode": 400,  
"message": \[  
"year must be a number conforming to the specified constraints",  
"each value in genres must be a string"  
\],  
"error": "Bad Request"  
}

 

ValidationPipe의 옵션

1. whitelist : true로 설정하면 아무 decorator도 없는 어떠한 property의 object를 거릅니다.

If set to true validator will strip validated object of any properties that do not have any decorators.
Tip: if no other decorator is suitable for your property use @Allow decorator.

 

2. forbidNonWhitelisted : true로 설정하면 decorator가 없는 속성이 들어오면 예외처리됨.

If set to true, instead of stripping non-whitelisted properties validator will throw an error

 

3. transform : true로 설정하면 유저가 보낸 값을 controller에서 설정한 원하는 형식으로 바꿀 수 있음.

(ex url의 path parameter는 무조건 string으로 들어오므로 number로 변환하여 사용하여야 했으나, 이 옵션을 주게되면, 자동으로 number로 변환되어 들어옴. console.log(typeof id) )

main.ts

import { ValidationPipe } from '@nestjs/common';  
import { NestFactory } from '@nestjs/core';  
import { triggerAsyncId } from 'async\_hooks';  
import { AppModule } from './app.module';

async function bootstrap() {  
const app = await NestFactory.create(AppModule);  
app.useGlobalPipes(new ValidationPipe({  
whitelist : true,  
forbidNonWhitelisted : true,  
transform: true  
}));  
await app.listen(3000);  
}  
bootstrap();

 

create_movie.dto.ts

import { IsNumber, IsString } from "class-validator";

export class CreateMovieDto {  
@IsString()  
readonly title: string;

@IsNumber()
readonly year: number;

@IsString({each : true})
readonly genres: string[];
}

 

movie/controller.ts

import { Body, Controller, Delete, Get, Param, Patch, Post, Put, Query } from '@nestjs/common';  
import { CreateMovieDto } from './dto/create-movie.dto';  
import { Movie } from './entities/movie.entity';  
import { MoviesService } from './movies.service';

@Controller('movies')  
export class MoviesController {

constructor(private readonly moviesService: MoviesService) {}

@Get()
getAll(): Movie[] {
    return this.moviesService.getAll();
}

@Get('search')
search(@Query('year') searchingYear:string) {
    return `we are searching for a movie made after ${searchingYear}`;
}

@Get(':id')
getOne(@Param('id') movieId: number): Movie{
    return this.moviesService.getOne(movieId);
}

@Post()
create(@Body() movieData: CreateMovieDto){
    console.log(movieData);
    return this.moviesService.createOne(movieData);
}

@Delete(':id')
remove(@Param('id') movieId:number){
    return this.moviesService.deleteOne(movieId);
}

@Patch(':id') 
path(@Param('id') movieId:number, @Body() updateData) {
    return this.moviesService.update(movieId, updateData);
}

}

 

movie/service.ts

import { Injectable, Delete, NotFoundException } from '@nestjs/common';  
import { CreateMovieDto } from './dto/create-movie.dto';  
import { Movie } from './entities/movie.entity';

@Injectable()  
export class MoviesService {  
private movies: Movie\[\] = \[\];

getAll(): Movie[] {
    return this.movies;
}

getOne(id:number): Movie {
    const movie =  this.movies.find(movie => movie.id === id);
    if (!movie) {
        throw new NotFoundException(`Movie with ID ${id} not found.`)
    } 
    return movie;
}

deleteOne(id:number) {
    this.getOne(id);
    this.movies = this.movies.filter(movie => movie.id !== id);
}

createOne(movieData: CreateMovieDto): boolean {
    this.movies.push({
        id: this.movies.length + 1,
        ...movieData
    })        
    return true; 
}

update(id:number, updateData) {
    const movie = this.getOne(id);
    this.deleteOne(id);
    console.log(this.getAll())
    this.movies.push({...movie, ...updateData});
}

}

 


2. updateData

DTO(데이터 전송 객체 , Data Transfer Object) 생성

 

방법 1. update-movie.dto.ts 파일생성하여 dto 타입을 지정해주는데, 부분만 수정할 수 있으니, ?의 옵션을 준다.

import { IsNumber, IsString } from "class-validator";

export class UpdateMovieDto {  
@IsString()  
readonly title?: string;

@IsNumber()
readonly  year?: number;

@IsString({each : true})
readonly  genres?: string[];
}

 

방법 2. mapped-types

: 타입을 변환시키고 사용할 수 있게하는 패키지

[https://www.npmjs.com/package/@nestjs/mapped-types]

 

PartialType()
설치

npm i --save @nestjs/mapped-types

 

1.  Create-dto의 타입을 updare-dto의 타입으로 변환하기

import { PartialType } from "@nestjs/mapped-types";  
import { CreateMovieDto } from "./create-movie.dto";

export class UpdateMovieDto extends PartialType(CreateMovieDto){
}

 

2. @IsOptional() : 장르에 옵션주기

import { IsNumber, IsOptional, IsString } from "class-validator";

export class CreateMovieDto {  
@IsString()  
readonly title: string;

@IsNumber()
readonly  year: number;

@IsOptional()
@IsString({each : true})
readonly  genres: string[];
}

NestJS가 지원하는 class validaor는 정말 유용하다.
개발자가 일일이 에러를 잡아줄필요 없이,
실시간으로 NestJS가 서버를 보호해주고 있다.
class validaor의 많은 옵션들을 잘 활용해보도록 하자!

'NestJS' 카테고리의 다른 글

TIL | NestJS_URI_parameter_받아오기  (0) 2021.10.17
TIL | NestJS_REST_API_Module  (0) 2021.10.11
TIL | NestJS_REST_API_Service  (0) 2021.10.11
TIL | NestJS_REST_API_Controller  (0) 2021.10.11
TIL | NestJS_REST_API_Settings  (0) 2021.10.11
Share Link
reply
«   2024/10   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31