커맨드 객체의 값 검증


폼에서 넘어온 파라미터의 값이 정상적인 값인지 검증하는 작업이 필요하다. (이를 Validation 체크라 한다.)

스프링 MVC에서는 이를 위해 2가지 인터페이스를 지원한다.

  • org.springframework.validation.Validator
  • org.springframework.validation.Errors

 

Validator 인터페이스는 다음과 같다.

public interface Validator {
    
    boolean supports(Class<?> clazz); // Validator가 검증할 수 있는 타입인지 확인한다.
    void validate(Object target, Errors errors); // target을 검증한 후, 에러값이 있다면 errors에 담는다.
}

 

위의 인터페이스를 구현해서 회원가입 폼에서 넘어온 커맨드 객체를 검증해보자.

public class RegisterRequestValidator implements Validator {

    private static final String emailRegExp = 
            "^[_A-Za-z0-9-\\+]+(\\.[_A-Za-z0-9-]+)*@" +
            "[A-Za-z0-9-]+(\\.[A-Za-z0-9]+)*(\\.[A-Za-z]{2,})$";
    
    private Pattern pattern;
    
    public RegisterRequestValidator() {
        pattern = Pattern.compile(emailRegExp);
    }
    
    @Override
    public boolean supports(Class<?> clazz) {
        return RegisterREquest.class.isAssignableFrom(clazz);
    }
    
    @Override
    public void validate(Object target, Errors errors) {
        RegisterREquest regReq = (RegisterRequest) target;
        
        if (regReq.getEmail() == null || regReq.getEmail().trim().isEmpty()) {
            errors.rejectValue("email", "required");
        } else {
            Matcher matcher = pattern.matcher(regReq.getEmail());
            
            // 패턴과 매칭되지 않으면
            if (!matcher.matches()) 
                errors.rejectValue("email", "bad");
        }
        
        ValidationUtils.rejectIfEmptyOrWhitespace(errors, "name", "required");
        ValidationUtils.rejectIfEmpty(errors, "password", "required");
        ValidationUtils.rejectIfEmpty(errors, "confirmPassword", "required");
        
        if (!regReq.getPassword().isEmpty()) {
            if (!regReq.isPasswordEqualToConfirmPassword())
                errors.rejectValue("confirmPassword", "nomatch");
        }
    }
}

 

구현한 검증 객체는 컨트롤러에서 사용한다.

@Controller
public class RegisterController {

    private MemberRegisterService memberRegisterService;
    
    // ...중략
    
    @PostMapping(value = "/register")
    public ModelAndView register(@RequestBody RegisterRequest regReq, Errors errors, ModelAndView mnv) {
        
        new RegisterRequestValidator().validate(regReq, errors); // 커맨드 객체를 검증한다 !

        if (errors.hasErrors()) { // 만약 검증에 실패하면, 회원가입 폼을 다시 보여준다.
            mnv.setViewName("register/registerForm");
            return mnv; 
        }
        
        try {
            memberRegisterService.regist(regReq);
            mnv.setViewName("register/registerSuccess");
            return mnv;
        } catch (DuplicateMemberException e) {
            errors.rejectValue("email", "duplicate");
            mnv.setViewName("register/registerForm");
            return mnv;
        }
    }
}