← Notes

Nest.js 유효성 검사 — Validation Pipe와 class-validator

Nest.js 백엔드 개발· 6 / 8
  1. 1 — Nest.js 프로젝트 생성과 구조
  2. 2 — Nest.js Decorator 동작원리와 종류, Custom Decorator
  3. 3 — Nest.js 의존성 주입 개념과 적용 방법
  4. 4 — Nest.js HTTP exceptions 에러 처리 모음
  5. 5 — Nest.js CORS 설정
  6. 6 — Nest.js 유효성 검사 — Validation Pipe와 class-validator
  7. 7 — Nest.js API 문서화 — Swagger Module
  8. 8 — Nest.js 환경 변수 관리 — Config Module

현재 진행 중인 토이프로젝트는 프론트엔드 개발자분과 함께 협업으로 진행하고 있는 프로젝트이다.

그렇기에 백엔드를 실제로 외부에서 사용이 가능한 상태로 만들어야 하고, 올바르게 사용할 수 있도록 참고할 수 있는 매뉴얼도 필요하다.

Nest.js에는 프론트엔드와 협업을 위한 다양한 설정을 내부에서 혹은 라이브러리 호환을 제공한다. 그 중 가장 기본이 되는 설정별로 문서를 구분해 하나씩 정리해보자.

Validation Pipe

Validation Pipe 설정을 하는 이유

Validation Pipe는 Nest.js의 내장 기능으로, 클라이언트로부터 들어오는 HTTP 요청 데이터의 유효성을 검사한다. 애플리케이션에서 예상한 타입과 규칙에 맞지 않는 데이터를 걸러내고, 검증에 실패한 경우 즉시 오류 처리를 수행한다.

이 기능을 활용하면, 비즈니스 로직에서 데이터 유효성을 검증하는 중복을 줄여주고, 유효성 검사를 요청 처리 파이프라인에서 수행하기 때문에 올바르지 않은 데이터가 비즈니스 로직에 영향을 미치는 것을 방지할 수 있다.

설정하는 과정은 다소 번거로울 수 있지만, 프론트엔드와 백엔드 간의 데이터 통신에서 정확한 타입 및 규칙을 강제할 수 있고, 안정적인 서버 운영을 위해 권장되는 기능이다.

Validation Pipe 설정

유효성 검사를 위해 @nestjs/commonValidationPipe 클래스를 이용한다. 유효성 검사가 필요한 메소드나 특정 데이터(Body, Param, Query 등)에 직접 적용해줄 수도 있지만, 서버로 들어오는 모든 요청 데이터에 적용할 수 있도록 main.tsuseGlobalPipes()메소드를 이용해 전역으로 설정해두었다.

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

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

  const port = config.get<number>('PORT');

  app.useGlobalPipes(
    new ValidationPipe({
      whitelist: true,
      forbidNonWhitelisted: false,
      transform: true,
    }),
  );

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

useGlobalPipes() 메소드로 추가한 옵션 내용은 아래와 같다.

  • whitelist: 요청 데이터 중 DTO에 정의되지 않은 속성의 유효성 검사를 건너뛸지 여부를 결정함.

    • false: 해당 속성의 유효성 검사를 거치지 않은 채로 데이터를 비즈니스 로직으로 넘김.(default)
    • true: 아래 forbidNonWhitelisted에 따라 설정됨.
  • forbidNonWhitelisted: DTO에 정의되지 않은 속성이 들어왔을 때 요청을 거부할지 여부를 결정함.

    • false: 해당 속성이 비즈니스 로직에 넘어가지 않도록 걸러줌.(default)
    • true: 해당 속성이 들어올 경우 그 즉시 에러를 발생함.
  • transform: 유효성 검사 전에 들어온 데이터를 DTO 클래스의 타입에 맞게 자동 변환 여부를 결정함.

비즈니스 로직에서, 프론트엔드에서는 백엔드로부터 받은 데이터를 그대로 다시 전달하는 경우가 있고, 백엔드에서는 요청 데이터를 그대로 save하는 경우도 있기 때문에,

서버 안정 상 whitelist 는 활성화하고 forbidNonWhitelisted 는 비활성화해 두었다.

Validation Pipe 활용: class-validator

앞선 Validation Pipe 설정이 잘 적용되기 위해선 그의 기준이 필요하다. 보통 컨트롤러의 Request Data의 정의를 DTO로 등록해 한번에 설정해두기 때문에 DTO를 유효성 검증의 기준으로 사용할 수 있다.

DTO 정의 시 속성마다 타입을 확실하게 지정하거나 세부적인 특성을 지정하기 위해 class-validator 라이브러리와 함께 사용하면 더 철저한 유효성 검증에 도움이 된다.

npm install class-validator

라이브러리를 설치한 후 아래 처럼 사용할 수 있다.

import { IsEmail, IsOptional, IsString } from 'class-validator';
import { AuthType } from 'src/shared/types/enums/user.enum';

export class CreateUserDto {
  @IsEmail()
  email: string;

  @IsString()
  nickname: string;

  @IsString()
  password: string;

  @IsOptional()
  @IsEnum(AuthType)
  authType: AuthType = AuthType.BASIC;
}

@IsString()와 같이 데이터의 타입을 지정할 수 있고, @IsEmail()와 같이 세부적으로 데이터의 특성을 지정해줄 수 있다.

그 외에도 다양한 기능이 라이브러리에 준비되어 있기 때문에 좀더 정교하게 유효성을 검사할 수 있다.

ValidationPipe 유효성 검사 실패 시 400 응답

요청된 데이터가 DTO에 정의된 속성과 일치하지 않을 경우, 위와 같이 즉시 에러를 발생시킨다.

목차