μ΄λ² κΈμ ν΅ν΄ BindingResultλ₯Ό νμ©ν κ²μ¦(Validation)μ μμλ³΄κ³ μ νλ€.
κΈμ μμλ
- μλ²μμ κ²μ¦μ΄ νμν μ΄μ
μ μλ²μμ κ²μ¦μ μΆκ°μ μΌλ‘ ν΄μΌ νλκ°? - BindingResult
BindingResultλ₯Ό νμ©νμ¬ κ²μ¦μ μννλ λ°©λ² - μ¬μ©μμ μ
λ ₯ κ° μ μ§ λ°©λ²
λ°μΈλ©μ νμ§ λͺ»ν μν©μμλ μ¬μ©μμ μ λ ₯ κ°μ μ μ₯νλ λ°©λ²
μΌλ‘ μ§ννκ² λ€.
1. μλ²μμ κ²μ¦μ΄ νμν μ΄μ π§²
컨νΈλ‘€λ¬μ μ€μν μν μ€ νλλ HTTP μμ²μ΄ μ μμΈμ§ κ²μ¦νλ κ²μ΄λ€.
κ·Έλ¬λ ν΄λΌμ΄μΈνΈμμ κ²μ¦μ νκ³ μλ²μμλ κ²μ¦λ κ°μ κ·Έλ₯ μ°λ©΄ λλ κ±° μλκ°λΌκ³ μκ°ν μ μλ€. νμ§λ§ μλμ κ°μ μ΄μ λ‘ μΈν΄μ μλ²μμλ κ²μ¦μ μνν΄μΌ νλ€.
- ν΄λΌμ΄μΈνΈ κ²μ¦μ μ‘°μν μ μμΌλ―λ‘ λ³΄μμ μ·¨μ½νλ€
- μλ²λ§μΌλ‘ κ²μ¦νλ©΄, μ¦κ°μ μΈ κ³ κ° μ¬μ©μ±μ΄ λΆμ‘±ν΄μ§λ€.
- ν΄λΌμ΄μΈνΈ κ²μ¦κ³Ό μλ² κ²μ¦μ μμ΄μ μ¬μ©νλ, μ΅μ’ μ μΌλ‘ μλ² κ²μ¦μ νμμ΄λ€.
- API λ°©μμ μ¬μ©νλ©΄ API μ€νμ μ μ μν΄μ κ²μ¦ μ€λ₯λ‘ API μλ΅ κ²°κ³Όμ μ λ¨κ²¨μ€μΌ νλ€.
2. BindingResult π
π 1. κ°λ
μ€νλ§μ΄ μ 곡νλ κ²μ¦ μ€λ₯ μ²λ¦¬ λ°©λ²μ ν΅μ¬μ BindingResultμ΄λ€.
@PostMapping("/add")
public String addItem(@ModelAttribute Item item, BindingResult bindingResult) {
...
}
BindingResultλ μ€νλ§μ΄ μ 곡νλ κ²μ¦ μ€λ₯λ₯Ό 보κ΄νλ κ°μ²΄μ΄λ€. κ²μ¦ μ€λ₯κ° λ°μνλ©΄ BindingResultμ 보κ΄νλ©΄ λλ€. κ·Έλ¦¬κ³ BindingResultλ Modelμ μλμΌλ‘ ν¬ν¨λκΈ° λλ¬Έμ κ·Έ κ°μ μλ΅μ λ°λ μͺ½μμ μ¬μ©νλ©΄ λλ€.
μ£Όμν μ ν κ°μ§λ BindingResultμ μμΉλ νμ λ°μΈλ©λλ κ°μ²΄ λ€μ μμΌ νλ€λ κ²μ΄λ€.
π 2. μ¬μ©
BindingResultμ μ 무μ λ°λΌμ λ°μΈλ© μ νμ μ€λ₯κ° λ°μνμ λμ μ§νμ΄ λ¬λΌμ§λ€.
- BindingResultκ° μλ κ²½μ°
400 μ€λ₯κ° λ°μνλ©΄μ 컨νΈλ‘€λ¬κ° νΈμΆλμ§ μκ³ , μ€λ₯ νμ΄μ§λ‘ μ΄λνλ€. - BindingResultκ° μλ κ²½μ°
μ€λ₯ μ 보(FieldError)λ₯Ό BindingResultμ λ΄μμ 컨νΈλ‘€λ¬λ₯Ό μ μ νΈμΆνλ€.
BindingResultμ κ²μ¦ μ€λ₯λ₯Ό μ μ©νλ κ²μλ 3κ°μ§ λ°©λ²μ΄ μλ€.
- μμμ μ€λͺ ν κ²μ²λΌ λ°μΈλ© μμ²΄κ° μ€ν¨νλ κ²½μ°μλ μ€νλ§μ΄ FieldErrorλ₯Ό μμ±ν΄μ BindingResultμ λ£μ΄μ€λ€.
- Validatorλ₯Ό μ¬μ©νλ€. (λ€μμ λ€λ£° μ£Όμ μΈ Bean Validationμμ νμΈνμ.)
- κ°λ°μκ° μ§μ λ£μ΄μ€λ€.
bindingResult.addError(new FieldError("item", "itemName", "μν μ΄λ¦μ νμμ
λλ€."));
π 3. μ€μ μ μ©
μ§κΈκΉμ§μ λ΄μ©μ κ°μ§κ³ Item μμλ₯Ό μ΄μ©ν μ½λλ₯Ό νμΈν΄ 보μ. Item classκ° λ€μκ³Ό κ°μ΄ μ‘΄μ¬νκ³ , μλμ κ°μ μ€λ₯λ₯Ό νμΈν κ²μ΄λ€.
@Data
public class Item {
private Long id;
private String itemName;
private Integer price;
private Integer quantity;
}
- μμ΄ν μ΄λ¦(itemName)μ΄ μλ κ²½μ°
- κ°κ²©(itemPrice)μ λ²μκ° 1,000 ~ 1,000,000μ΄ μλ κ²½μ°
- κ°μ(quantity)κ° μ΅λ 9,999κ°κ° μλ κ²½μ°
- μ΅μ’ κ°(κ°κ²©(itemPrice) * κ°μ(quantity))μ΄ 10,000μ λ―Έλ§μΈ κ²½μ°
μ΄λ₯Ό κ²μ¦μ νμ©ν μ½λλ‘ νννλ©΄ μλμ κ°λ€.
@Slf4j
@Controller
@RequiredArgsConstructor
public class ValidationController {
private final ItemRepository itemRepository;
@PostMapping("/add")
public String addItem(@ModelAttribute Item item, BindingResult bindingResult, RedirectAttributes redirectAttributes) {
// 1. μμ΄ν
μ΄λ¦(itemName)μ΄ μλ κ²½μ°
if(!StringUtils.hasText(item.getItemName())){
bindingResult.addError(new FieldError("item", "itemName", "μν μ΄λ¦μ νμμ
λλ€."));
}
// 2. κ°κ²©(itemPrice)μ λ²μκ° 1,000 ~ 1,000,000μ΄ μλ κ²½μ°
if(item.getPrice() == null || item.getPrice() < 1000 | item.getPrice() > 1_000_000){
bindingResult.addError(new FieldError("item", "price", "κ°κ²©μ 1,000 ~ 1,000,000κΉμ§ νμ©ν©λλ€."));
}
// 3. κ°μ(quantity)κ° μ΅λ 9,999κ°κ° μλ κ²½μ°
if(item.getQuantity() == null || item.getQuantity() > 10_000) {
bindingResult.addError(new FieldError("item", "quantity", "μλμ μ΅λ 9,999κΉμ§ νμ©ν©λλ€."));
}
// νΉμ νλ μμΈκ° μλ μ 체 μμΈ
// 4. μ΅μ’
κ°(κ°κ²©(itemPrice) * κ°μ(quantity))μ΄ 10,000μ λ―Έλ§μΈ κ²½μ°
if(item.getPrice() != null && item.getQuantity() != null){
int resultPrice = item.getPrice() * item.getQuantity();
if(resultPrice < 10_000) {
bindingResult.addError(new ObjectError("item", "κ°κ²© * μλμ ν©μ 10,000μ μ΄μμ΄μ΄μΌ ν©λλ€. νμ¬ κ° = " + resultPrice));
}
}
if(bindingResult.hasErrors()){
return "item/addForm"; // λ€μ μν λ±λ‘νμ΄μ§λ‘ μ΄λ
}
Item savedItem = itemRepository.save(item);
redirectAttributes.addAttribute("itemId", savedItem.getId());
redirectAttributes.addAttribute("status", true);
return "redirect:/items/{itemId}";
}
}
3. μ€λ₯ λ°μ μ μ¬μ©μ μ λ ₯ κ° μ μ§ λ°©λ² π§°
λ°μΈλ©μ΄ λλ μμ μ μ€λ₯κ° λ°μνλ©΄ λͺ¨λΈ κ°μ²΄μ μ¬μ©μ μ λ ₯ κ°μ μ μ§νκΈ° μ΄λ ΅λ€λ λ¬Έμ κ° μλ€. μλ₯Ό λ€μ΄ Integer νμ μΈ priceμ λ¬Έμκ° λ€μ΄μ¨λ€λ©΄ κ°μ 보κ΄ν μ μκΈ° λλ¬Έμ΄λ€.
μ΄λ° κ²½μ° FieldErrorμ ObjectErrorμ μμ±μλ₯Ό μ΄μ©νμ¬ ν΄κ²°ν μ μλ€. κΈ°μ‘΄μ μ¬μ©ν μμ±μκ° μλ rejectedValueλ₯Ό μ¬μ©ν μ μλ μμ±μλ₯Ό μ¬μ©νμ¬ rejectedValueμ κ°μ μ μ₯νλ©΄ λλ€. μλλ FieldErrorμ ObjectErrorμ μμ±μλ₯Ό λνλΈ κ²μ΄λ€.
// rejectedValue X
public FieldError(String objectName,
String field,
String defaultMessage)
// rejectedValue O
public FieldError(String objectName,
String field,
@Nullable Object rejectedValue,
boolean bindingFailure,
@Nullable String[] codes,
@Nullable Object[] arguments,
@Nullable String defaultMessage)
// rejectedValue X
public ObjectError(String objectName,
@Nullable String defaultMessage)
// rejectedValue O
public ObjectError(String objectName,
@Nullable String[] codes,
@Nullable Object[] arguments,
@Nullable String defaultMessage)
κ°κ°μ νλΌλ―Έν°λ λ€μκ³Ό κ°μ μλ―Έλ₯Ό κ°μ§λ€.
- objectName
μ€λ₯κ° λ°μν κ°μ²΄ μ΄λ¦ - field
μ€λ₯ νλ - rejectedValue
μ¬μ©μκ° μ λ ₯ν κ°(κ±°μ λ κ°) - bindingFailure
νμ μ€λ₯ κ°μ λ°μΈλ© μ€ν¨μΈμ§, κ²μ¦ μ€ν¨μΈμ§ κ΅¬λΆ κ° - codes
λ©μμ§ μ½λ - arguments
λ©μμ§μμ μ¬μ©νλ μΈμ - defaultMessage
κΈ°λ³Έ μ€λ₯ λ©μμ§
rejectedValueλ₯Ό μ¬μ©νλ μμ±μλ₯Ό μ΄μ©νλ€λ©΄ μλμ κ°μ΄ μ½λλ₯Ό μμ±ν μ μλ€.
@Slf4j
@Controller
@RequiredArgsConstructor
public class ValidationController {
private final ItemRepository itemRepository;
@PostMapping("/add")
public String addItem(@ModelAttribute Item item, BindingResult bindingResult, RedirectAttributes redirectAttributes) {
// 1. μμ΄ν
μ΄λ¦(itemName)μ΄ μλ κ²½μ°
if(!StringUtils.hasText(item.getItemName())){
bindingResult.addError(
new FieldError("item",
"itemName",
item.getItemName(),
false,
null,
null,
"μν μ΄λ¦μ νμμ
λλ€."));
}
// 2. κ°κ²©(itemPrice)μ λ²μκ° 1,000 ~ 1,000,000μ΄ μλ κ²½μ°
if(item.getPrice() == null || item.getPrice() < 1000 | item.getPrice() > 1_000_000){
bindingResult.addError(new FieldError("item",
"price",
item.getPrice(),
false,
null,
null,
"κ°κ²©μ 1,000 ~ 1,000,000 κΉμ§ νμ©ν©λλ€."));
}
// 3. κ°μ(quantity)κ° μ΅λ 9,999κ°κ° μλ κ²½μ°
if(item.getQuantity() == null || item.getQuantity() > 10_000) {
bindingResult.addError(new FieldError("item",
"quantity",
item.getQuantity(),
false,
null,
null,
"μλμ μ΅λ 9,999 κΉμ§ νμ©ν©λλ€."));
}
// νΉμ νλ μμΈκ° μλ μ 체 μμΈ
// 4. μ΅μ’
κ°(κ°κ²©(itemPrice) * κ°μ(quantity))μ΄ 10,000μ λ―Έλ§μΈ κ²½μ°
if(item.getPrice() != null && item.getQuantity() != null){
int resultPrice = item.getPrice() * item.getQuantity();
if(resultPrice < 10_000) {
bindingResult.addError(new ObjectError("item",
null,
null,
"κ°κ²© * μλμ ν©μ 10,000μ μ΄μμ΄μ΄μΌ ν©λλ€.. νμ¬ κ° = " + resultPrice));
}
}
if(bindingResult.hasErrors()){
return "item/addForm"; // λ€μ μν λ±λ‘νμ΄μ§λ‘ μ΄λ
}
Item savedItem = itemRepository.save(item);
redirectAttributes.addAttribute("itemId", savedItem.getId());
redirectAttributes.addAttribute("status", true);
return "redirect:/items/{itemId}";
}
}
ν΄λΉ κΈμ κΉμν λμ 'μ€νλ§ MVC 2ν - λ°±μλ μΉ κ°λ° νμ© κΈ°μ 'μ μ°Έκ³ νμμ΅λλ€.
'π μ€νλ§ > κΈ°λ³Έ κ°λ ' μΉ΄ν κ³ λ¦¬μ λ€λ₯Έ κΈ
[Spring] κ²μ¦(Validation) - Validator (0) | 2023.05.02 |
---|---|
[Spring] κ²μ¦(Validation) - bindingResult.rejectValue(), binding.reject() (0) | 2023.05.02 |
μ€νλ§ μΈν°μ ν°(Spring Interceptor) (0) | 2023.04.30 |
μλΈλ¦Ώ νν°(Servlet Filter) (0) | 2023.04.29 |
λ©μμ§ & κ΅μ ν (Message & Internationalization) (0) | 2023.04.25 |