본문 바로가기
Back-end/기초부터 따라하는 nest.js

#15. 기초부터 따라하는 Nest.js : Class-validator와 Pipe

by hsloth 2023. 5. 20.

 

해당 포스팅은 nest.js 9.0.0 버전, typeorm 0.3.x 버전을 기준으로 작성되었습니다.
모든 글은 작성자의 주관이 100% 담겨있기 때문에 부정확할 수 있습니다.

 

#pre. 터미널을 켜고 프로젝트 폴더로 이동

https://suloth.tistory.com/44

 

#0-1. 기초부터 따라하는 nest.js : 터미널 키는 법 + 터미널에서 작업 폴더 이동

윈도우 윈도우는 윈도우+R 버튼을 누른 후, cmd 를 입력하여 터미널을 킵니다. 혹은 윈도우 버튼을 눌러서 검색창에 cmd를 검색하면 터미널이 나올텐데 그걸 실행시켜주시면 됩니다. Mac OS Mac의 경

suloth.tistory.com

 
위의 링크의 내용을 참고하여 study 폴더로 이동해줍니다.
그리고 code . 명령어를 통해 vscode를 열어줍니다.


Class-validator


Class-validator는 데코레이터를 이용하여 데이터의 유효성을 검증할 수 있게 하는 라이브러리입니다.

조금 더 쉽게 말하면 클라이언트로부터 온 데이터가 해당 타입과 일치하는지 검증해준다고 생각하면 됩니다.

DTO나 Entity로 들어오는 데이터를 자동으로 검증 해줍니다.

 

Class-validator도 밑에서 설명할 pipe의 한 종류입니다.

 

먼저, class-validator를 설치해줍시다.

npm i class-validator class-transformer

 

그리고, ValidationPipe를 사용할 수 있도록 설정해줍시다.

두 가지 방법이 있습니다.

 

1. main.ts 파일에서 전역으로 사용할 수 있도록 설정해준다. 이때, ExceptionFilter보다 먼저(위에서) 설정을 해주어야 합니다.

async function bootstrap() {
  const app = await NestFactory.create(AppModule);

  ...

  app.useGlobalPipes(new ValidationPipe());

  ...

  await app.listen(3000);
}
bootstrap();

 

2. AppModule에 의존성주입을 하여 Providers에 등록해준다.

@Module({
  ...
  
  providers: [
    ...
    {
      provide: APP_PIPE,
      useClass: ValidationPipe,
    },
    ...
  ],
})
export class AppModule {}

그러면, 이제부터 Dto와 Entity에 Validation Pipe를 붙일 수 있습니다.

Entity에 validation pipe를 적용하는 이유는 PickType을 써서 Dto를 생성할 경우 검증하기 위해 사용합니다.

 

저희는 아래의 포스팅에서 CreateArticleDto를 만들었습니다.

https://suloth.tistory.com/96

 

#12. 기초부터 따라하는 Nest.js : Dto와 Swagger

해당 포스팅은 nest.js 9.0.0 버전, typeorm 0.3.x 버전을 기준으로 작성되었습니다. 모든 글은 작성자의 주관이 100% 담겨있기 때문에 부정확할 수 있습니다. #pre. 터미널을 켜고 프로젝트 폴더로 이동 ht

suloth.tistory.com



그래서 저희는 Entity에 class-validator를 적용해보도록 하겠습니다.

해당 Dto에서는 title과 content만 사용하기 때문에 일단, 그 두 개만 적용해보도록 하겠습니다.

import { Column, Entity, JoinColumn, ManyToOne, OneToMany } from 'typeorm';
import { CommentEntity } from './comment.entity';
import { CommonBigPKEntity } from './common/common.entity';
import { UserEntity } from './user.entity';
import { ApiProperty } from '@nestjs/swagger';
import { IsString } from 'class-validator';

@Entity('Article')
export class ArticleEntity extends CommonBigPKEntity {
  @ApiProperty({
    example: '게시글 제목입니다.',
    description: '게시글 제목',
    required: true,
  })
  @IsString()
  @Column('varchar', { unique: false, nullable: false })
  title: string;

