관리 메뉴

Mini

[Nest] DTO 구현, class-validator, message 구현 본문

JS/Nest.js

[Nest] DTO 구현, class-validator, message 구현

Mini_96 2024. 9. 20. 21:01

* createPost dto 구현

  • main.ts에서 app.use
    • 이래야 @IsString 등이 작동함.
async function bootstrap() {
  const app = await NestFactory.create(AppModule);

  app.useGlobalPipes(new ValidationPipe());

  await app.listen(3000);
}
bootstrap();
  • 모델의 엔티티에 Validator를 넣고
export class PostsModel extends BaseModel{

  /**
   * 게시글은 1명의 사용자를 가진다.
   * 사용자는 게시글 여러개를 가진다.
   * users 모델에서 posts모델을 표현하는 속성이 posts다.
   */
  @ManyToOne(()=>UsersModel, (user)=> user.posts, {
    nullable: false,
  })
  author: UsersModel;

  @Column()
  @IsString()
  @Length(2,20, {
    message:' 길이는 2~20이어야 합니다.',
  })
  title: string;
  • dto에서는 필요한속성만 pick 해서 구성하면됨.
export class CreatePostDto extends PickType(PostsModel, ['title', 'content']){ }

 

  • 컨트롤러 수정
@Post()
@UseGuards(AccessTokenGuard)
createPost(
  @User('id') userId : number,
  @Body() body : CreatePostDto){
  return this.postsService.createPost(userId ,body);
}

 

  • 서비스 수정
    • dto 내부에 {title : adfd , content : gfdijfogjf} 이렇게 담겨있음
    • 그대로 ...으로 복사해주면 됨.
async createPost(authorId: number, postDto : CreatePostDto){

  const post = this.postsRepository.create({
    author: {
      id: authorId,
    },
    // title: title,
    // content: content,
    ...postDto,
    likeCount:0,
    commentCount:0,
  });

결과

 

* optional pick => update post dto 구현

  • createdto에서 옵셔널로  pick (partialType) 해오기
  • update 할때는 title, content 가 비어있어도 작동해야함.
import { PartialType } from "@nestjs/mapped-types";
import { CreatePostDto } from "./create-post.dto";
import { IsOptional, IsString } from "class-validator";

export class UpdatePostDto extends PartialType(CreatePostDto){
  @IsString()
  @IsOptional()
  title? :string;
  
  @IsString()
  @IsOptional()
  content?: string;
}

 

 

* 검증시 오류 메시지 구현

  • 엔티티
@IsEmail(null, {
  message : emailValidationMessage,
})
email: string;
  • common > message용 func
import { ValidationArguments } from "class-validator";

export const lengthValidationMessage = (args: ValidationArguments) => {
  /**
   * ValidationArguments의 속성들
   *
   * 1) value == 검증되고 있는 값 (입력된 값)
   * 2) constraints -> 파라미터의 제한사항들
   *      @Length(2, 20)
   *      args.constraints[0] == 2
   *      args.constraints[1] == 20
   * 3) targetName == 검증하고 있는 클래스의 이름
   * 4) object == 검증하고있는객체
   * 5) property == 검증되고있는 객체의 속성 이름 (ex : nickname)
   */

  // min, max 가 모두 있는경우
  if(args.constraints.length == 2){
    return `${args.property}은(는) ${args.constraints[0]} ~ ${args.constraints[1]} 글자를 입력해주세요.`;
  }
  else{ // min만 준 경우
    return `${args.property}은(는) ${args.constraints[0]} 이상 글자를 입력해주세요.`;
  }
}
import { ValidationArguments } from "class-validator";

export const emailValidationMessage = (args: ValidationArguments) => {
  return `${args.property}에 정확한 이메일을 입력해주세요.`;
}

결과

  • email 검증시 첫인자로 빈 객체를 넣어야함! // null 안됨!
@IsEmail({}, {
  message : emailValidationMessage,
})

 

* 회원가입 dto 구현

  • users entitiy 수정
@Column({
  unique: true,
})
@IsEmail()
@IsString()
email: string;

@Column()
@IsString()
@Length(3,20, {
  message : lengthValidationMessage,
})
password: string;
  • dto
    • userModel에서 필요한 속성만 pick
import { PickType } from "@nestjs/mapped-types";
import { UsersModel } from "../../users/entities/users.entity";

export class RegisterUserDto extends PickType(UsersModel, ['nickname','email','password']){ }
  • 컨트롤러 body를 dto로 수정
@Post('/register/email')
postRegisterEmail(
  @Body() body : RegisterUserDto) {
  return this.authService.registerWithEmail(body);
}