DEV/Node

[Node] Custom Validate Decorator 적용하기 (with. NestJS)

2024. 11. 7. 15:18
목차
  1. 0. 개요
  2. 1. 사전 설정
  3. a. 라이브러리 Install
  4. b. Global 설정
  5. 2. 커스텀 데코레이터 구현
  6. a. 휴대번호 검증 데코레이터
  7. b. 비밀번호 검증 데코레이터
  8. 3. DTO에 커스텀 데코레이터 적용
  9. 4. 컨트롤러에서 DTO 적용
  10. 5. 테스트
  11. 6. 마무리

0. 개요

NestJS 프로젝트에서 class-validator와 class-transformer 라이브러리를 통해 데코레이터 사용만으로 데이터 검증을 할 수 있습니다.
기본적으로 제공하는 데코레이터를 사용해도 충분하지만 특정 값에 대한 검증을 추가하고 싶을때 커스텀 데코레이터를 만들게 됩니다.

이번 포스팅에서는 휴대번호와 비밀번호 검증을 위한 커스텀 데코레이터를 구현해보려고 합니다.

1. 사전 설정

a. 라이브러리 Install

우리가 만들고자 하는 기능에 필요한 두 가지 라이브러리를 설치합니다.

npm install class-transformer class-validator

b. Global 설정

app.useGlobalPipes는 전역 Pipe 를 추가하는 메소드로 ValidationPipe를 추가하여 요청 라이프사이클에서 메소드 핸들러가 작동하기 전에 검증을 수행하게 됩니다.

해당 설정은 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, // DTO에 정의되지 않은 속성 제거
      forbidNonWhitelisted: true, // DTO에 정의되지 않은 속성이 있으면 에러 반환
      transform: true, // 요청 데이터를 DTO 인스턴스로 자동 변환
    }),
  );

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

 

2. 커스텀 데코레이터 구현

휴대번호와 비밀번호 관련 데코레이터를 만들때 정규식을 이용한 문자열을 검증하는 방식으로 진행했습니다.
(정규식 관련 내용은 다른 포스팅에서!)

a. 휴대번호 검증 데코레이터

휴대번호 검증은 xxx-xxx(x)-xxxx 기준으로 작성되었습니다.

import { registerDecorator, ValidationOptions, ValidationArguments } from 'class-validator';

export function IsPhoneNumber(validationOptions?: ValidationOptions): PropertyDecorator {
  return function (object: Object, propertyName: string) {
    registerDecorator({
      name: 'isPhoneNumber',
      target: object.constructor,
      propertyName: propertyName,
      options: validationOptions,
      validator: {
        validate(value: any, args: ValidationArguments) {
          const phoneRegex = /^\d{3}-\d{3,4}-\d{4}$/; // 예: 123-4567-8901
          return typeof value === 'string' && phoneRegex.test(value);
        },
      },
    });
  };
}

 

b. 비밀번호 검증 데코레이터

비밀번호는 보안상의 이유로 복잡한 검증이 필요할 수 있습니다.
아래 예시 코드는 최소 8자, 대문자, 소문자, 숫자, 특수문자를 포함하도록 하는 비밀번호 검증 데코레이터입니다.

export function IsPassword(validationOptions?: ValidationOptions): PropertyDecorator {
  return function (object: Object, propertyName: string) {
    registerDecorator({
      name: 'isPassword',
      target: object.constructor,
      propertyName: propertyName,
      options: validationOptions,
      validator: {
        validate(value: any, args: ValidationArguments) {
          const passwordRegex = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,}$/;
          return typeof value === 'string' && passwordRegex.test(value);
        },
        defaultMessage(args: ValidationArguments) {
          return 'Password must be at least 8 characters long and include at least one uppercase letter, one lowercase letter, one number, and one special character.';
        },
      },
    });
  };
}

 

3. DTO에 커스텀 데코레이터 적용

위에서 만든 데코레이터를 DTO에 적용하고 추가적인 검증 데코레이터를 함께 사용합니다.
해당 코드에서는 @IsNotEmpty를 적용하였지만, 값이 들어올때만 검증 하고싶다면 @IsOptional() 데코레이터와 함께 사용하면 됩니다.

