12. κ²μ¦ (Validation)
π€ μ¬μ©μκ° μΉνμ΄μ§μ μνμ λ±λ‘νκ³ μμ ν μ μλ <μν κ΄λ¦¬="" μμ€ν ="">μ κ°λ°νλ€κ³ κ°μ ν΄λ³΄μ. μ¬κΈ°μ λ€μν μꡬμ¬νμ΄ μκ²Όλ€.μν>
- νμ κ²μ¦
- κ°κ²©, μλμ λ¬Έμκ° λ€μ΄κ°λ©΄ κ²μ¦ μ€λ₯ μ²λ¦¬
- νλ κ²μ¦
- μνλͺ : νμ, 곡백 X
- κ°κ²© : 1,000μ μ΄μ ~ 1,000,000μ μ΄ν
- μλ : μ΅λ 9,999κ°κΉμ§ λ±λ‘ κ°λ₯
- νΉμ νλμ λ²μλ₯Ό λμ΄μλ κ²μ¦.
- κ°κ²© * μλ = 10,000μ μ΄μ
μ’μ μΉ μλΉμ€λ μ΄λ¬ν μ€λ₯κ° λ°μνλ©΄ μ€λ₯κ° λ°μν κ°μ μ μ§ν μνλ‘ μ΄λ€ μ€λ₯κ° λ°μνλμ§ μ¬μ©μμκ² μΉμ ν μλ €μ£Όμ΄μΌ νλ€.
μΆμ²: κΉμνμ μ€νλ§MVC (μΈνλ°)
μ, μ΄μ κ°λ°ν΄λ³΄μ ππ»ββοΈ
1οΈβ£ Β BindingResult
- μ€νλ§μ΄ μ 곡νλ κΈ°λ₯μ΄λ€.
- κ²μ¦ μ€λ₯λ₯Ό 보κ΄νλ κ°μ²΄λ‘, μ€λ₯κ° λ°μνλ©΄ μ€λ₯λ΄μ©μ μ μ₯ν΄μ€λ€.
- BindingResult κ° μμΌλ©΄ @ModelAttribute μ λ°μ΄ν° λ°μΈλ© μ μ€λ₯κ° μμ΄λ 컨νΈλ‘€λ¬λ₯Ό νΈμΆν΄μ€λ€.
- λ€λ§, @RequestBody λ‘ λ°μ΄ν° λ°μΈλ©μ νλ JSON λ°μ΄ν°μ κ²½μ° νμ μλ¬κ° λ°μνλ©΄ λͺ¨λΈ κ°μ²΄μ λ°μ΄ν°κ° λ΄κΈ°μ§ μκ³ , 컨νΈλ‘€λ¬λ₯Ό νΈμΆν μ μκ² λλ€. μ΄ κ²½μ°λ μμΈ μ²λ¦¬λ‘ μ€λ₯ λ©μμ§λ₯Ό μΆλ ₯ν΄μΌ νλλ° μ΄κ²μ λ€μ κ°μμμ μμΈν μμ보μ.
2οΈβ£ Β BindingResult - rejectValue(), reject() λ©μλ
- BindingResult λ rejectValue(), reject() λ©μλλ₯Ό μ 곡νλ€. νλλͺ κ³Ό μλ¬μ½λλ₯Ό νλΌλ―Έν°λ‘ λκΈ°λ©΄, κ·Έμ ν΄λΉνλ μ€λ₯ λ©μμ§λ₯Ό λΈλΌμ°μ μ μΆλ ₯ν μ μλ€.
- rejectValue() : FieldError λ₯Ό κ²μ¦νλ λ©μλ.
- reject() : ObjectError λ₯Ό κ²μ¦νλ λ©μλ.
/* κ²μ¦ λ‘μ§ μμ */
if (!StringUtils.hasText(item.getItemName())) {
//ItemName μ΄ κ³΅λ°±μ΄λΌλ©΄,
bindingResult.rejectValue("itemName", "required");
//itemName νλμ required μλ¬ μ½λλ₯Ό bindingResultμ λ΄λλ€.
}
//bindingResult μ μλ¬κ° λ΄κ²¨μλ€λ©΄,
if (bindingResult.hasErrors()) {
//μ¬μ©μκ° μ
λ ₯ν νΌμΌλ‘ λλλ €λ³΄λΈλ€.
return "validation/v2/addForm";
}
3οΈβ£ Β errors.properties
- μ€λ₯ λ©μμ§λ₯Ό ꡬλΆνκΈ° μ½κ² λ³λμ νμΌλ‘ κ΄λ¦¬νμ.
- μ€λ₯ μ½λλ₯Ό λ§λ€ λλ μμΈν λ§λ€ μ μκ³ , λ¨μνκ² λ§λ€ μλ μλ€.
#level1 - μμΈν λ§λ€κΈ° (μλ¬λͺ
.objectλͺ
.fieldλͺ
)
required.item.itemName=μν μ΄λ¦μ νμ μ
λλ€.
#level2 - λ¨μνκ² λ§λ€κΈ°
required=νμ κ° μ
λλ€.
- λ¨μνκ² λ§λ€λ©΄ λ²μ©μ±μ΄ μ’μμ μ¬κΈ°μ κΈ°μ μ¬μ©ν μ μμ§λ§ λ©μμ§λ₯Ό μΈλ°νκ² λ§λ€ μ μκ³ , λ°λλ‘ λ무 μμΈνκ² λ§λ€λ©΄ λ²μ©μ±μ΄ λ¨μ΄μ§λ€.
- μ€νλ§μ μΈλ°νκ² μμ±λ μλ¬ μ½λ(level1)λ₯Ό μ°μ μΌλ‘ μ μ©νκΈ° λλ¬Έμ μν©μ λ§κ² μμ±ν΄λλ©΄ λλ€.
4οΈβ£ Β κ²μ¦ μ€λ₯λ₯Ό μ μ©νλ 3κ°μ§ λ°©λ²
1. μ€νλ§μ΄ FieldError λ₯Ό μμ±ν΄μ BindingResult μ μ§μ λ£μ΄μ€λ€.
2. κ°λ°μκ° μ§μ λ£μ΄μ€λ€.
3. Validator λ₯Ό λΆλ¦¬νλ€.
κ²μ¦ μꡬμ¬ν μ€ <1λ². νμ κ²μ¦>μμ κ°κ²©, μλμ λ¬Έμμ΄μ λ£μΌλ©΄ @ModelAttribute λ₯Ό ν΅ν΄ Item κ°μ²΄μ λ°μ΄ν°κ° μ£Όμ λμ§ μλλ€. μ΄λ¬ν κ²½μ°λ typeMismatchλ‘ μ€νλ§μ΄ μλμΌλ‘ FieldError λ₯Ό μμ±ν΄μ€λ€.
κ²μ¦ μꡬμ¬ν μ€ <3λ². νΉμ νλμ λ²μλ₯Ό λμ΄μλ κ²μ¦> μ ObjectError μ ν΄λΉνλ κΈλ‘λ² μ€λ₯λ‘, κ°λ°μκ° μ§μ μλ° μ½λλ‘ μλ¬μν©μ μ μν μ΄ν μ§μ bindingResult μ μλ¬μ½λλ₯Ό λ΄λλ€.
/* κ°λ°μκ° μ§μ μ μνλ κ²μ¦ λ‘μ§ */
if (item.getPrice() != null && item.getQuantity() != null) {
int resultPrice = item.getPrice() * item.getQuantity();
if (resultPrice < 10000) {
bindingResult.reject("totalPriceMin", new Object[]{1000, resultPrice}, null);
}
}
- νμ§λ§ μ΄λ¬ν κ²μ¦ λ‘μ§μ΄ β컨νΈλ‘€λ¬βμ λ€μ΄κ° μλ κ²μ΄ λ¬Έμ κ° λ μ μλ€. 컨νΈλ‘€λ¬μ μν μ΄ μ»€μ§κ³ μ μ§λ³΄μμ±μ΄ λ¨μ΄μ§κΈ° λλ¬Έμ Validator λΌλ ν΄λμ€λ₯Ό λ³λλ‘ λ§λ€μ΄μ λ‘μ§μ λΆλ¦¬νλ κ²μ΄ μ’λ€.
public String addItemV5(@ModelAttribute Item item, BindingResult bindingResult, RedirectAttributes redirectAttributes, Model model) {
//κ²μ¦ λ‘μ§μ μν (νκ², BindingResult λ₯Ό νλΌλ―Έν°λ‘ λκΈ΄λ€)
itemValidator.validate(item, bindingResult);
//κ²μ¦μ μ€ν¨νλ©΄ λ€μ μ
λ ₯ νΌμΌλ‘
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}";
}