저번에는 중복 조건과 같이 조금 애매한 부분을 처리할 수 없었다.
annotation을 커스텀할 수 있다.
닉네임, 이름 둘 중 하나만 있어도 통과시켜줄 수 있는 것을 만들어보자
AssertTrue annotation은 이 is 라는 boolean을 return하는 메소드에 반드시 붙여줘야 한다.
Name Object가 null이 아니어야 되고 name이 blank가 아니여야 통과할 수 있다.
private String name;
private String nickName;
@AssertTrue(message = "name or nickname 은 존재해야 합니다.")
public boolean isNameCheck(){
if(Objects.nonNull(name) && !name.isBlank()) {
return true;
}
if(Objects.nonNull(nickName) && !nickName.isBlank()) {
return true;
}
return false;
}
"resultCode": "",
"resultMessage": "",
"data": {
"name": "",
"nickname": "",
"age": 20,
"password": "1111",
"email": "meow@gmail.com",
"phone_number": "123-456-7890",
"register_at": "2025-01-01T13:00:00"
},
"error": {
"errorMessage": []
}
}
json을 위처럼 send했더니 error가 제대로 떴다.

name에 이름을 넣으면 잘 전송된다.

이번엔 phonenumber에 대한 코드를 작성해보자
@Constraint(validatedBy = {PhoneNumberValidator.class})은 어떤 클래스로 검증을 할 것이냐 라고 해서 validator을 지정해주는 것이다.
@Target({ElementType.FIELD})는 변수에다가 붙일 것이기 때문에 field만 붙이자.
@Retention(RetentionPolicy.RUNTIME)은 Policy가 실행 중에만 annotation이 동작하는 것이다.
@Constraint(validatedBy = {PhoneNumberValidator.class})
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface PhoneNumber {
String message() default "핸드폰 번호 양식에 맞지 않습니다. ex) 000-0000-0000";
String regexp() default "^\\d{2,3}-\\d{3,4}-\\d{4}$";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
이제 phonenumber를 검증해주는 클래스를 작성해보자
public class PhoneNumberValidator implements ConstraintValidator<PhoneNumber, String> {
// 초기화할때 default 패턴을 가져오기 위해
private String regexp;
@Override
public void initialize(PhoneNumber constraintAnnotation) {
this.regexp = constraintAnnotation.regexp();
}
@Override //어떤 값을 검증할 것인지는 value에 할당된 값이 넘어 오고, 그 값을 검증해줘야 한다.
public boolean isValid(String value, ConstraintValidatorContext context) {
if (value == null) {
return true; // null 값을 허용하는 경우 true 반환
}
boolean result = Pattern.matches(regexp, value);
return result;
}
}
그리고 저번에 했던 정규식을 정해놓은 @Pattern annotation을 지우고 @PhoneNumber annotation을 달아보자
@PhoneNumber
private String phoneNumber;
그러면 400error가 뜨면서 errorMessage도 제대로 뜨게 된다.

이번엔 날짜 검증, YearMonth를 만들어보자
UserRegisterRequest에 아래 코드를 추가하고
@YearMonth(pattern = "yyyy-MM")
private String birthDayYearMonth;
package com.example.validation.annotation;
import com.example.validation.validator.PhoneNumberValidator;
import com.example.validation.validator.YearMonthValidator;
import jakarta.validation.Constraint;
import jakarta.validation.Payload;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Constraint(validatedBy = {YearMonthValidator.class})
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@NotBlank
public @interface YearMonth {
String message() default "Year Month 양식에 맞지 않습니다. ex) 230101";
String pattern() default "yyyyMMDD";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
package com.example.validation.validator;
import com.example.validation.annotation.PhoneNumber;
import com.example.validation.annotation.YearMonth;
import jakarta.validation.ConstraintValidator;
import jakarta.validation.ConstraintValidatorContext;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.regex.Pattern;
public class YearMonthValidator implements ConstraintValidator<YearMonth, String> {
private String pattern;
@Override
public void initialize(YearMonth constraintAnnotation) {
this.pattern = constraintAnnotation.pattern();
}
@Override //어떤 값을 검증할 것인지는 value에 할당된 값이 넘어 오고, 그 값을 검증해줘야 한다.
public boolean isValid(String value, ConstraintValidatorContext context) {
var reValue = value + "01";
var rePattern = pattern + "dd";
try {
LocalDate date = LocalDate.parse(value, DateTimeFormatter.ofPattern(value));
System.out.println(date);
return true;
} catch (Exception e) {
return false;
}
}
}
코드를 위처럼 작성하고 우선 틀린 양식의 YearMonth를 보내보자
{
"resultCode": "",
"resultMessage": "",
"data": {
"name": "sdf",
"nickname": "dsf",
"age": 20,
"password": "1111",
"email": "meow@gmail.com",
"phone_number": "010-1234-4564",
"register_at": "2025-01-01T13:00:00",
"birth_day_year_month": "202301"
},
"error": {
"errorMessage": []
}
}
400 에러가 뜨고

제대로 넣으면 200 ok 가 뜨면서 잘 온다.
