본문 바로가기

STUDY/Spring

Spring Boot | 유효성 검사 직접 만들기! (Custom Constraint)

기본적으로 제공되는 어노테이션 말고, 직접 만들어볼 수 있다. 

 

1. 제약(Constraint) @interface 작성

여기서 message, groups, payload는 기본적으로 꼭 작성해주어야 하는 값이다.

@Size(max = 10, message = "...", groups = {...}) 이런식으로 받아지는 값이라고 생각하면 쉬움

@Target({METHOD, FIELD, TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE})
@Retention(RUNTIME)
@Constraint(validatedBy = SmsBytesSizeValidator.class)
@Documented
public @interface SmsBytesSize {

    String message() default "";

    Class<?>[] groups() default {};

    Class<? extends Payload>[] payload() default {};

}

 

2. 검증자(Validator) 작성

ConstraintValidator를 상속받아 직접 검증하는 코드를 구현할 수 있다.

SmsBytesSize는 위에서 작성한 것.. String은 검증할 Field값이라고 생각하면 된다. 당연히 Object도 가능하다.

 

initialize는 현재의 경우 특별히 작성할 것이 없어 빈채로 나뒀지만(아예 지워버려도 됨) 만약 Constraint에서 어떠한 값을 받기로 했다면 initialize안에서 초기화해주어야 함!

 

isValid는 검증을 하는 부분,, value라는 값으로 검증할 값이 들어오고 그 값을 이용해 유효성 검사를 하면 된다.

나의 경우 현재 90바이트가 넘을 경우에 유효하지 않다고 판단하고 있다.

public class SmsBytesSizeValidator implements ConstraintValidator<SmsBytesSize, String> {

    @Override
    public void initialize(SmsBytesSize constraintAnnotation) {

    }

    @Override
    public boolean isValid(String value, ConstraintValidatorContext context) {
        int count = 0;
        try {
            count = value.getBytes("EUC-KR").length;
            addConstraintViolation(
                    context, "90bytes 초과"
            );
            return count < 90 ? true : false;
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return true;
    }

    private void addConstraintViolation(ConstraintValidatorContext context, String msg) {
        context.disableDefaultConstraintViolation();
        context.buildConstraintViolationWithTemplate(msg).addConstraintViolation();
    }
}

 

3. 사용하기!

직접 만든 어노테이션을 붙여 검증처리 할 수 있다!

groups속성을 이용해 조건처리도 가능

@SmsBytesSize(groups = Sms.class)
private String text;

 

+) groups속성은 구분하기 위한 값으로, 빈 interface를 하나 생성하면 됨

public interface Sms {

}

 

+) 이런식으로 한데 모아 관리하는 것도 가능

public interface ColorGroups {
  public interface Red {}
  public interface Blue {}
  /* ... */
}

///////////

@NotEmpty(groups = ColorGroups.Red.class)
private String required;

 


+) 참고

 

Validation 어디까지 해봤니? : NHN Cloud Meetup

TOAST Cloud의 메시징 플랫폼 상품인 Notification은 메시지, 이메일 주소 형식, 수신/발신자의 번호 등 클라이언트의 입력값에 대해 많은 검증을 진행합니다.

meetup.toast.com