(스프링) 커맨드 객체의 값 검증과 에러 메시지 처리
*회원가입 처리 부분의 코드가 동작하긴 하지만, 정상적이지 않은 값을 입력해도 정상적으로 동작할 수 있다. 올바르지 않은 이메일 주소를 입력해도 가입 처리가 되고 이름을 입력하지 않아도 가입을 할 수 있다.
또 다른 문제는 중복된 이메일 주소를 입력해서 다시 폼을 보여줄 때 가입이 처리되지 않는 이유에 대한 설명을 보여주지 않는다. 가입이 실패하는 이유를 보여주어야 한다. 그렇지 않으면 사용자는 혼란을 겪는다.
또 다른 문제는 중복된 이메일 주소를 입력해서 다시 폼을 보여줄 때 가입이 처리되지 않는 이유에 대한 설명을 보여주지 않는다. 가입이 실패하는 이유를 보여주어야 한다. 그렇지 않으면 사용자는 혼란을 겪는다.
1. 커맨드 객체 검증과 에러 코드 지정하기
다음 두 인터페이스를 사용한다.
- org.springframework.validation.Validator
- org.springframework.validation.Errors
Validator 인터페이스는 객체를 검증할 때 사용되며, 다음과 같이 정의되어 있다.
public interface Validator{
boolean supports(Class<?> clazz);
void validate(Object target, Errors errors);
}
--->supports()메소드는 Validator가 검증할 수 있는 타입인지를 검사할 목적으로 사용되고, validate()메소드는 첫 번쨰 마라미터로 전달받은 객체를 검증하고 그 결과를 Erros에 담는 기능을 정의한다.
-->validate()메소드에서 target을 실제 타입으로 변환한 뒤에 if문에서 값을 검사한다. email프로퍼티의 값이 유효한지를 검사한다. "email"프로퍼티 값이 존재하지 않을 경우(null이나 빈 문자열인 경우) , errors.rejectValue("email", "required"); "required"를 추가한다.
matcher을 통해 정규표현식이 일치한지 검사한다.
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "name", "required");
ValidationUtils.rejectIfEmpty(errors, "password", "required");
ValidationUtils.rejectIfEmpty(errors, "confirmPassword", "required");
ValidationUtils클래스는 객체의 값 검증 코드를 간결하게 작성할 수 있도록 도와준다.
위 코드는 검사 대상 객체의 "name"프로퍼티가 null이거나 공백문자로만 되어 있는 경우, "name" 프로퍼티의 에러 코드로 required를 추가한다.
여기서 궁금한 점은 ValidationUtils.rejectIfEmptyOrWhitespace()메소드를 실행할 때 검사 대상 객체인 target을 파라미터로 전달하지 않는데, 어떻게 target객체의 "name" 프로퍼티의 값을 검사할까?
비밀은 Errors에 있다.
위 코드처럼 @RequestMapping 적용 메소드의 커맨트 객체 파라미터 뒤에 Errors타입의 파라미터가 위치하면, 스프링 MVC는 handlestep3()메소드를 호출할 때 커맨드 객체와 연결된 Errors객체를 생성해서 파라미터로 전달한다.
이 Errors 객체는 getFieldValue()메소드를 제공하고 있으며, 이 메소드를 사용하면 커맨드 객체의 특정 프로퍼티 값을 가져올 수 있다.
위 코드를 보면 앞서 작성한 RegisterRequestValidator객체를 생성하고 validate()메소드를 실행하고 있다. 이를 통해 RegisterRequest커맨드 객체의 값이 올바른지 검사하고 그결과를 Errors객체에 담는다.
memberRegidterService.regist()는 동일한 이메일을 가진 회원데이터가 이미 존재할 경우 AlreadyExistingMemberException을 발생시킨다. 또한, 이메일 중복에러를 추가하기 위해 "email" 프로퍼티의 에러코드 "duplicate"를 추가했다.
커맨드 객체의 특정 프로퍼티가 아닌 커맨드객체 자체가 잘못될 수도 있는데, 이런 경우에는 rejectValue()메소드 대신에 reject()메소드를 사용한다.
예를들어, 로그인 아이디와 비밀번호를 잘못 입력한 경우, 아이디가 잘못되었거나 아이디가 맞는데 비밀번호가 틀렸다는 식으로 에러 메시지를 보여주기 보다는, 보안을 위해 아이디와 비밀번호가 일치하지 않는다고 메시지를 보여주곤 한다.
이런 경우에는 특정 프로퍼티에 에러를 추가하기 보다는 커맨드 객체 자체에 에러를 추가해야 하는데, 이때 reject()메소드를 사용한다.
이런 종류의 에러를 글로벌에러라고 부른다.
@RequestMapping메소드에 Errors타입의 파라미터를 추가할 때 주의할점은, Errors타입 파라미터는 반드시 커맨드 객체를 위한 파라미터 다음에 위치해야 한다는 것이다.
댓글
댓글 쓰기