개발/Spring

Spring / 어노테이션으로 Parameter 검증하기

highright96 2021. 8. 17.

본 글의 예제 코드는 아래 링크에서 확인하실 수 있습니다.

https://github.com/highright96/spring-practice

 

GitHub - highright96/spring-practice: 책, 프로젝트 등을 참고하여 작성하는 예제

책, 프로젝트 등을 참고하여 작성하는 예제. Contribute to highright96/spring-practice development by creating an account on GitHub.

github.com

 

라이브러리 추가

dependencies {
	implementation 'org.springframework.boot:spring-boot-starter-validation'
}

데이터 검증하기

서버는 클라이언트의 요청 데이터를 바인딩할 때, 데이터가 유효한지 검사해야한다. 물론 클라이언트에서 검사를 한 후 요청을 보내지만, 데이터를 변형해서 보낼 수 있는 위험이 있기 때문에 서버에서도 반드시 검증을 해야한다.

 

스프링에서 제공하는 검증기(Validator)를 사용하면, 간단한 검증은 어노테이션 하나로 처리할 수 있다.

 

보여줄 예제의 검증 조건은 다음과 같다.

1. 이름은 필수값이다.

2. 나이는 필수값이며, 90이하의 숫자이여야 한다.

3. 이메일은 이메일 양식에 맞춰야 한다.

 

검증 조건에 맞춰 요청에 바인딩될 DTO는 다음과 같다.

@Getter
@Setter
public class User {
    @NotBlank //NULL or 빈 문자열 검사
    private String name;

    @NotNull //NULL 검사
    @Max(value = 90) //최대값 검사
    private Integer age;

    @Email //이메일 양식 검사
    private String email;
}

클라이언트의 요청을 받을 컨트롤러는 다음과 같다.

@RestController
@RequestMapping("/api/validation-v1")
public class ValidationControllerV1 {
    @PostMapping
    public ResponseEntity<User> user(@Valid @RequestBody User user) {
        return ResponseEntity.ok(user);
    }
}

유효성 검증이 필요한 DTO 앞에 @Valid 어노테이션을 추가해야한다.

커스텀 어노테이션으로 데이터 검증하기

날짜를 입력받는데 yyyyMMdd 형식으로 받고 싶을때가 있다. 하지만 Validation에서는 이런 형식을 검증해줄 Validator을 제공하지 않는다.

 

Spring이 제공하는 검증 외의 커스텀한 검증이 필요하면, 다음과 같이 새로운 Validator을 생성하면 된다.

 

YearMonth 어노테이션

@Constraint(validatedBy = {YearMonthValidator.class})
@Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE})
@Retention(RUNTIME)
public @interface YearMonth {

    String message() default "yyyyMMdd 형식에 맞지 않습니다.";

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

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

    String pattern() default "yyyyMMdd";
}

 

YearMonthValidator.class

public class YearMonthValidator implements ConstraintValidator<YearMonth, String> {

    private String pattern;

    @Override
    public void initialize(YearMonth yearMonth) {
        pattern = yearMonth.pattern();
    }

    @Override
    public boolean isValid(String value, ConstraintValidatorContext context) {
        try {
            LocalDate.parse(value, DateTimeFormatter.ofPattern(pattern));
        } catch (Exception e) {
            return false;
        }
        return true;
    }
}

isValid 메서드를 통해 @YearMonth 어노테이션이 붙은 값을 검증한다. false가 반환되면 MethodArgumentNotValidException이 발생한다. Spring이 제공하는 다른 검증 어노테이션도 동일한 예외를 발생한다.

 

변경된 DTO는 다음과 같다.

@Getter
@Setter
public class User {

    @NotBlank
    private String name;

    @NotNull
    @Max(value = 90)
    private Integer age;

    @Email
    private String email;

    @YearMonth
    private String reqYearMonth; 
}

작동 확인

포스트맨으로 확인해보니 정상 작동하는 것을 확인할 수 있다.

참고

https://docs.spring.io/spring-framework/docs/3.2.x/spring-framework-reference/html/validation.html

https://www.baeldung.com/spring-boot-bean-validation

댓글