13. Bean Validation
์ ๋ ฅ๊ฐ์ด ๊ณต๋์ด๋ฉด ์๋๊ฑฐ๋ ์ ๋ ฅํ ์ ์๋ ์ซ์์ ๋ฒ์๊ฐ ์ ํ๋์ด ์๋ ๋ฑ, ๊ฒ์ฆ์ด ํ์ํ ํญ๋ชฉ์ ์ฌ์ค ์ด๋ ์๋น์ค๋ ๋น์ทํ ๊ฒ์ด๋ค. ๊ทธ๋ ๊ธฐ ๋๋ฌธ์ ์คํ๋ง์ ๊ธฐ๋ณธ์ ์ธ ๊ฒ์ฆ ํญ๋ชฉ๋ค์ ์ด๋ ธํ ์ด์ ์ผ๋ก ์ ๊ณตํ๊ณ ์๋ค. ์ด๊ฒ์ ํ์ฉํ ๊ฒ์ฆ ๋ฐฉ์์ Bean Validation ์ด๋ผ๊ณ ํ๋ค.
1๏ธโฃ ย Bean Validation - FieldError
- Item ๊ฐ์ฒด์ ๋ค์๊ณผ ๊ฐ์ด @ ์ด๋ ธํ ์ด์ ์ ์ถ๊ฐํ๋ค.
- ๊ฒ์ฆ ๋ก์ง์ ์ํํ @ModelAttribute ์์ @Validated ์ด๋ ธํ ์ด์ ์ ์ถ๊ฐํ๋ค.
public class Item {
private Long id;
@NotBlank //๊ณต๋ฐฑ, ๋์ด์ฐ๊ธฐ๋ฅผ ํ์ฉํ์ง ์์.
private String itemName;
@NotNull //null์ ํ์ฉํ์ง ์์.
@Range(min = 1000, max = 1000000) //์
๋ ฅ ๊ฐ๋ฅํ ์ซ์ ๋ฒ์๋ฅผ ์ง์ .
private Integer price;
@NotNull
@Max(value = 9999) //์
๋ ฅ ๊ฐ๋ฅํ ์ต๋๊ฐ์ ์ง์ .
Integer quantity;
}
@PostMapping("/add")
public String addItemV6(@Validated @ModelAttribute Item item, BindingResult bindingResult, RedirectAttributes redirectAttributes, Model model) {
(...)
}
2๏ธโฃ ย errors.properties
- Bean Validation ์ผ๋ก ์ถ๋ ฅ๋๋ ์๋ฌ ๋ฉ์์ง๋ฅผ ์ข ๋ ์์ธํ ์์ฑํ๊ณ ์ถ๋ค๋ฉด properties ํ์ผ์ ๋ฉ์์ง๋ฅผ ๋ฑ๋กํ๋ฉด ๋๋ค.
#Bean Validation ์๋ฌ ๋ฉ์์ง ์ถ๊ฐ
NotBlank={0} ๊ณต๋ฐฑX
Range={0}, {2} ~ {1} ํ์ฉ
Max={0}, ์ต๋ {1}
3๏ธโฃ ย Bean Validation - ObjectError
- ํน์ ํ๋(FieldError) ๊ฐ ์๋ ์ค๋ธ์ ํธ ๊ด๋ จ ์ค๋ฅ(ObjectError) ๋ฅผ ์ฒ๋ฆฌํ๋ ค๋ฉด @ScriptAssert() ์ด๋ ธํ ์ด์ ์ ์ฌ์ฉํ๋ฉด ๋๋ค.
@ScriptAssert(lang = "javascript", script = "_this.price * _this.quantity >= 10000", message = "์ดํฉ๊ณ๋ 10,000์ ์ด์์ด์ด์ผ ํฉ๋๋ค.")
public class Item {
(...)
}
- ๊ทธ๋ ์ง๋ง ์ค์ ์ฌ์ฉํด๋ณด๋ฉด ์ ์ฝ์ด ๋ง๊ณ ๋ณต์กํ๊ธฐ์, ObjectError์ ๊ฒฝ์ฐ ์๋ฐ ์ฝ๋๋ก ์์ฑํ๋ ๊ฒ์ ๊ถ์ฅํ๋ค.
4๏ธโฃ ย groups
- Bean Validation์ ์ด๋ ๊ฒ ํธ๋ฆฌํ ๊ธฐ๋ฅ์ ์ ๊ณตํด์ฃผ์ง๋ง ๋ฑ๋ก ํผ๊ณผ ์์ ํผ์์์ ๊ฒ์ฆ ์๊ตฌ์ฌํญ์ด ๋ค๋ฅธ ๊ฒฝ์ฐ ์ ์ฉํ๊ธฐ ํ๋ค์ด์ง๋ค.
- ์ด ๊ฒฝ์ฐ ๋ฐฉ๋ฒ์ ๋ ๊ฐ์ง์ธ๋ฐ, ์ฒซ๋ฒ์งธ๋ก groups ๊ธฐ๋ฅ์ ํ์ฉํ ์ ์๋ค.
- ๊ฐ์ฒด์ ์ ์ฉํ Bean Validation ์ด๋ ธํ ์ด์ ์ ํด๋น ๊ฒ์ฆ์ฌํญ์ ์ ์ฉํ ํด๋์ค๋ค์ ์ ์ด๋ฃ์ด ๊ทธ๋ฃนํํ๋ค.
- ์ปจํธ๋กค๋ฌ์ @Validated ์ด๋ ธํ ์ด์ ์ ์ด๋ค ๊ทธ๋ฃน์ ๊ฒ์ฆ ํญ๋ชฉ์ ์ ์ฉํ ๊ฒ์ธ์ง๋ฅผ ์ ์ด๋ฃ๋๋ค.
public class Item {
@NotNull(groups = UpdateCheck.class)
private Long id;
@NotBlank(groups = {SaveCheck.class, UpdateCheck.class})
private String itemName;
@NotNull(groups = {SaveCheck.class, UpdateCheck.class})
@Range(min = 1000, max = 1000000, groups = {SaveCheck.class, UpdateCheck.class})
private Integer price;
@NotNull(groups = {SaveCheck.class, UpdateCheck.class})
@Max(value = 9999, groups = {SaveCheck.class})
private Integer quantity;
}
@PostMapping("/add")
public String addItemV6(@Validated(SaveCheck.class) @ModelAttribute Item item, BindingResult bindingResult, RedirectAttributes redirectAttributes, Model model) {
(...)
}
5๏ธโฃ ย ํผ ๊ฐ์ฒด ์์ฑ
- ์ groups ๋ฐฉ์์ ์ฌ์ฉํ๋ฉด ์ฝ๋์ ๋ณต์ก๋๊ฐ ์ฆ๊ฐํ๋ค.
- ๊ฒ์ฆ ํญ๋ชฉ์ ๋ถ๋ฆฌํด์ผ ํ๋ ์ด์ ๋ ๋ฑ๋ก ํผ๊ณผ ์์ ํผ์์ ์ ์กํ๋ ํ๋๊ฐ ๋ค๋ฅด๊ธฐ ๋๋ฌธ์ด๋ค.
- ์ด ๊ฒฝ์ฐ ๋ฑ๋ก, ์์ ํผ์์ ๋ฐ์ดํฐ๋ฅผ ์ ๋ฌ๋ฐ์ ๊ฐ์ฒด๋ฅผ ๋ฐ๋ก ์์ฑํด์ @ModelAttribute ์ ๋ด์ ํ ๊ฒ์ฆ์ ์ํํ ์ดํ Item ๊ฐ์ฒด์ ๋ฐ์ดํฐ๋ฅผ ์ธํ ํ๋ฉด ๊ฐ๋จํด์ง๋ค.
public class ItemSaveForm {
@NotBlank
private String itemName;
@NotNull
@Range(min = 1000, max = 1000000)
private Integer price;
@NotNull
@Max(value = 9999)
private Integer quantity;
}
public class ItemUpdateForm {
@NotNull
private Long id;
@NotBlank
private String itemName;
@NotNull
@Range(min = 1000, max = 1000000)
private Integer price;
//[์์ ] ์์ ์๋์ ์์ ๋กญ๊ฒ ๋ณ๊ฒฝํ ์ ์๋ค.
private Integer quantity;
}
/* ์ปจํธ๋กค๋ฌ */
public String edit(@PathVariable Long itemId, @Validated @ModelAttribute("item") ItemUpdateForm form, BindingResult bindingResult) {
}