본문 바로가기

Spring

검증2 - Validation : Bean Validation

인프런 김영한 님의 스프링mvc2편을 보고 정리한 글입니다.

무엇을 배웠나요?

BeanValidation - 소개

  • 검증 로직을 모든 프로젝트에 적용할 수 있게 공통화하고, 표준화 한 것이 바로 BeanValidation
  • 검증 애노테이션 정의 및 사용법
    • @NotBlank : 빈값 + 공백만 있는 경우를 허용하지 않는다.
    • @NotNull : null 을 허용하지 않는다.
    • @Range(min = 1000, max = 1000000) : 범위 안의 값이어야 한다.
    • @Max(9999) : 최대 9999까지만 허용한다.
    @Data
    public class Item {
     private Long id;
     @NotBlank
     private String itemName;
     @NotNull
     @Range(min = 1000, max = 1000000)
     private Integer price;
     @NotNull
     @Max(9999)
    private Integer quantity;
     public Item() {
     }
     public Item(String itemName, Integer price, Integer quantity) {
     this.itemName = itemName;
     this.price = price;
     this.quantity = quantity;
     }
    }
    
  • 그러나 BeanValidation으로만은 특정 필드를 넘어서는 객체 오류의 검증을 하기 어렵다.
    • 객체 오류의 경우 자바 코드로 직접 검증하는 것이 바람직
  • 검증순서는 다음과 같다
    1. 성공하면 다음으로
    2. 실패하면 typeMismatch 로 FieldError 추가
    3. Validator 적용
    <aside> 🎙️ 바인딩에 성공한 필드만 BeanValidation을 적용하기 때문에 모델객체에 정상적으로 값이 들어와야만 바인딩이 의미가 있다. 예를 들어 typeMismatch오류의 경우는 객체에 값이 들어오지 않기때문에 검증을 하지 못한다.
  • </aside>
  • @ModelAttribute 각각의 필드에 타입 변환 시도

Bean Validation - 에러 코드

  • 만약 BeanValidation이 기본으로 제공하는 오류메시지 이외에 좀 더 자세히 변경하고 싶으면 다errors.properties에 추가 하면 된다. 
  • #Bean Validation 추가 NotBlank={0} 공백X Range={0}, {2} ~ {1} 허용 Max={0}, 최대 {1}
  • @NotBlank NotBlank.item.itemName NotBlank.itemName NotBlank.java.lang.String NotBlank @Range Range.item.price Range.price Range.java.lang.Integer Range
  • BeanValidation 메시지 찾는 순서는 다음과 같다.
    1. 생성된 메시지 코드 순서대로 messageSource 에서 메시지 찾기
    2. 애노테이션의 message속성 사용 @NotBlank(message = "공백! {0}")
    3. . 라이브러리가 제공하는 기본 값 사용 공백일 수 없습니다.

Bean Validation - 오브젝트 오류

  • 만약 객체오류를 @BeanValidation으로 처리하고 싶으면 @ScriptAssert를 사용하면 된다.
  • → 그러나 실무에서는 사용하기 까다로워 자바 코드로 검증을 하는 것이 바람직하다

BeanValidation - 한계

  • 만약 동일한 필드에 대해서 해당 필드를 저장할때와 수정할때의 검증이 서로 다르면 BeanValidation만으로는 부족하다
  • ➕ 만약 프론트단에서 특정 필드의 값이 항상 들어가있고 수정이 불가능하도록 되어 있어도 서버단에서는 이를 꼭 검증해야 하는데 그 이유로는 프론트단에서 원래라면 수정이 불가능하였던 필드라도 악의적으로(예를 들면 postman 같은 방식으로) 필드 값을 지우고 폼을 전송하는 문제가 발생할수도 있기에 꼭 서버단에서 검증을 해주어야 한다.
  • 이러한 한계점을 극복하기 위한 방법으로 두가지가 있다.
    1. BeanValidation의 groups를 사용하는 방법
    2. 폼전송을 위한 별도의 모델 객체를 만들어 사용한다.

BeanValidation - groups

  • 사용방법은 다음과 같다.
    1. groups 생성
      package hello.itemservice.domain.item;
      	public interface UpdateCheck {
      }
      
    2. package hello.itemservice.domain.item; public interface SaveCheck { }
    3. groups 적용
    4. @Data public class Item { @NotNull(groups = UpdateCheck.class) //수정시에만 적용 private Long id; @NotBlank(groups = {SaveCheck.class, UpdateCheck.class}) private String itemName; . . .
  • groups 기능을 사용해서 등록과 수정시에 각각 다르게 검증을 할 수 있다.
  • 그러나 전반적으로 복잡도가 올라가기 떄문에 실무에서는 groups를 사용하기 보다는 등록용 폼 객체와 수정용 폼 객체를 분리해서 사용한다.