Spring MVC/Validation

Validation 검증 - Bean Validation의 글로벌 Validation 오류

Hcode 2022. 12. 8.

 

이전 글로 Validation을 편하게 할 수 있는 Bean Validation에 대해 알아보았습니다.
 

Validation 검증 - Bean Validation과 Spring MVC

이전 글로 Bean Validation에 대해 간단히 알아보았습니다. Validation 검증 - Bean Validation 이란? 이전 글로 Validator를 사용하는 2가지 방법에 대해 알아보았습니다. Validation 검증 - Validator를 사용하는 2가

hhhhicode.tistory.com

이번 글로 글로벌 Validation 오류에 대해 알아보겠습니다.

 


 

Bean Validation의 글로벌 Validation 오류

  • 검증 순서
  • 글로벌 Validation 오류
  • 도메인 객체를 하나만 사용할 경우 문제점

에 대해 다룹니다.

 


 

검증 순서

바인딩 성공 예

대상 객체에 @ModelAttribute 적용

  → 각각의 필드 타입 변환, 바인딩 시도

    → 바인딩에 성공한 필드만 Bean Validation 적용

 

바인딩 실패 예

대상 객체에 @ModelAttribute 적용

  → 각각의 필드 타입 변환 X, 바인딩 X

    → TypeMismatch FieldError 생성

      → BindingResult에 FieldError 추가

        → 해당 Field는 Bean Validation 적용 X

 

Bean Validation → BindingResult → Front에서 BindingResult 사용

 


 

글로벌 Validation 오류

Bean Validation에서 특정 필드 오류(FieldError)가 아닌
  특정 필드를 넘어서는 오류(ObjectError)를 처리해 봅시다.

 

ObjectError를 처리하는 방법은 2가지가 있습니다.

  • @ScriptAssert()
  • 직접 자바 코드로 ObjectError 작성

 


 

@ScriptAssert()

실제로 사용해보면 제약이 많고 복잡합니다.

검증 기능이 해당 객체의 범위를 벗어나는 경우가 종종 발생하는데
  그런 경우 대응이 어렵습니다.

 

그래도 예를 보겠습니다.

@Data
@ScriptAssert(lang="javascript", script="_this.price*_this.quantity >= 10000")
public class Item {
    ...
}
해당 객체의 범위를 벗어난다는 것은 스크립트의 _this.price를 보면
  범위의 뜻을 잘 알 수 있습니다.

 

따라서 글로벌 오류인 ObjectError의 경우
  @ScriptAssert를 억지로 사용하는 것보다는
    ObjectError 관련 부분만 직접 자바 코드로 작성하는 것이 편합니다.

 


 

직접 자바 코드로 ObjectError 작성

ObjectError를 작성하기 위해 파라미터의 대상 객체 다음에 BindingResult 객체가 오게 합니다.

해당 Handler 안에 ObjectError를 작성해 줍니다.

@PostMapping("/{userId}/update")
public String profileUpdate(@PathVariable String userId, Model model,
                            @RequestParam(value = MemberConst.HOME_URI, defaultValue = "/") String homeUri,
                            @Validated @ModelAttribute MemberUpdateDto memberUpdateDto, BindingResult bindingResult,
                            RedirectAttributes redirectAttributes) {

    ...
        
    if (memberUpdateDto.getUserId().equals(memberUpdateDto.getPassword())) {
        bindingResult.reject("passwordEqualUserId", null, null);
    }
        
    ...
        
}

예시를 들기 위해 개인 프로젝트에서 코드를 가져왔습니다.

if 조건문으로 해당 유저의 아이디와 비밀번호가 같을 경우

  BindingResult에 ObjectError를 담고 있습니다.

 


 

도메인 객체를 하나만 사용할 경우 문제점

하나의 도메인 객체에 선언한 Validator를 가지고
  모든 페이지에서 공용으로 사용하고 있기 때문에
    각 페이지마다 Validation 요구 사항이 다를 시 문제가 발생합니다.

 

하나의 도메인 객체에 Validator가 선언되어 있습니다.

그 도메인 객체가 공통으로 사용되는 페이지들에서 Validator 또한 공통으로 사용됩니다.

그런데 그 페이지들의 모든 Validation 기준이 같지 않을 수 있습니다.

 

즉 여러 페이지에 걸쳐서

  같은 도메인 객체를 사용하기 때문에, 같은 Validator가 사용되고 있는데
    페이지별로 다른 Validation 기준을 가질 경우 문제가 생기는 것입니다.

 


 

문제점 예시

예를 들면
  등록 시에는 유저의 닉네임을 적지 않아도 되지만
    서비스에 입장하기 위해 닉네임이 필요하게 되었고

      그러기 위한 수정 시에는 유저의 닉네임을 무조건 입력해야 하는 경우입니다.

또 다른 예시로는

  등록 시에는 서버에서 사용하는 id에 값이 없어도 되지만

    수정 시에는 서버에서 사용하는 id 값이 필수인 것을 예시로 들 수 있겠습니다.

 

문제 해결에는 2가지 방법이 있습니다.

다음 글로는 문제 해결 2가지 방법에 대해 알아보겠습니다.


 

다음 글로 도메인 객체를 하나만 사용할 경우 발생하는 문제점을 해결하는 2가지 방법에 대해 알아보겠습니다.
 

Validation 검증 - 도메인 객체를 하나만 사용할 경우 문제점 해결

이전 글로 Bean Validation의 글로벌 Validation 오류에 대해서 알아보았습니다. Validation 검증 - Bean Validation의 글로벌 Validation 오류 이전 글로 Validation을 편하게 할 수 있는 Bean Validation에 대해 알아보았

hhhhicode.tistory.com

 

댓글