Loading...
본문 바로가기
👥
총 방문자
📖
0개 이상
총 포스팅
🧑
오늘 방문자 수
📅
0일째
블로그 운영

여러분의 방문을 환영해요! 🎉

다양한 개발 지식을 쉽고 재미있게 알려드리는 블로그가 될게요. 함께 성장해요! 😊

코딩 정보/NestJs

[NestJs] DTO란 무엇이고 사용방법에 대해 알아보자

by 꽁이꽁설꽁돌 2025. 1. 27.
728x90
반응형
     

목차

     

     

     

     

    DTO란?

    DTO(Data Transfer Object, 데이터 전송 객체)란 프로세스 간에 데이터를 전달하는 객체를 의미합니다. 말 그대로 데이터를 전송하기 위해 사용하는 객체라서 그 안에 비즈니스 로직 같은 복잡한 코드는 없고 순수하게 전달하고 싶은 데이터만 담겨있습니다.  아래의 그림을 통해 DTO는 주로 클라이언트와 서버가 데이터를 주고받을 때 사용하는 객체임을 알 수 있습니다.

     

    참고

    https://tristy.tistory.com/54

     

    DTO란 무엇이고 왜 사용해야 할까?

    밑의 예제 코드는 전부 NestJS + TypeOrm 환경에서 작성되었습니다. 트리스티가 Nest Js를 공부하며 남긴 기록입니다. 틀린 내용은 언제든지 말씀해주세요 ~! 📢 DTO란 무엇인가요? DTO(Data Transfer Object,

    tristy.tistory.com

     

     

     

    사용방법

    yarn add class-validator
    yarn add class-transformer

     

    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());
      await app.listen(process.env.PORT ?? 3000);
    }
    bootstrap();

     

    아래와 같이 객체안에 검증 annotation을 해준뒤 원하는 오류메세지를 설정해 줄 수 있다.

    import { IsString } from 'class-validator';
    
    export class CreatePostDto {
      @IsString({
        message: 'title은 string타입을 입력해 주어야 합니다!',
      })
      title: string;
    
      @IsString({
        message: 'content는 string타입을 입력해 주어야 합니다!',
      })
      content: string;
    }

     

     @Post()
      @UseGuards(AccessTokenGuard)
      postPosts(@User('id') userId: number, @Body() body: CreatePostDto) {
        return this.postsService.createPost(userId, body);
      }

     

     

    우리는 entity와 겹치는 부분인 content와 title만 가져다 쓰고 싶으면 다음과 같이 하면 된다.

    import { IsString } from 'class-validator';
    import { BaseModel } from 'src/common/entity/base.entity';
    import { UsersModel } from 'src/users/entities/users.entity';
    import {
      Column,
      Entity,
      ManyToOne,
    } from 'typeorm';
    
    @Entity()
    export class PostsModel extends BaseModel {
      //절대적으로 겹치지 않는 칼럼 생성
    
      // 1) UsersModel과 연동한다. Foreign Key를 이용해서
      // 2) null이 될 수 없다.
      @ManyToOne(() => UsersModel, (user) => user.posts, {
        nullable: false,
      })
      author: UsersModel;
    
      @Column()
      @IsString({
        message: 'title은 string타입을 입력해 주어야 합니다!',
      })
      title: string;
    
      @Column()
      @IsString({
        message: 'content는 string타입을 입력해 주어야 합니다!',
      })
      content: string;
    
      @Column()
      likeCount: number;
      @Column()
      commentCount: number;
    }

     

    그래서 다음과 같이 dto코드를 바꾸면 오류가 난다.

    import { IsString } from 'class-validator';
    import { PostsModel } from '../entities/posts.entity';
    
    export class CreatePostDto extends Pick<PostsModel, 'title' | 'content'> {}

     

     

     

    타입이 아닌 값으로 상속 받아야 하기 때문에 PickType으로 바꾸면 해결된다.

    import { IsString } from 'class-validator';
    import { PostsModel } from '../entities/posts.entity';
    import { PickType } from '@nestjs/mapped-types';
    
    //Pick, Omit, Partial ->type 반환
    //PickType OmitType PartialType -> 값 반환
    export class CreatePostDto extends PickType(PostsModel, ['content', 'title']) {}

     

     

    그렇다면 updatePostDTO도 한번 만들어 보자

    아래와 같이 PartialType을 쓰게 되면 옵셔널 체이닝을 사용할 수 있다.

    물론 extends를 쓰지 않아도 된다. 하지만 상속성을 잘 표현하기 위해 다음과

    같이 쓰는 것이 적절한 방향이라고 볼 수 있다.

    import { IsOptional, IsString } from 'class-validator';
    import { CreatePostDto } from './create-post.dto';
    import { PartialType } from '@nestjs/mapped-types';
    
    export class UpdatePostDTO extends PartialType(CreatePostDto) {
      @IsString()
      @IsOptional()
      title?: string;
    
      @IsString()
      @IsOptional()
      content?: string;
    }

     

    Validation Message 일반화

    기능

    /**
     * ValidationArguments의 프로퍼티들
     *
     * 1) value -> 검증 되고 있는 값 (입력된 값)
     * 2) constraints -> 파라미터에 입력된 제한 사항들
     *    args.constraints[0] -> 1
     *    args.constraints[1] -> 20
     * 3) targetName -> 검증하고 있는 클래스의 이름
     * 4) object -> 검증하고 있는 객체
     * 5) property -> 검증 되고 있는 객체의 프로퍼티 이름
     */

     

    사용예시

    import { ValidationArguments } from 'class-validator';
    
    export const lengthValidationMessage = (args: ValidationArguments) => {
      if (args.constraints.length === 2) {
        return `${args.property}은 최대 ${args.constraints[0]}~${args.constraints[1]}글자를 입력 해주세요!`;
      } else {
        return `${args.property}는 최소 ${args.constraints[0]} 글자를 입력 해주세요!`;
      }
    };

     

     

    이런식으로 message를 각각마다 작성하지 않고 일반화하여 사용할 수 있다.

     

     

    강의출처

     

    [코드팩토리] [초급] NestJS REST API 백엔드 완전 정복 마스터 클래스 - NestJS Core 강의 | 코드팩토리 -

    코드팩토리 | 자바스크립트, 타입스크립트 다음은 백엔드 개발! NestJS를 이용한 REST API 백엔드 개발, Socket IO 개발 및 배포를 할 수 있게 됩니다., 백엔드가 처음이어도 누구나 OK! 트렌디한 NestJS로

    www.inflearn.com

     

    반응형