  @ApiProperty({
    example: '게시글 내용입니다.',
    description: '게시글 내용',
    required: true,
  })
  @IsString()
  @Column('text', { unique: false, nullable: false })
  content: string;

  ...
}

 

중간의 @IsString() 이라는 데코레이터가 추가되었습니다.

이 데코레이터는 해당 속성이 String임을 명시해줌과 동시에, string타입이 아닌 값이 들어오면 에러를 뱉도록 되어있습니다.

 

그러면 이제 서버를 시작해봅시다.

npm run start:dev 명령어를 통해 서버를 시작해줍시다.

 

그 후, http://127.0.0.1:3000/api-docs 경로로 이동을 해서 스웨거 문서를 열어줍시다.

그리고 로그인을 해줍시다. 혹시 로그인 하는 방법을 까먹으셨다면, 아래 포스팅을 참고하도록 합시다.

https://suloth.tistory.com/96

 

#12. 기초부터 따라하는 Nest.js : Dto와 Swagger

해당 포스팅은 nest.js 9.0.0 버전, typeorm 0.3.x 버전을 기준으로 작성되었습니다. 모든 글은 작성자의 주관이 100% 담겨있기 때문에 부정확할 수 있습니다. #pre. 터미널을 켜고 프로젝트 폴더로 이동 ht

suloth.tistory.com

 

이제 로그인까지 했다면, class-validator가 제대로 동작하는지 확인해봅시다.

 

스웨거 문서에서 다음과 같이 title과 content에 문자열이 아닌 숫자 값을 넘기면,

 

위의 사진과 같이 Status 400 에러를 뱉으면서 title과 content가 string이어야한다는 메시지를 넘깁니다.

 

 

하지만, Class-validator를 사용한다면 nest.js의 처리속도가 매우 느려진다는 단점이 있습니다...

그래서 class-validator를 대체할 수 있는 다른 라이브러리가 있는데 typia 라는 라이브러리입니다. 저도 아직 공부해보지는 않았지만, 관심이 있다면 공부를 한 번 해보시는 것을 추천드립니다.


Pipe


자, 이제 pipe에 대해서 알아봅시다.

파이프는 말 그대로 관입니다. 데이터가 파이프로 들어오면 파이프에서 데이터를 검증하거나 데이터의 형태를 변환시켜주는 역할을 합니다.

 

파이프는 주로 다음과 같은 상황에서 많이 사용합니다.

@Get('/:id')
async readArticle(@Param('id', ParseIntPipe) id: number) {
  const articleId = id;
  ...
}

만약 우리가 articleId를 Int타입으로 설정해놨다면, Param을 통히 id변수에 저장되는 데이터의 형식은 string입니다. 그래서 해당 string 데이터를 int타입으로 바꿔줄 필요가 있습니다.

이런식으로 @Param데코레이터의 2번째 인자에 ParseIntPipe라는 파이프를 넣어주면 해당 변수의 형식은 number로 변환됩니다.

 

그리고 Pipe 추가적으로 옵션을 넣어주고 싶은 경우 다음과 같이 new를 넣어주면 됩니다.

@Get('/:keys')
async readArticle(@Param('id', new ParseArrayPipe({ items: Number, separator: ',' }))
  keys: number[],
) {
  ...
}

keys의 값을 받는데, 구분자는 , 로 하고 구분하고난 원소들의 타입은 Number로 변환합니다. 그리고 그 number배열을 keys라는 변수에 담습니다.

 


여기까지 모두 완료를 하셨다면! 이제 깃허브에 푸쉬해봅시다.

 

https://suloth.tistory.com/46

 

#0-2. 기초부터 따라하는 Nest.js : Git과 Github 사용법

이 글은 아래의 포스팅에 이어서 작성하는 포스팅입니다. https://suloth.tistory.com/45 #1. 기초부터 따라하는 Nest.js : Nest.js 초기 설정 Nest.js란? node.js의 백엔드 프레임워크 중 하나입니다. node.js에는 수

suloth.tistory.com

 

참고하시라고 올려두는 사진입니다.