1 분 소요


Validator 분리1

컨트롤러에서 검증 로직이 차지하는 부분이 매우 크기 때문에 별도의 클래스로 역할을 분리하는 것이 좋다.

ItemValidator.class

@Component
public class ItemValidator implements Validator {

    @Override
    public boolean supports(Class<?> clazz) {
        return Item.class.isAssignableFrom(clazz);
    }

    @Override
    public void validate(Object target, Errors errors) {
        Item item = (Item) target;

        ValidationUtils.rejectIfEmptyOrWhitespace(errors, "itemName", "required");

        // 컨트롤러에 있던 검증 로직을 모두 이곳에 넣는다.
        // bindingResult대신 errors 파라미터를 사용한다.
    }
}

public interface Validator {
    boolean supports(Class<?> clazz);
    void validate(Object target, Errors errors);
}
  • supports() {}: 해당 검증기를 지원하는 여부 확인
  • validate() : 검증 대상 객체와 BindingResult

addItemV5

private final ItemValidator itemValidator;

// ...

itemValidator.validate(item, bindingResult);
 
if (bindingResult.hasErrors()) {
    log.info("errors={}", bindingResult);
    return "validation/v2/addForm";
}


Validator 분리2

스프링이 Validator인터페이스를 별도로 제공하는 이유는 체계적으로 검증 기능을 도입하기 위해서다. 앞에서는 검증기를 직접 불러서 사용했지만, Validator인터페이스를 사용해서 검증기를 만들면 스프링의 추가적인 도움을 받을 수 있다.

WebDataBinder

WebDataBinder는 스프링의 파라미터 바인딩의 역할을 해주고 검증 기능도 내부에 포함한다.

Controller에 다음 코드 추가

@InitBinder
public void init(WebDataBinder dataBinder) {
    log.info("init binder {}", dataBinder);
    dataBinder.addValidators(itemValidator);
}
  • WebDataBinder에 검증기를 추가하면 해당 컨트롤러에서는 검증기를 자동으로 적용.
  • @InitBinder -> 해당 컨트롤러에만 영향을 준다.

@Validated 적용

Controller

@PostMapping("/add")
public String addItemV6(@Validated @ModelAttribute Item item, BindingResult bindingResult, RedirectAttributes redirectAttributes) {
    if (bindingResult.hasErrors()) {
        log.info("errors={}", bindingResult);
        return "validation/v2/addForm";
    }
}

validator를 직접 호출하는 부분이 사라지고, 검증 대상 앞에 @Validated가 붙었다.

동작 방식

@Validated는 검증기를 실행하라는 애노테이션이다.
이 애노테이션이 붙으면 앞서 WebDataBinder에 등록한 검증기를 찾아서 실행한다.
이때 여러 검증기를 등록한다면 그 중에 어떤 검증기가 실행되어야 할지 구분이 필요한데 이때 supports()가 사용된다.

여기서는 supports(Item.class)가 호출되고, 결과가 true이므로 ItemValidatorvalidate()가 호출된다.


<출처 : 인프런 스프링 MVC 2편 - 백엔드 웹 개발 활용 기술(김영한)>

댓글남기기