상세 컨텐츠

본문 제목

[nestjs] validation

Web/NestJS

by 클리엘 클리엘 2021. 3. 16. 15:10

본문

728x90

아래 내용은 이전 포스팅에서 이어지는 내용입니다.

 

[Server/NestJS] - [nestjs] Service

 

[nestjs] Service

nestjs에서 Service를 생성하려면 다음 명령을 사용합니다. nest g s Service 이름을 입력하고 다음으로 넘어갑니다. Service가 생성되면 app.module.ts와 관련 파일이 생성되어 있음을 확인할 수 있습니다. imp

lab.cliel.com

 

nest에서 유효성을 검증하기 위해서는 아래와 같이 class-validation을 설치합니다.

npm i class-validator class-transformer

설치가 완료되면 Model 디렉터리의 student.ts파일에 아래 내용을 추가합니다.

export class studentValidator {
    @IsString()
    readonly name: string;
    @IsString()
    readonly group: string;
    @IsNumber()
    readonly age: number;
};

파일은 validation을 위한 클래스를 추가하는 것이며 name, group, age필드만을 전달하고 각각의 필드에 적용되어야 할 타입을 명시하고 있습니다.

 

만약 필드중 배열이 존재한다면 아래와 같이 데코레이터를 작성해 필요한 데이터 타입을 명시하고 배열 값을 모두 확인하는 방식으로 처리해야 합니다.

@IsString({ each; true })

유효성을 확인하기 위한 데코레이터는 이 외에도 길이를 제한하는 @Length()나 Email형식을 강제하는 @IsEmail()등이 있습니다.

 

https://github.com/typestack/class-validator 

 

typestack/class-validator

Decorator-based property validation for classes. Contribute to typestack/class-validator development by creating an account on GitHub.

github.com

그리고 school.controller.ts에 있는 setStudent() 함수에 기존 student대신 위에서 생성한 studentValidator로 바꿔주고

@Post()
async setStudent(@Body() std:studentValidator) {
    this.schoolService.addStudent(std);
    return await this.schoolService.getStudents();
}

school.service.ts에서의 addStudent()함수도 studentValidator형 식이 되도록 바꿔줍니다.

addStudent(studentValidator) {
    this.students.push({
        id: this.students.length + 1,
        ...studentValidator
    });
}

이제 setStudent()함수를 통해 전달되는 데이터 형식은 studentValidator형식과 동일해야 합니다.

 

마지막으로 main.ts를 수정해 중간에 데이터가 통과하는 pipe를 연결해 줍니다.

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

  app.useGlobalPipes(
    new ValidationPipe()
  );

  await app.listen(80);
}

위와 같이 작성한 후 테스트해 봅니다.

 

고의적으로 name필드를 누락했으며 age에 숫자가 아닌 문자열을 전달했습니다. 이 상태로 Post를 날려주면 무엇이 잘못되었는지 필요한 정보를 알려주게 됩니다.

 

필요한 모든 필드를 정상으로 돌려놓고 다시 POST를 시도해 보면

 

age를 숫자로 했음에도 불구하고 여전히 오류가 발생하고 있습니다. 이렇게 되는 이유는 POST로 전송하는 데이터는 숫자라 하더라도 문자열로서 전송되기 때문입니다. 이러한 문제점을 해결하려면 age필드에 대해 다음과 같이 타입 변환을 시도해야 합니다.

export class studentValidator {
    @IsString()
    readonly name: string;
    @IsString()
    readonly group: string;
    @Type(() => Number)
    @IsNumber()
    readonly age: number;
};

위와 같이 하면 자동적으로 타입을 변환을 시도해 주기 때문에 데이터타입의 변환에 대해 따로 신경 쓰지 않아도 됩니다.

 

이번에는 tmp라는 임의의 필드를 만들어 전송을 시도했습니다. 보시는 바와 같이 student는 tmp라는 필드를 갖지 않으므로 무의미한 데이터라고 봐야 하는데 문제는 이러한 의미 없는 데이터의 전송이 가능하다는 것입니다. 이런 경우에는 ValidationPipe에서 whitelist옵션을 true로 지정하면 됩니다.

app.useGlobalPipes(
  new ValidationPipe({
    whitelist: true
  })
);

기본적으로 필요하지 않는 필드는 무시하지만 클라이언트에게 경고를 반환하려면 forbidNonWhiteListed 옵션을 treu로 설정합니다.

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

이번에는 school.controller.ts에 있는 getStudent() 함수를 보겠습니다. 이 함수는 id값을 매개변수로 받는데 타입을 보면 string으로 명시되어 있습니다. student 클래스를 보면 id는 number로 되어 있으나 매개변수로 전달되는 값은 string문자열이므로 string으로 명시된 것입니다.

 

school.service.ts의 getStudent() 함수에서 또한 id를 +id로 명시했는데 문자열 형식의 id를 number로 바꾸기 위한 조치입니다. 이러한 상태에서 ValidationPipe의 옵션 중 transform을 true로 설정하면 타입 변환을 자동으로 수행할 수 있습니다.

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

이제 school.controller.ts와 school.service.ts에 있는 id string을 모두 number로 바꿔 줍니다.

getStudent(id: number) {
    const std = this.students.find(x => x.id === id);

    if (!std) {
        throw new NotFoundException('student 정보 없음');
    }

    return std;
}

 

728x90

'Web > NestJS' 카테고리의 다른 글

[nestjs] module과 의존성주입(dependency injection)  (0) 2021.03.16
[nestjs] DTO (Data Transfer Object)  (0) 2021.03.16
[nestjs] validation  (0) 2021.03.16
[nestjs] Service  (0) 2021.03.16
[nestjs] controller  (0) 2021.03.15
[nestjs] 시작하기  (0) 2021.03.15

관련글 더보기

댓글 영역