Written on
·
426
1
기본 원리 이해해가며 많은 도움이 되었습니다. 그리고 배운 내용을 확장하는 와중에 영한님 의견을 꼭 듣고 싶습니다. 제가 지금 스프링 전체를 이해하지 못해서 이런 고민을 하게된건지, 아니면 원래 이렇게 짜야하는 건지 모르겠습니다. 만약 뒤에 강의나 다른강의에서 해결하는 방법이 나온다면 그 파트만 말해주셔도 감사합니다.
제가 짠 코드는 이렇습니다.
@PostMapping("/login") public String login(@Validated @ModelAttribute("loginForm") LoginForm form, BindingResult bindingResult, HttpServletRequest request) { if (bindingResult.hasErrors()) { return "login"; } loginValidator.validateLogin(form, bindingResult); if (bindingResult.hasErrors()) { return "login"; } loginService.login(request, form.getEmail()); return "redirect:/"; }
타입 검증을 하고 문제가 없으면 논리 검증코드를 거치고 논리 검증코드에 문제가 있으면 bindingResult에 reject를 넣는 코드를 짰습니다. 그래서 문제를 다시 검사합니다. 근데 이 코드가 맘에 안드는게 hasErrors 코드가 2번으로 중복됩니다.
그래서 이를 줄인다고 loginValidator 안에 밑의 코드를 넣을 수 있지만 이래도 여전히 문제가 되는게 만드는 Validator를 만드는 족족 밑의 코드를 넣어야 하니 컨트롤러쪽에서는 깔끔하겠지만, 나중에 계속 다음 Validator를 만들 때마다 코드를 넣는 중복도 피할 수 없습니다.
if (bindingResult.hasErrors()) { return; }
그래서 질문은 다음과 같습니다.
원래 검증하는 부분을 실무에서는 이를 어떻게 해결하는지 혹은, 만드는 Validator마다 알아서 맨 첫 시작은 bindingResult.hasErrors()를 알아서 호출하게 할만한 방법이 어떤 방법이 있을까요?
답변이 길어질 것 같으면 그냥 Spring에 어떤 기능을 잘활용하면 된다고 짤막하게 남겨주셔도 감사할 것 같습니다.
주저리주저리..
원래는 도전정신으로 Validator를 설계할 때 위에 @Controller처럼 어노테이션을 @Validator를 붙이고 앞서 배운 핸들러와 매핑처럼 들어온 파라미터 타입에 맞는 핸들러를 알아서 찾아서 쓰는 입장에선 validator.validate와 같이 깔끔하게 쓰자고 호기롭게 공부를 시작했지만 생각보다 벽느껴서 나중에 잘하게 되면 다시 도전해보려합니다. ㅠㅠ
Answer 2
2
0
안녕하세요.
말씀하신 부분에 대해서 고민을 조금 해보았습니다.
if 문의 논리연산자( &&, || )의 처리를 잘 활용한다면 조금더 매끄러운 코드를 작성할 수 있습니다.
본격적인 코드에 앞서 먼저 설명드리고 진행하도록 하겠습니다.
1) If 문의 논리연산자 처리
static boolean true_test( ){
system.out.println("ture_test");
retrun true;
}
static boolean false_test(){
system.out.println("false_test");
return false;
}
우선 위와 같은 함수 2개가 존재하고 if 문에서 논리연산자로 조건 검사를 하는 경우를 생각해보겠습니다.
if ( test_true( ) && test_false( ) ) ; // test_true, test_false 모두 실행됩니다.
// &&의 경우 앞이 참인 경우 뒤가 참인지 거짓인지 확인해야 하므로 모두 실행됩니다.
if( test_false( ) && test_true( ) ) ; // test_false 만 실행됩니다.
// && 연산자 앞의 결과가 false인 경우 뒤의 항목을 굳이 실행할 필요가 없기에 뒤의 항목은 실행되지 않습니다.
if( test_true( ) || test_false( ) ) ; // test_true 만 실행됩니다.
// || (OR) 연산자 앞의 결과가 true 인 경우 뒤의 항목을 굳이 실행할 필요가 없기에 뒤의 항목은 실행되지 않습니다.
if( test_false( ) || test_true( ) ) ; // test_false, test_true 모두 실행됩니다.
// && 연산자 앞의 결과가 false인 경우 뒤의 항목이 참인지 거짓인지 확인해야 하므로 모두 실행됩니다.
이와 같은 사실을 활용한다면 아래와 같은 코드로 작성하는 것이 가능합니다.
2) 수정된 코드
// 함수 수정
public boolean validateLogin(form, bindingResult){
(....)
return bindingResult.hasErrors();
}
// if문 수정
if ( bindingResult.hasErrors() || loginValidator.validateLogin(form, bindingResult) ) {
return "login";
}
// 1) 타입 검증에 문제가 생긴 경우 :
// bindingReulst.hasErrors() 가 true가 됩니다.
// 따라서 뒤의 validateLogin() 은 실행되지 않습니다.
// 2) 논리 검증에 문제가 생긴 경우 :
// validateLogin()에서 true 를 반환하기 때문에 if 문 안의 문장이 실행되게 됩니다.
이렇게 작성한다면 validate 추가 검증 함수를 만들 때
return 타입을 boolean 으로 하고 return bindingResult.hasErrors() 를 추가로 작성해야 합니다만,
if 문 한 번으로 보다 코드를 깔끔하게 작성할 수 있습니다.
감사합니다.
이것도 깔끔한 코드네요! 답변 감사합니다.
혹시나 컨트롤러마다 중복되는
이 부분을 상속이나 다른 무언가를 통해서 이를 상속받은 검증기는 반드시 이 문장을 실행한다던지 하는 방법같은,, 이 코드를 아예 내부로 숨겨버릴 수는 없는거겠죠?