엔티티에 타입 정의하기
export class UserEntity extends CommonCloumns {
/**
* 이름 칼럼으로 사용자의 이름을 의미
* @minLength 1
* @maxLength 50
*/
@Column({ length: 50, select: false })
public name!: string;
/**
* 사용자의 별칭, 설정하지 않는 경우도 있다.
* @minLength 1
* @maxLength 50
*/
@Column({ length: 50 })
public nickname!: string;
}
각 프로퍼티에는 이처럼, 주석을 통해서 태그를 달 수 있다.
태그가 아닌 주석은 해당 프로퍼티에 대한 description이 되어, 추후 swagger, sdk 생성에 활용된다.
따라서 주석은 프론트 개발자와 소통하는 데에도 사용되기 때문에 훨씬 더 유의미(?)해졌다.
@type {"int"|"uint"} |
number | 정수, 부호가 없는 정수 타입을 의미 |
@minimum {number} |
number | 최솟값(해당 수의 이상) |
@maximum {number} |
number | 최댓값(해당 수의 이하) |
@exclusiveMinimum {number} |
number | 최솟값(해당 수를 초과) |
@exclusiveMaximum {number} |
number | 최댓값(해당 수의 미만) |
@multipleOf {number} |
number | 해당 수의 배수만 허용 |
@step {number} |
number | 해당 수의 간격을 띄운 숫자끼리만 허용. (minimum, exclusiveMinimum이 필요) |
@length {number} |
string | 고정된 문자열의 길이를 의미 |
@minLength {number} |
string | 최소 문자열 길이 |
@maxLength {number} |
string | 최대 문자열 길이 |
@format |
string | 문자의 형식을 지정 |
@pattern {string} |
string | 지정된 정규표현식을 통과하는 문자만 허용 |
@items {number} |
array | 배열의 크기를 지정 |
@minItems {number} |
array | 최소 배열 크기 |
@maxItems {number} |
array | 최대 배열 크기 |
현재 지원되는 태그들은 이 정도가 있는데,
이 정도만 가지고도 class-validator, class-transform을 대체하는 데에 충분하다.
@IsOptional, 이건 뭘로 대체하는가?
export class UserEntity extends CommonCloumns {
@Column()
public gender?: boolean;
}
IsOptional의 경우에는 따로 태그가 필요없다.
그저 프로퍼티 명 옆에 물음표를 추가하여, 그 값이 undefined일 수도 있음을 명시해주기만 하면 된다.
@pattern으로 정규표현식 만들기
/**
* 사용자의 생일을 의미하는 값
*
* @pattern ^(19\d{2}|2\d{3})-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])$
*/
@Column('timestamp with time zone', { nullable: true, select: false })
public birth?: string | null;
YYYY-MM-DD 형태만 저장하고 싶어서 이러한 정규표현식을 작성했다.
예상대로 잘 동작했다.
// custom validator의 예시
import { getDifferTime } from '@root/user-admin/utils/function';
import { registerDecorator, ValidationOptions, ValidationArguments } from 'class-validator';
export function IsAfterDate(validationOptions?: { hours: number } & ValidationOptions) {
return function (object: Record<string, any>, propertyName: string) {
registerDecorator({
name: 'IsAfterDate',
target: object.constructor,
propertyName: propertyName,
options: validationOptions,
constraints: [],
validator: {
validate(value: any, args: ValidationArguments) {
return value instanceof Date && getDifferTime(value, new Date(), 'hour') >= validationOptions.hours;
},
},
});
};
}
기존에는 위와 같이 custom validator를 구현해야 했고, 정규표현식이면 코드가 상당히 길어져야 했다.
그런데 이제 pattern 부분에 주석으로 명시해주기만 하면 되기 때문에 훨씬 더 직관적으로 변했다.