Spring boot 프로젝트 만드는 과정에서 Validator를 한번 써보기 위해서 적용을 시켜봤습니다..
보통 특정 객체에 대한 검증을 하기 위해서 사용된다.
Validator 인터페이스를 사용하기 위해서는 2가지 메서드를 오버라이딩해서 사용합니다.
@Override
public boolean supports(Class<?> clazz) {
}
@Override
public void validate(Object target, Errors errors) {
}
supports -> 어떤 클래스의 객체의 검증을 지원할 것인지에 대한 코드를 작성해야한다.
validate -> 매개변수 target의 객체에 대하여 검증을 실행 한 후 문제가 있을 경우 errors 를 통해서
확인합니다.
예시코드
@Setter
@Getter
public class SignUpRequest {
// 이메일, 이름, 비밀번호, 주소( 3가지 )
@Email
@NotBlank
private String email;
@Length(min = 2)
@NotBlank
private String name;
@Length(min = 8, message = "최소 8자 이상 입력해주세요.")
@NotBlank
private String password;
@Length(min = 8, message = "최소 8자 이상 입력해주세요.")
@NotBlank
private String confirmPassword;
@NotEmpty
private String zipcode;
@NotEmpty
private String extraAddress;
@NotEmpty
private String detailsAddress;
private boolean verifyPassword;
... 생략
}
회원가입을 위해서 사용할 DTO를 만들었고 해당 DTO의 객체들에 대한 검증을 위해서 Validation 타입의
어노테이션을 적용시켜뒀습니다.
@RequiredArgsConstructor
@Component
public class SignUpValidator implements Validator {
private final MemberRepository memberRepository;
@Override
public boolean supports(Class<?> clazz) {
return clazz.isAssignableFrom(SignUpRequest.class);
}
@Override
public void validate(Object target, Errors errors) {
SignUpRequest signupRequest = (SignUpRequest) target;
if(!verifyPassword(signupRequest)) {
errors.rejectValue("password", "NOT_CORRECT_PASSWORD","비밀번호가 일치하지 않습니다.");
} else if(existEmail(signupRequest)) {
errors.rejectValue("email", "EXIST_EMAIL","이미 존재하는 이메일입니다.");
}
}
private boolean verifyPassword(SignUpRequest signupRequest) {
return signupRequest.isVerifyPassword();
}
private boolean existEmail(SignUpRequest signupRequest) {
return memberRepository.existsByEmail(signupRequest.getEmail());
}
}
supports 메서드의 반환값 코드의 경우 한가지가 더 있다고 하는데 둘 중 하나인 isAssignableFrom을 사용했습니다.
기본적으로 회원가입할 때 비밀번호를 2번 입력하게 하는 로직이 대부분이기 때문에
동일한 비밀번호 입력 여부와 간단하게 이미 가입된 이메일주소인지에 대한 여부만 검증을 했습니다.
errors.rejectValue를 통해서 해당 검증에 대한 에러의 자세한 내용을 다루면됩니다.
Controller
@RestController
@RequiredArgsConstructor
@Log4j2
public class MemberApiController {
private final MemberService memberService;
private final SignUpValidator signUpValidator;
private final static String API_URI = "/api/member";
@InitBinder("signUpRequest") // 네이밍 주의
public void signupInitBinder(WebDataBinder webDataBinder) {
webDataBinder.addValidators(signUpValidator);
}
// 회원등록
@PostMapping(API_URI)
public ResponseEntity<String> signUpRequest(@RequestBody @Valid SignUpRequest signup,
Errors errors) {
if(errors.hasErrors()) {
return new ResponseEntity<>(errors.getFieldError().getDefaultMessage(), HttpStatus.BAD_REQUEST);
}
// 회원가입 진행
// save 반환타입 추후 변경
Long memberId = memberService.signUp(signup);
return new ResponseEntity<>("success", HttpStatus.OK);
}
}
@InitBinder를 통해서 WebDataBinder로 Validator를 설정하시면 됩니다.
@InitBinder의 값을 넣을 떄 검증하려는 객체의 클래스명칭을 넣으면 되는데 이때 네이밍을 주의해야합니다.
해당 클래스의 변수명을 지정할때와 같은 공식으로 MemberDto라면 "memberDto" 이런식으로
입력해주셔야 정상적으로 작동을 합니다.
테스트 코드로 진행했을 때 작동을 하지않아서 꽤 애먹었던 부분이기도 합니다.
public ResponseEntity<String> signUpRequest(@RequestBody @Valid SignUpRequest signup,
Errors errors) {
if(errors.hasErrors()) {
return new ResponseEntity<>(errors.getFieldError().getDefaultMessage(), HttpStatus.BAD_REQUEST);
}
}
상단의 회원가입 메서드 부분을 발췌했습니다.
여기서 @Valid를 지정해주시고 Errors를 매개변수로 받으시면 되겠습니다.
SignUpValidator에서 validate 메서드를 통해서 검증실패로 인해 에러가 발생하게 되면 Errors 타입 객체를 통해서
에러가 저장되고 해당 매개변수를 통해서 그에 따른 처리를 하시면 되겠습니다.
Errors 가 아닌 BindingResult 타입 파라미터를 사용하셔도 무방합니다.
'Back-End > Spring' 카테고리의 다른 글
Spring Boot + Gradle + MyBatis 설정 (0) | 2021.07.05 |
---|---|
Spring Boot Test Code 동작순서 정렬 - @TestMethodOrder (0) | 2021.06.25 |
Spring boot @ControllerAdvice (0) | 2021.05.17 |
@QueryProjection 으로 Querydsl 작성 (1) | 2021.05.11 |
JPA) @Entitygraph (0) | 2021.05.07 |