Bean Validation의 정의
Bean Validation 2.0(JSR-380)이라는 기술 표준으로 검증 애노테이션과 여러 인터페이스의 모음입니다.
사전 작업
의존관계 추가
Bean Validation을 사용하기 위해선 우선 build.gradle
에서 의존관계를 추가해줘야합니다.
implementation 'org.springframework.boot:spring-boot-starter-validation'
다른 검증기 연결 코드 제거
다른 검증기 연결 코드가 있으면 Spring의 Bean Validation만 적용해주기 위해 다른 검증기 연결 코드는 삭제해야 합니다.
사용 예시
도메인에 적용
@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;
}
설명
@NotBlank, @NotNull, @Range, @Max 등등 여러가지의 Bean Validation이 있습니다.
호출 메서드
@PostMapping("/add")
public String addItem(
@Validated @ModelAttribute Item item,
BindingResult bindingResult,
...) {
...
}
Message 등록
// 상세
NotBlank.item.itemName=상품 이름은 필수입니다.
// 범용
NotBlank={0} 공백X
Range={0}, {2} ~ {1} 허용
Max={0}, 최대 {1}
인자값
{0}
은 필드명이고,{1}
,{2}
…은 각 애노테이션 마다 다릅니다.
오브젝트 에러 처리
FieldError가 아닌 ObjectError관련 오류는 오브젝트 오류 관련 부분만 직접 자바 코드로 작성하는 것을 권장합니다.
검증 로직 분리
Groups
같은 Model이어도 상황별로 검증 로직이 다를 때 사용할 수 있습니다.
예시) 상품 등록할 때는 수량을 9999까지만 넣을 수 있지만 수정할 때는 무제한으로 넣을 수 있는 경우
1. Interface 생성
package hello.itemservice.domain.item;
public interface SaveCheck { }
package hello.itemservice.domain.item;
public interface UpdateCheck { }
2. Groups 적용
@Data
public class Item {
...
@NotNull(groups = {SaveCheck.class, UpdateCheck.class}) // 등록 수정 둘 다 적용
@Max(value = 9999, groups = SaveCheck.class) // 등록시에만 적용
private Integer quantity;
3. Groups 로직 Controller에 적용
// 저장 로직에 추가 예시
@PostMapping("/add")
public String addItemV2(
@Validated(SaveCheck.class) @ModelAttribute Item item, // 인터페이스를 인자로 추가
BindingResult bindingResult, ...) {
...
}
객체 자체를 분리
Groups보다 더 범용적으로 쓰는 방법입니다. 데이터 객체 자체를 추가용, 수정용 등으로 따로 만듭니다.
1. 객체 각각 생성
// 추가용
@Data
public class ItemSaveForm {
@NotBlank
private String itemName;
@NotNull
@Range(min = 1000, max = 1000000)
private Integer price;
@NotNull
@Max(value = 9999)
private Integer quantity;
}
// 수정용
@Data
public class ItemUpdateForm {
@NotNull
private Long id;
@NotBlank
private String itemName;
@NotNull
@Range(min = 1000, max = 1000000)
private Integer price;
//수정에서는 수량은 자유롭게 변경할 수 있다.
private Integer quantity;
2. 분리 로직 Controller에 적용
// 저장 로직에 추가 예시
@PostMapping("/add")
public String addItemV2(
@Validated @ModelAttribute("item") ItemSaveForm item, // ItemSaveForm 타입
BindingResult bindingResult, ...) {
...
Item item = new Item();
item.setItemName(form.getItemName());
item.setPrice(form.getPrice());
item.setQuantity(form.getQuantity());
...
}
설명
분리해서 만든 데이터 모델 타입으로 item을 파라미터로 추가합니다. 코드 중간에 new Item();을 이용하여 기존의 Item타입으로 객체를 새로 만들어준 후 이용할 수 있습니다.
주의
@ModelAttribute("item")
에 item
이름을 넣어준 부분을 주의합시다.
이것을 넣지 않으면 ItemSaveForm
의 경우 규칙에 의해 itemSaveForm
이라는 이름으로 MVC Model에 담기게 됩니다.
이렇게 되면 뷰 템플릿에서 접근하 는 th:object
이름도 함께 변경해주어야 합니다.