4. 글로벌 범위 Validator와 컨트롤러 범위 Validator

meteorfish·2022년 11월 8일

spring CH12 MVC 2

목록 보기
3/4

글로벌 범위 Validator : 모든 컨트롤러에 적용
컨트롤러 범위 Validator : 단일 컨트롤러에 적용



4.1 글로벌 범위 Validator설정과 @Valid 애노 테이션

[ 설정 요소 ]

  • 설정 클래스에서 WebMvcConfigurer의 getValidator()가 Validator 객체를 리턴
    하도록 구현
  • 글로벌 범위 Validator가 검증할 커맨드 객체에 @Valid 적용

WebMvcConfigurer의 getValidator()가 Validator 객체를 리턴

-> MvcConfig.java

@Configuration
@EnableWebMvc
public class MvcConfig implements WebMvcConfigurer {
    @Override
    public Validator getValidator() {
        return new RegisterRequestValidator();
    }
    
    ...
}
  • getValidator()가 리턴한 객체를 글로벌 범위 Validator 로 사용.
  • 그러면, @Valid로 사용할 Validator 적용 가능.
  • 컨트롤러에서 해당 커맨드 객체에 @Valid 붙여서 글로벌 범위 Validator를 적용하자.

글로벌 범위 Validator가 검증할 커맨드 객체에 @Valid 적용

NOTE
@Valid 사용하기 위해 의존을 추가하자.

  implementation 'org.springframework.boot:spring-boot-starter-validation'

-> RegisterController.java

	@PostMapping("/register/step3")
    public String handleStep3(@Valid RegisterRequest regReq, Errors errors){
        if(errors.hasErrors())
            return "register/step2";
        try{
            memberRegisterService.regist(regReq);
            return "register/step3";
        } catch(DuplicateMemberException ex){
            errors.rejectValue("email", "duplicate");
            return "register/step2";
        }
    }
  • @Valid 붙이면 글로벌 범위 Validator가 해당 타입을 검증할 수 있는지 확인.
  • 그리고 결과를 Errors에 저장.
  • 이 과정은 handleStep3()가 실행되기 전에 이뤄지므로 별도의 파라미터 없이 Error 만으로 검증 에러를 확인 가능!

[ 주의 사항 ]

Errors 타입 파라미터가 없으면 검증 실패 시 400 에러 응답 뜸!

RegisterRequestValidator 클래스는 RegisterRequest 타입만 검증 가능.
따라서, 글로벌 범위 Validator로 부적합.


스프링 MVC는 자체적으로 글로벌 Validator 제공해서 이를 이용해 Bean Validation이 제공하는 애노테이션으로 값 검증이 가능.
이는 추후에...



4.2 @InitBinder을 이용한 컨트롤러 범위 Validator

@initBinder를 이용해 컨트롤러 범위 Validator 설정.

-> Registercontroller.java

	@PostMapping("/register/step3")
    public String handleStep3(@Valid RegisterRequest regReq, Errors errors){
        if(errors.hasErrors())
            return "register/step2";
        try{
            memberRegisterService.regist(regReq);
            return "register/step3";
        } catch(DuplicateMemberException ex){
            errors.rejectValue("email", "duplicate");
            return "register/step2";
        }
    }
    
	@InitBinder
    protected void initBinder(WebDataBinder binder){
        binder.setValidator(new RegisterRequestValidator());
    }
  • 어떤 Validator가 커맨드 객체를 검증할지는 initBinder()가 결정.
  • @InitBinder 붙은 메서드는 setValidator()를 이용해 컨트롤러 범위에 적용할 Validator 설정.
  • RegisterRequestValidator를 컨트롤러 범위 Validator로 설정했으므로 @Valid붙은 RegisterRequest 검증 시, 이 Validator를 사용함.
  • @InitBinder가 붙은 메서드는 요청 처리 메서드 실행 전에 매번 실행됨!
  • WebDataBinder는 내부적으로 Validator 목록을 갖음.
  • 이 목록에는 글로벌 범위 Validator가 기본으로 포함.
  • setValidator()를 하면 기존 Valiteor 목록을 삭제하고 파라미터로 전달받은 Validator를 목록에 추가
    => 글로벌 범위 Validator 대신 컨트롤러 범위 Validator 사용.

addValidator()는 기존 Validator 목록에 새로운 Validator 추가.
즉, 글로벌 범위 Validator 존재할 때 실해하면, 새로운 추가 컨트롤러 범위 Validator가 기존꺼 뒤에 추가됨.

0개의 댓글