오봉이와 함께하는 개발 블로그
스프링 MVC 2 - BindingResult 본문
BindingResult 1
스프링이 제공하는 검증 오류 처리 방법을 알아보자.
여기서 핵심은 BindingResult이다. 우선 코드로 확인해보자.
ValidationItemControllerV2 - addItemV1
@PostMapping("/add")
public String addItemV1(@ModelAttribute Item item, BindingResult bindingResult, RedirectAttributes redirectAttributes, Model model) {
// 검증 오류 결과 보관
Map<String, String> errors = new HashMap<>();
// 검증 로직
if(!StringUtils.hasText(item.getItemName())) {
bindingResult.addError(new FieldError("item", "itemName", "상품 이름은 필수입니다."));
}
if(item.getPrice() == null || item.getPrice() < 1000 || item.getPrice() > 1000000) {
bindingResult.addError(new FieldError("item", "price", "가격은 1,000 ~ 1,000,000 까지 허용합니다."));
}
if(item.getQuantity() == null || item.getQuantity() > 9999) {
bindingResult.addError(new FieldError("item", "quantity", "수량은 최대 9,999개 까지 허용합니다."));
}
// 특정 필드가 아닌 복합 룰 검증
if(item.getPrice() != null && item.getQuantity() != null) {
int resultPrice = item.getPrice() * item.getQuantity();
if(resultPrice < 10000) {
bindingResult.addError(new ObjectError("item", "가격 * 수량의 합은 10,000원 이상이어야 합니다. 현재 값 = " + resultPrice));
}
}
// 검증에 실패하면 다시 입력 폼으로
if (bindingResult.hasErrors()) {
log.info("errors = {}", bindingResult);
return "validation/v2/addForm";
}
// 검증 성공했을 때
Item savedItem = itemRepository.save(item);
redirectAttributes.addAttribute("itemId", savedItem.getId());
redirectAttributes.addAttribute("status", true);
return "redirect:/validation/v2/items/{itemId}";
}
주의BindingResult bindingResult
파라미터의 의치는 @ModelAttribute Item item
다음에 와야 한다.
필드 오류 - FieldError
if(!StringUtils.hasText(item.getItemName())) {
bindingResult.addError(new FieldError("item", "itemName", "상품 이름은 필수입니다."));
}
FieldError 생성자 요약public FieldError(String objectName, String field, String defaultMessage) {}
필드에 오류가 있으면 FieldError
객체를 생성해서 bindingResult
에 담아두면 된다.
- objectName : @ModelAttribute의 이름
- field : 오류가 발생한 필드 이름
- defaultMessage : 오류 기본 메시지
글로벌 오류 - ObjectErrorpublic ObjectError(String objectName, String defaultMessage) {}
특저 필드를 넘어서는 오류가 있으면 ObjectError
를 생성해서 bindingResult
에 담아두면 된다.
- objectName : @ModelAttribute의 이름
- defaultMessage : 오류 기본 메시지
오류 처리
// 검증에 실패하면 다시 입력 폼으로
if (bindingResult.hasErrors()) {
log.info("errors = {}", bindingResult);
return "validation/v2/addForm";
}
bindingResult.hasErrors()
를 통해 조건을 검사한다.
스프링에서 제공하는 BindingResult
를 사용하면 자동으로 뷰에 넘겨주기 때문에 전 코드와 달리 @ModelAttribute
가 필요하지 않다.
View - HTML
<div th:if="${#fields.hasGlobalErrors()}">
<p class="field-error" th:each="err : ${#fields.globalErrors()}" th:text="${err}">전체 메시지</p>
</div>
<div>
<label for="itemName" th:text="#{label.item.itemName}">상품명</label>
<input type="text" id="itemName" th:field="*{itemName}" class="form-control" th:errorclass="field-error" placeholder="이름을 입력하세요">
<div class="field-error" th:errors="*{itemName}">
상품명 오류
</div>
</div>
th:errorclass="field-error"
이 있을 때, th:field="*{itemName}"
에서 itemName
을 가진 오류가 있으면 class에 자동으로 추가해준다.
타임리프 스프링 검증 오류 통합 기능
타임리프는 스프링의 BindingResult
를 활용해서 편리하게 검증 오류를 표현하는 기능을 제공한다.#fields
: #fields
로 BindingResult
가 제공하는 검증 오류에 접근할 수 있다.th:errors
: 해당 필드에 오류가 있는 경우 태그에 출력한다. th:if
의 편의 버전.th:errorclass
: th:field
에서 지정한 필드에 오류가 있으면 class
정보를 추가한다.
BindingResult 2
- 스프링이 제공하는 검증 오류를 보관하는 객체
- 검증 오류가 발생하면 여기에 보관됨.
- BindingResult가 있으면 @ModelAttribute에 데이터 바인딩 시 오류가 발생해도 컨트롤러가 호출됨
- int나 Integer 타입을 지정한 변수에 문자열을 넣으면 서버에서는 400 에러를 보내서 오류 페이지로 넘어간다.
- 하지만 BindingResult가 있으면 오류 페이지로 넘기지 않고, 오류 정보를 담아서 컨트롤러를 호출하여 오류 정보를 전달한다.
BindingResult에 검증 오류를 적용하는 3가지 방법
- @ModelAttribute의 객체 타입 오류 등으로 바인딩이 실패하는 경우 스프링이 FieldError를 생성해서 BindingResult에 넣어준다.
- 개발자가 직접 넣어준다.
- Validator 사용
주의
- BindingResult는 검증할 대상 바로 다음에 와야한다.
- (@ModelAttribute Item item, BindingResult bindingresult) {...}
- BindingResult는 Model에 자동으로 포함된다.
BindingResult와 Errors
- org.springframework.validation.Errors
- org.springframework.validation.BindingResult
BindingResult
는 인터페이스고, Errors
인터페이스를 상속받고 있다.
실제 넘어오는 구현체는 BeanPropertyBindingResult
인데, 둘 다 구현하고 있으르모 BindingResult
대신 Errors
를 사용해도 된다.Errors
는 단순한 오류 저장과 조회 기능을 제공한다. BindingResult
는 여기에 추가적인 기능을 제공한다.
주로 관례상 BindingResult
를 사용하기 때문에 BindingResult
를 사용하도록 하자.
출처 : 인프런 김영한 지식공유자님 강의 스프링 MVC 2편 - 백엔드 웹 개발 활용 기술
'BE > Spring' 카테고리의 다른 글
스프링 MVC 2 - 오류 코드와 메시지 처리 part.1 (0) | 2022.08.23 |
---|---|
스프링 MVC 2 - FieldError, ObjectError (0) | 2022.08.23 |
스프링 MVC 2 - 검증 직접 처리 (0) | 2022.08.19 |
스프링 MVC 2 - 검증(Validation) 요구사항 (0) | 2022.08.18 |
스프링 MVC 2 - 스프링 메시지 소스 사용 (0) | 2022.08.18 |