예시 email 검증
// 'class-validator' 패키지에서 필요한 클래스와 함수를 가져옵니다.
import {
registerDecorator,
ValidationOptions,
ValidatorConstraint,
ValidatorConstraintInterface,
ValidationArguments,
} from 'class-validator';
// 이것은 특정 것을 검증하기 위한 데코레이터입니다. 여기서는 이메일을 검사하고 있습니다.
@ValidatorConstraint({ async: false })
class IsCustomEmailConstraint implements ValidatorConstraintInterface {
// 이 'validate' 함수는 제공된 이메일이 유효한지 확인합니다.
validate(email: string, args: ValidationArguments) {
// 이메일이 유효하다고 간주되려면 일치해야 하는 패턴입니다.
const emailRegex = /^[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,}$/;
// 이메일이 패턴과 일치하지 않는지 확인
if (!emailRegex.test(email)) {
// 일치하지 않으면 '잘못된 형식'이라고 말합니다.
args.constraints[0] = 'invalidFormat';
return false;
}
// 이메일의 첫 부분(‘@’ 전)에 특수 문자가 있는지 검사합니다.
const specialChars = /[!#$%&'*+/=?^_`{|}~-]/;
const localPart = email.split('@')[0];
// 이메일의 첫 부분의 첫 번째 또는 마지막 문자가 특수 문자인지 확인합니다.
if (specialChars.test(localPart[0]) || specialChars.test(localPart[localPart.length - 1])) {
args.constraints[0] = 'specialCharFirstOrLast';
return false;
}
// 이메일의 첫 부분에서 두 특수 문자가 나란히 있는지 확인합니다.
for (let i = 0; i < localPart.length - 1; i++) {
if (specialChars.test(localPart[i]) && specialChars.test(localPart[i + 1])) {
args.constraints[0] = 'consecutiveSpecialChars';
return false;
}
}
// 모든 검사를 통과하면, 이메일은 유효합니다.
return true;
}
// 이 함수는 무엇이 잘못되었는지에 따라 기본 오류 메시지를 제공합니다.
defaultMessage(args: ValidationArguments) {
const failureReason = args.constraints[0];
switch (failureReason) {
case 'invalidFormat':
return '이메일 형식이 잘못되었습니다. 표준 이메일 형식(예: user@example.com)을 따라야 합니다.';
case 'specialCharFirstOrLast':
return '이메일이 유효하지 않습니다. 이메일 주소의 첫 번째 또는 마지막 문자로 특수 문자가 올 수 없습니다.';
case 'consecutiveSpecialChars':
return '이메일이 유효하지 않습니다. 특수 문자가 연속해서 두 번 이상 나타날 수 없습니다.';
default:
return '이메일이 유효하지 않습니다.';
}
}
}
// 이 함수는 사용자 정의 이메일 검증기를 생성하기 위해 사용됩니다.
export function IsEmailCustom(validationOptions?: ValidationOptions) {
return function (object: Object, propertyName: string) {
// 이 코드는 클래스의 속성에 사용자 정의 이메일 검증기를 등록합니다.
registerDecorator({
target: object.constructor,
propertyName: propertyName,
options: validationOptions,
constraints: [],
validator: IsCustomEmailConstraint,
});
};
}
ValidatorConstraintInterface
→ 커스텀 validation 로직을 제공하기 위해 꼭 구현해야하는 인터페이스
→ 자신이 만든 custom valdators (검증자) 에 있는 custion validation(검증) 규칙을 제공하기 위해 꼭 구현해야하는 interface
→ implements 를 이용하여 해당 속성을 다른 클래스에 주입
ValidationArguments
→ 유효성 검사 과정에 대한 정보를 제공하기 위해 사용
→ validation 규칙을 확인하는 과정 중에 보내고 싶은 메세지를 저장
추가 코드 설명 : IsEmailCustom
IsEmailCustom 함수는 이메일 주소의 유효성을 검사하는 사용자 정의 검증기를 적용하기 위해 사용됩니다. 이 함수는 다음과 같이 구성되어 있습니다:
- 함수 인자: validationOptions - 이것은 선택적 인자로, 검증기의 동작을 설정할 수 있는 옵션을 제공합니다. 예를 들어, 특정 메시지를 표시하거나, 검증 실패 시 행동을 정의할 수 있습니다.
- 반환되는 함수: 이 함수는 object (대상 객체)와 propertyName (속성 이름)을 인자로 받습니다. 이 두 인자를 사용하여 특정 클래스의 특정 속성에 검증기를 적용합니다.
- registerDecorator 함수: 이 내장 함수는 실제로 검증기를 해당 속성에 연결하는 역할을 합니다. 여기서는 몇 가지 주요 옵션을 설정합니다:
- target: 검증기를 적용할 클래스의 생성자입니다. 즉, 검증기가 어떤 클래스의 어떤 속성에 적용될지 정의합니다.
- object.constructor는 JavaScript에서 매우 중요한 개념 중 하나, object.constructor는 해당 객체의 생성자 함수를 참조합니다. 생성자 함수는 객체를 생성하고 초기화하는 데 사용되는 특별한 메소드입니다.
- propertyName: 검증기가 적용될 속성의 이름입니다.
- options: 검증 시 적용할 추가 옵션들입니다. (예: 에러메세지)
- constraints: 검증기에 전달할 추가적인 제약 조건을 배열 형태로 제공합니다.
- validator: 실제로 이메일 유효성을 검사할 로직을 포함하고 있는 파일을 지정합니다. : IsCustomEmailConstraint 클래스
- target: 검증기를 적용할 클래스의 생성자입니다. 즉, 검증기가 어떤 클래스의 어떤 속성에 적용될지 정의합니다.
object.constructor의 역할
- registerDecorator에서 object.constructor를 사용하는 이유는, 해당 데코레이터를 적용할 "클래스"를 정확하게 지정하기 위함입니다. 클래스의 인스턴스(즉, 객체)가 제공될 때, object.constructor를 통해 이 객체가 어떤 클래스에서 생성되었는지를 알 수 있습니다. 이 정보를 사용하여 클래스 레벨에서 속성이나 메소드에 특정 데코레이터를 연결할 수 있습니다.
- 예시
class Person {
constructor(name) {
this.name = name;
}
}
let joey = new Person("joey");
joey.constructor // Person class 의 구조가 출력됩니다.
데코레이터 사용 예시
export class SignUpRequestDto {
@IsEmailCustom()
email: string;
}
@IsEmailCustom() 은 자동으로 registerDecorator를 호출하여, SignUpRequestDto 클래스의 email 속성에 유효성 검사기를 적용합니다. 즉, target 파라메터에 SignUpRequestDto 클래스가 할당되어 SignUpRequestDto 구조를 파악하고, propertyName 에 할당된 email에 유효성 검사기인 "IsCustomEmailConstraint" 이 적용 되어집니다.
참고자료
- class-validator 라이브러리
'프로그래밍 > Nest.js' 카테고리의 다른 글
[ Nest.js ] cross-validator 의 데코레이터가 적용이 안되는 경우 (0) | 2024.07.14 |
---|---|
[ Nest.js ] [ TypeORM ] bulk insert (0) | 2024.07.06 |
[ Nest.js ] 테스트 코드 작성 FIRST 원칙 (0) | 2024.06.30 |
[ Nest.js ] Logger 구현 (0) | 2024.06.26 |
[ NestJS ] Jest 의 기본 사용법 (0) | 2024.06.14 |