import { IsNotEmpty, IsEmail } from 'class-validator';
import { IsPhoneNumber, IsPassword } from './custom-decorators';

export class CreateUserDto {
  // ... 다른 변수들
  @IsNotEmpty()
  @IsEmail() // 기본 Validation Decorator
  email: string;

  @IsNotEmpty()
  @IsPhoneNumber({ message: 'Invalid phone number format' })
  phone: string;

  @IsNotEmpty()
  @IsPassword({ message: 'Password does not meet the complexity requirements' })
  password: string;
}

 

4. 컨트롤러에서 DTO 적용

Controller에 테스트 요청에 관한 내용을 정의.

import { Body, Controller, Post } from '@nestjs/common';
import { CreateUserDto } from './dto/create-user.dto';

@Controller('users')
export class UsersController {
  @Post()
  createUser(@Body() createUserDto: CreateUserDto) {
    // 요청 데이터가 DTO 검증을 통과해야 이 메서드에 도달합니다.
    return {
      message: 'User created successfully',
      data: createUserDto,
    };
  }
}

 

5. 테스트

a. 검증 통과


b. 검증 시 실패

 

 

 

6. 마무리

Spring이나 NestJS나 프레임워크 별로 검증 라이브러리는 대부분 존재하기 때문에 하나 공부해두면 다른 부분 프레임워크에서 적용하기 어렵진 않아보입니다.

본 포스팅에서는 많이 사용될만한 휴대번호, 비밀번호에 대한 커스텀이지만 각자 필요한 부분이 다를수있기에 검증 후 Return Boolean Type 만 적용한다면 취향에 맞게 커스텀이 가능합니다.

728x90

'DEV > Node' 카테고리의 다른 글

[Node] class-validator decorator 목록  (1) 2024.11.18
[Node] Passport 활용하기 (with. NestJS)  (0) 2024.11.10
[Node] NestJS 란?  (0) 2023.11.16
  1. 0. 개요
  2. 1. 사전 설정
  3. a. 라이브러리 Install
  4. b. Global 설정
  5. 2. 커스텀 데코레이터 구현
  6. a. 휴대번호 검증 데코레이터
  7. b. 비밀번호 검증 데코레이터
  8. 3. DTO에 커스텀 데코레이터 적용
  9. 4. 컨트롤러에서 DTO 적용
  10. 5. 테스트
  11. 6. 마무리
'DEV/Node' 카테고리의 다른 글
  • [Node] class-validator decorator 목록
  • [Node] Passport 활용하기 (with. NestJS)
  • [Node] NestJS 란?
l-eazzy
l-eazzy
귀찮고 귀찮은데 귀찮기 싫어서 개발하는 귀찮은 개발자.
귀찮은 개발자의 블로그귀찮고 귀찮은데 귀찮기 싫어서 개발하는 귀찮은 개발자.
l-eazzy
귀찮은 개발자의 블로그
l-eazzy
전체
오늘
어제
  • 분류 전체보기 (89)
    • DEV (68)
      • Language (3)
      • Spring (22)
      • Node (4)
      • Flutter (1)
      • Infra (15)
      • DataBase (2)
      • Airflow (2)
      • ErorrBox (8)
      • Etc (11)
    • REVIEW (8)
      • IT (7)
      • 카메라 (1)
    • Daily (10)
      • 출사 (1)
      • 그냥 (1)
      • 오늘의 점심 (7)
    • 아무거나 (2)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • 티스토리챌린지
  • AWS
  • QueryDSL
  • JPA
  • Spring
  • Airflow
  • springboot
  • docker
  • 오블완
  • 강남

최근 댓글

최근 글

hELLO · Designed By 정상우.
l-eazzy
[Node] Custom Validate Decorator 적용하기 (with. NestJS)
상단으로

티스토리툴바

단축키

내 블로그

내 블로그 - 관리자 홈 전환
Q
Q
새 글 쓰기
W
W

블로그 게시글

글 수정 (권한 있는 경우)
E
E
댓글 영역으로 이동
C
C

모든 영역

이 페이지의 URL 복사
S
S
맨 위로 이동
T
T
티스토리 홈 이동
H
H
단축키 안내
Shift + /
⇧ + /

* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.