끄적이는 개발노트

NestJS 연습 프로젝트(Movie) - DTO와 유효성검사 본문

JavaScript/NestJS

NestJS 연습 프로젝트(Movie) - DTO와 유효성검사

크런키스틱 2021. 10. 1. 17:07
728x90

이번 포스트에서는 create와 update에 타입을 부여하기 위해 사용된 DTO기능을 알아본다.

 

1. DTO란?

DTO (Data Transter Object)
데이터 전송 객체로 프로세스 간에 데이터를 전달하는 객체

DTO는 프로세스 간에 호출의 수를 줄이고 하나의 호출만으로 서비스가 이용되게 해준다.

따라서, 개발자에게 코드를 더 간결하게 만들어주고, NestJS에서는 들어오는 쿼리에 대해 유효성을 검사하게 해준다.

 

2. npm 설치

클래스 유효성 검사와 이따가 알아볼 기능을 위해 npm을 미리 설치한다.

$> npm i class-validator class-transformer @nestjs/mapped-types

 

3. DTO 파일 생성

dto폴더를 만들고 그 안에 필요한 파일들을 만들어준다.

우선, create를 위한 dto파일부터 살펴보자.

// create-movie.dto.ts

export class CreateMovieDto {
    readonly title: string;
    readonly year: number;
    readonly genres: string[];
}

이렇게 dto파일을 생성한 후에 다음과 같이 create에 타입을 선언해준다.(update도 마찬가지)

이렇게 타입을 지정해주면, movieData는 CreateMovieDto라는 타입을 갖게 된다.

타입은 어플리케이션이 작동할 때 도움을 주는데 위와 같은 코드로는 간결함은 주지만, 유효성 검사가 이루어지지는 않는다.

즉, 타입에 선언한 것 외에 값(ex. director: "me")을 넣어도 생성이 된다.

이러한 상황을 막기 위해 필요한 것이 유효성 검사이고, NestJS에서는 앞서 설치한 npm class-validator를 통해 손쉽게 가능하다.

이를 위해서 main.ts에 유효성 검사 파이프를 만든다.

 

4. 파이프 생성

파이프는 express의 미들웨어와 비슷한 기능으로 이해하면 된다.

// main.ts

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

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

우리가 사용할 파이프를 NestJS 어플리케이션에 넘겨준다.

유효성 검사 파이프를 위해 사용하는 것이 ValidationPipe로 위와 같이 설정해준다.

ValidationPipe의 옵션들 중 사용한 옵션들을 살펴보자.

 

  • whitelist: true -> 데코레이터가 존재하지 않는 속성의 객체를 거름
  • forbidNonWhitelisted: true -> 존재하지 않는 값을 보낼 경우, 존재하면 안되는 요소로 메세지 출력
  • transform: true -> 사용자가 전송한 값을 원하는 실제 타입으로 변환

 

whitelist와 forbidNonWhitelisted는 유효성 검사를 강화해주는 옵션들로 다음과 같은 메세지를 출력한다.

transform은 이전 포스트에서 언급한 id의 타입에 관한 내용으로, 일반적으로 url을 통해 받는 데이터는 string이다. 하지만, 우리가 원하는 id의 타입은 number인데 기존에는 이 타입을 직접 변환해야했다. 하지만, npm class-transform을 설치하고 transform: true로 설정하면 그런 변환 코드 없이 자동으로 변환해준다.

 

5. DTO 파일 수정

이제 다시 create-movie.dto.ts로 가서 기존의 내용들에 유효성 검사를 추가한다.

// create-movie.dto.ts

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

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

    @IsNumber()
    readonly year: number;

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

title과 year은 각각 타입이 string, number이어야만 한다.

genres는 배열이지만 각각은 string이어야 하기 때문에 @IsString데코레이터에 each: true 옵션을 부여한다.

마지막으로, genres는 선택요소임을 나타낸다.

 

// update-movie.dto.ts

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

export class UpdateMovieDto extends PartialType(CreateMovieDto) {}

update dto에는 타입을 변환시키고 사용가능하게 해주는 npm mapped-types의 PartialType을 사용했다.

NestJS의 놀라운 기능 중 하나인데, update dto는 사실 create dto와 다를게 없다.

단지, 필수사항이 아니게만 바꿔주면 된다.

따라서, CreateMovieDto를 base로 두는 PartialType으로 UpdateMovieDto를 생성해주고, controller와 service의 업데이트 부분에 타입으로 지정해주면 끝난다.


이상으로, NestJS의 테스트를 제외한 기본 사용법에 대해 전부 알아보고 직접 사용해보았다.

본인도 아직 NestJS 입문자이기 때문에 실제 프로젝트는 아직 만들어보지 못했고, 깊은 공부가 더 필요하다.

하지만, 분명 기존의 Node.js와 Express.js에 비교하여 코딩하기가 훨씬 수월하고 체계적으로 변했다는 것만은 틀림없다.

 

다음 포스트에서는 Unit Test와 E2E Test를 통해 NestJS의 기본 사용법을 마무리한다.

728x90