일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
Tags
- JavaScript
- node.js
- ojdbc6
- 프로그래머스
- 인텔리제이
- 코어자바스크립트
- oracle
- Mac
- Stream
- 봤어요처리
- datagrip 한글깨짐
- MySQL
- TypeScript
- InteliJ
- REST
- @RequestBody
- javascript error
- SQL
- flutter mac 설치
- tecoble
- DART
- db
- Aspect
- eqauls-hashcode
- 프로젝트 여러 개
- maven
- Spring
- Java
- class-transformer
- svn
Archives
- Today
- Total
개발자가 되고 싶은 개발자
class-validator 사용법 본문
Preface
- 이전 포스팅을 작성하게된 본 목적을 이어서 작성합니다.
- 동료분이 노드 관련해서 질문주셔서 문제점을 같이 찾아보다가 class-validator의 옵션이 원인이었고,
몰랐던 옵션에 대해 알게되었습니다. - 해당 라이브러리에 대한 사용법과 옵션에 대해서 간단하게 정리합니다.
TypeStack
- class-validator도 class-transformer과 동일하게 TypeStack의 프로젝트입니다.
- 스프링처럼 Dependenchy Inejction을 지원하는 typedi와 같은 여러 어노테이션 기반의 타입 프로젝트들을 진행하고 있습니다.
typestack/class-validator
- class-validator는 데코레이터 기반의 클래스 속성 유효성 검사 라이브러리입니다.
- 클라이언트로부터 전달된 객체에 대한 값을 검사할 수 있습니다.
- 자릿수, 필수값, 타입 검사 등 여러 옵션들이 존재합니다.
Decorator-based property validation for classes.
Usage
- 아래와 같이 검사할 속성에 대해서 어노테이션을 작성해줍니다.
- 그리고 클래스의 객체를 생성하거나, 이전 포스팅에서 작성한 것처럼 전달받은 값을 class-transformer를 통해서 인스턴스화 시켜줍니다.
import {
validate,
validateOrReject,
Contains,
IsInt,
Length,
IsEmail,
IsFQDN,
IsDate,
Min,
Max,
} from 'class-validator';
export class Post {
@Length(10, 20)
title: string;
@Contains('hello')
text: string;
@IsInt()
@Min(0)
@Max(10)
rating: number;
@IsEmail()
email: string;
@IsFQDN()
site: string;
@IsDate()
createDate: Date;
}
- 위 예시는 class-validator에서 발췌하였습니다.
validate(post).then(errors => {
// errors is an array of validation errors
if (errors.length > 0) {
console.log('validation failed. errors: ', errors);
} else {
console.log('validation succeed');
}
});
- 그 후 validate를 호출하게 되면, 유효성 검사에 통과되지 않은 속성들에 대해서는 에러를 반환하게 되거나 별도의 예외처리를 하도록 콜백함수에 작성해주면 됩니다.
- 저 같은 경우는 에러를 반환하게되면 412에러를 반환해주면서, 어떤 속성에서 문제가 발생되었는지 담아서 반환해주고 있습니다.
공통화
create = asnyc (req: Requset, res: Response) => {
const dto = classToInstance(User, req.body);
validate(user);
const createdUser = await UserService.create(dto);
}
- 위와 같은 컨트롤러의 메소드가 있다고 가정하겠습니다.
- 서비스 레이어로 넘어간 데이터는 비즈니스로직 상에서 검증해야할 유효성만을 실행하고,
전제조건이 잘못된 데이터는 컨트롤러단에서 제어해줍니다. - 즉, 컨트롤러단에서 위에 대한 코드는 어떤 메소드에서던지 일반적으로 무조건 반복해서 호출되게 됩니다.
- 그렇다면, classToInstance와 validate를 모든 메소드에서 반복해서 호출해주는 것은 실수의 여지도 있고 상당히 비효율적입니다.
- 그래서 Dto를 정의할 때는 공통적으로 해당 함수들을 호출해주는 공통 클래스를 상속받도록 정의하여 호출하면 유효성검사가 수행된 인스턴스화된 객체를 넘겨받도록 사용할 수 있습니다.
Class CommonDto {
static getValidatedInstance<T extends CommonDto>(this: ClassConstructon<T>, req: Request): T {
const dto = plainToInstance(this, req.build, 설정할 옵션);
validateSync(dto);
return dto;
}
}
- 처음 위와 같은 형식으로 작성했을 때의 문제점은 dto의 어떤 property의 유효성에서 문제가 발생한지 알 수 없었고, 어떤 내용의 에러가 발생했는지 파악하기 힘들었습니다.
- 그래서 실무에선 class-validator의 validateSync를 바로 호출하는 것이 아닌,
반복문을 순회하면서 어디서 문제가 발생했는지 담아서 한꺼번에 반환하는 별도 커스템 메소드를 두어 사용하고 있습니다. - 이 부분은 프론트와 협의 혹은 사내 에러 컨벤션의 형태에 따라 적합하게 처리하면 될 것 같습니다.
Whitelisting
import { validate } from 'class-validator';
// ...
validate(post, { whitelist: true });
Even if your object is an instance of a validation class it can contain additional properties that are not defined.
If you do not want to have such properties on your object, pass special flag to validate method
- 유효성 검사가 통과된 인스턴스화된 변수일지여도, 정의하지 않은 추가적인 프로퍼티가 추가되어 있을 수 있습니다.
- 만약 이러한 상황을 방지하려면 validate 메소드에 whitelist 옵션을 주는 것으로 방지할 수 있습니다.
- 위 옵션만 추가할 경우 전달받을 수는 있지만, 전달받는 것만으로 에러가 발생하진 않습니다.
- 실제 존재하지 않는 속성에 대해서 접근하는 경우에 에러가 발생하게 됩니다.
- 만약 whitelist에 포함되지 않은 속성이 전달되는 경우에 대해서도 에러를 발생시키려면 아래와 같은 옵션을 추가할 수 있습니다.
import { validate } from 'class-validator';
// ...
validate(post, { whitelist: true, forbidNonWhitelisted: true });
E.O.D
- 최근들어 작성한 포스팅들에서는 사용하고 있던 라이브러리 혹은 언어들의 기본사양에 대해서 다시 한 번 복기하고 몰랐던 부분에 대해서 정리할 수 있었습니다.
- 해당 포스팅 본문의 공통화에 잠깐 작성한 부분과 같은 경우는 제가 진행하고 있는 프로젝트에서는 잘 사용중에 있지만, 다른 프로젝트에서는 사용되고 있지 않아서 반복적인 코드들이 많이 남아있는 경우도 있었습니다.
- 바쁜 일정속에 동일한 문제에 대해 논의하기까지는 부담스럽지 않나 생각했었지만, 동료분이 원인을 물어봤을 때도 한 번에 예상가는 문제점에 대해서 떠올릴 수 있으려면 이런 일반적인 부분들은 어느 정도 프레임워크화? 공통화가 되어 있어야 한다고 느꼈습니다.
'Dev > JavaScript & TypeScript' 카테고리의 다른 글
class-transformer란 무엇이고 왜 사용할까? (0) | 2024.08.15 |
---|---|
JavaScript의 기본 Error 객체 (0) | 2024.08.05 |
JavaScript의 Number 표현범위 (Java의 int를 곁들인…) (0) | 2024.07.18 |
시퀄라이즈의 타입스크립트 호환성 (0) | 2024.07.03 |
인프런 강의 안봤는데 봤어요 스크립트 (3) | 2024.06.28 |