๊ฒ์ฆ ๊ธฐ๋ฅ์ ๋งค๋ฒ ์ฝ๋๋ก ์์ฑํ๋ ๊ฒ์ ๋ฒ๊ฑฐ๋กญ๊ธฐ ๋๋ฌธ์ ์ ๋ ธํ ์ด์ ์ ์ฐ์.
Bean Validation: ๊ฒ์ฆ ๋ก์ง์ ๋ชจ๋ ํ๋ก์ ํธ์ ์ ์ฉํ ์ ์๋๋ก ๊ณตํตํํ๊ณ ํ์คํ ํ ๊ฒ
๊ตฌํ์ฒด๊ฐ ์๋๋ผ Bean Validation 2.0(JSR-380)์ด๋ผ๋ ๊ธฐ์ ํ์ค์ด๋ค.
์ฆ, ๊ฒ์ฆ ์ ๋
ธํ
์ด์
๊ณผ ์ฌ๋ฌ ์ธํฐํ์ด์ค ๋ชจ์
Bean Validation์ ์ธํฐํ์ด์ค๋ง ์ ๊ณตํ๊ณ ๊ตฌํ์ฒด๋ ๋ฐ๊ฟ๋ผ์ธ ์ ์์.
jakarta.validation-api
: Bean Validation ์ธํฐํ์ด์ค
hibernate-validator
: ๊ตฌํ์ฒด
๐ ๊ฒ์ฆ ์ ๋
ธํ
์ด์
@NotBlank
: ๋น๊ฐ + ๊ณต๋ฐฑ๋ง ์๋ ๊ฒฝ์ฐ๋ฅผ ํ์ฉ X
@NotNull
: null ํ์ฉ X
@Range(min = 1000, max = 1000000)
: ๋ฒ์ ์์ ๊ฐ์ด์ด์ผ ํจ
@Max(9999)
: ์ต๋ ๊ดํธ ์ ๊ฐ๊น์ง ํ์ฉ(์ฌ๊ธฐ์ 9999)
๐
javax.validation .constraints.NotNull
org.hibernate.validator .constraints.Rangejavax.validation ๋ก ์์ํ๋ฉด ํน์ ๊ตฌํ์ ๊ด๊ณ์์ด ์ ๊ณต๋๋ ํ์ค ์ธํฐํ์ด์ค
org.hibernate.validator ๋ก ์์ํ๋ฉด ํ์ด๋ฒ๋ค์ดํธ validator ๊ตฌํ์ฒด๋ฅผ ์ฌ์ฉํ ๋๋ง ์ ๊ณต๋๋ ๊ฒ์ฆ ๊ธฐ๋ฅ
(์ค๋ฌด์์ ๋๋ถ๋ถ ํ์ด๋ฒ๋ค์ดํธ validator๋ฅผ ์ฌ์ฉํ๋ฏ๋ก ์์ ๋กญ๊ฒ ์ฌ์ฉํด๋ ๋จ)
๐ ๋จ์ถํค
command + R
: ์ํ๋ ๋จ์ด๋ก ๋ณ๊ฒฝ(์ผ๊ด ๋ณ๊ฒฝ ๊ฐ๋ฅ)
command + shift + R
: ๋๋ ํ ๋ฆฌ ๋จ์๋ก ์ํ๋ ๋จ์ด๋ก ๋ณ๊ฒฝ(์ผ๊ด ๋ณ๊ฒฝ ๊ฐ๋ฅ)
spring-boot-starter-validation ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ๋ฃ์ผ๋ฉด ์๋์ผ๋ก Bean Validator๋ฅผ ์ธ์งํ๊ณ ์คํ๋ง์ ํตํฉ๋จ.
์คํ๋ง ๋ถํธ๋ ์๋์ผ๋ก ๊ธ๋ก๋ฒ Validator๋ก ๋ฑ๋กํ๋ค.
๊ทธ๋์ Validator๊ฐ @NotNull
๊ฐ์ ์ ๋
ธํ
์ด์
์ ๋ณด๊ณ ๊ฒ์ฆ์ ์ํํ๋ค.
๋ฌผ๋ก , @Valid
์ @Validated
๋ ์ ์ฉํด์ผ ํ๋ค.
๊ฒ์ฆ ์ค๋ฅ๊ฐ ๋ฐ์ํ๋ฉด FieldError, ObjectError๋ฅผ ์์ฑํด BindingResult์ ๋ด์์ค๋ค.
@ModelAttribute
๊ฐ๊ฐ์ ํ๋์ ํ์
๋ณํ ์๋๋ฐ์ธ๋ฉ์ ์ฑ๊ณตํ ํ๋๋ง Bean Validator๊ฐ ์ ์ฉ๋๋ค.
ํ์
๋ณํ์ ์ฑ๊ณตํด ๋ฐ์ธ๋ฉ์ ์ฑ๊ณตํ ํ๋์ฌ์ผ Bean Validator ์ ์ฉ์ด ์๋ฏธ์๋ค.
์ฆ, @ModelAttribute
โ ๊ฐ๊ฐ์ ํ๋ ํ์
๋ณํ ์๋ โ ๋ณํ์ ์ฑ๊ณตํ ํ๋๋ง BeanValidator ์ ์ฉ
Ex. itemName์ A๋ฅผ ๋ฃ์์ ๋ ํ์ ๋ณํ์ด ์ฑ๊ณตํ์ง๋ง price์ ์ซ์ ๋์ A๋ฅผ ๋ฃ์ผ๋ฉด ํ์ ๋ณํ์ ์คํจ
๐ @NotBlank
NotBlank.item.itemName
NotBlank.itemName
NotBlank.java.lang.String
NotBlank
๐ @Range
Range.item.price
Range.price
Range.java.lang.Integer
Range
์ด ์์๋๋ก ์๋ฌ ๋ฉ์์ง ์ฝ๋ ์์ฑ
BeanValidation ๋ฉ์์ง ์ฐพ๋ ์์
1. ์์ฑ๋ ๋ฉ์์ง ์ฝ๋ ์์๋๋ก messageSource์์ ๋ฉ์์ง ์ฐพ๊ธฐ
2. ์ ๋
ธํ
์ด์
message ์์ฑ ์ฌ์ฉ
3. ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ์ ๊ณตํ๋ ๊ธฐ๋ณธ ๊ฐ ์ ๊ณต (๊ณต๋ฐฑ์ผ ์ ์์ต๋๋ค. ๊ฐ์)
@ScriptAssert()
: BeanValidation์์ ํน์ ํ๋ fieldError๊ฐ ์๋ ํด๋น ์ค๋ธ์ ํธ ๊ด๋ จ ์ค๋ฅ objectError ์ฒ๋ฆฌ
ํ์ง๋ง ๊ธฐ๋ฅ์ด ๋๋ฌด ์ฝํด(ํด๋น ๊ฐ์ฒด์ ๋ฒ์๋ฅผ ๋์ด์๋ ๊ฒฝ์ฐ๊ฐ ์ฆ์) ๊ถ์ฅํ์ง ์์.
๊ทธ๋ฅ ์ค๋ธ์ ํธ ์ค๋ฅ ๊ด๋ จ ๋ถ๋ถ๋ง ์ง์ ์๋ฐ ์ฝ๋๋ก ์์ฑํ์.
๋ชฉํ: ์ํ ์์ ์๋ BeanValidation ์ ์ฉํ๊ธฐ
edit()
์ Item ๊ฐ์ฒด ๋ชจ๋ธ์ @Validated
๋ฅผ ์ถ๊ฐํ๊ณ editForm์ผ๋ก ์ด๋ํ๋ ์ฝ๋ ์ถ๊ฐ
ํ์ฌ ์์ ์ item์ id ๊ฐ์ ํญ์ ๋ค์ด์๋๋ก ๋ก์ง์ด ๊ตฌ์ฑ๋์ด ์์ด ๊ฒ์ฆํ์ง ์์๋ ๋๋ค๊ณ ์๊ฐํ์ง๋ง HTTP ์์ฒญ์ ์ธ์ ๋ ์ ์์ ์ผ๋ก ๋ณ๊ฒฝํด ์์ฒญํ ์ ์์ผ๋ฏ๋ก ์๋ฒ์์ ํญ์ ๊ฒ์ฆํด์ผ ํ๋ค.
์๋ฅผ ๋ค์ด HTTP ์์ฒญ์ ๋ณ๊ฒฝํด item์ id ๊ฐ์ ์ญ์ ํ๊ณ ์์ฒญํ ์ ์๋ค. ๋ฐ๋ผ์ ์ต์ข ๊ฒ์ฆ์ ์๋ฒ์์ ์งํํ๋ ๊ฒ์ด ์์ !
์๊ตฌ์ฌํญ์ ์กฐ๊ธ ์์ ํ๋๋ฐ ์์ ์์๋ ์๋์ ๋ฌด์ ํ์ผ๋ก, id๊ฐ์ ํ์๋ก ๋๋๋ก ํ๋ค. ๊ทธ ๊ฒฐ๊ณผ ๋ฑ๋ก์ด ์๋๋ค. ๋ฑ๋ก์์๋ id์ ๊ฐ๋ ์๊ณ quantity ์๋ ์ ํ ์ต๋ ๊ฐ์ธ 9999๋ ์ ์ฉ๋์ง ์์๋ค.
ํ๊ณ: item์ ๋ฑ๋ก๊ณผ ์์ ์์ ๊ฒ์ฆ ์กฐ๊ฑด์ ์ถฉ๋์ด ๋ฐ์ํ๊ณ , ๋ฑ๋ก๊ณผ ์์ ์ ๊ฐ์ BeanValidation์ ์ ์ฉํ ์ ์๋ค.
๋ฑ๋ก๊ณผ ์์ ์ ๊ฐ์ด ๊ฒ์ฆํ๋๊น ํ๊ณ๊ฐ ์์๋ค. ๊ทธ๋์ ๋ค๋ฅด๊ฒ ๊ฒ์ฆํ๋ ๋ฐฉ๋ฒ์ ์์๋ณด์.
BeanValidation groups
: ๋ฑ๋ก์ ๊ฒ์ฆํ ๊ธฐ๋ฅ๊ณผ ์์ ์ ๊ฒ์ฆํ ๊ธฐ๋ฅ์ ๊ฐ ๊ทธ๋ฃน์ผ๋ก ๋๋ ์ ์ฉ
๐ groups๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํด์๋ @Valid
๋์ @Validated
๋ฅผ ์ฌ์ฉํด์ผ ํจ.
๊ทธ๋ฆฌ๊ณ ์ฌ์ค groups ๊ธฐ๋ฅ์ ์ค๋ฌด์์ ์ ์ฌ์ฉํ์ง ์์. (๋ณต์ก๋๊ฐ ๋์. ์ค๋ฌด์์๋ ๋ฑ๋ก์ฉ ํผ ๊ฐ์ฒด์ ์์ ์ฉ ํผ ๊ฐ์ฒด๋ฅผ ๋ถ๋ฆฌํด ์ฌ์ฉํด๋ฒ๋ฆผ.)
์ฌํ ํด์๋ ๊ฒ์ฒ๋ผ ํ์ผ์ ๋ณต์ฌํ๊ณ ๋ฒ์ ์ผ๊ด์ ์ผ๋ก ๋ณ๊ฒฝํด์ฃผ๊ธฐ
์ ์ค๋ฌด์์ Bean Validation groups๋ฅผ ์ ์ฌ์ฉํ์ง ์๋๋ฉด ๋ฑ๋ก์ ํผ์์ ์ ๋ฌํ๋ ๋ฐ์ดํฐ๊ฐ Item ๋๋ฉ์ธ ๊ฐ์ฒด์ ๋ฑ ๋ง์๋จ์ด์ง์ง ์๊ธฐ ๋๋ฌธ์ด๋ค.
์ค์ ์ค๋ฌด์์๋ ํ์ ๋ฑ๋ก์ ํ์ ๋ฐ์ดํฐ๋ง ์ ๋ฌ๋ฐ๋ ๊ฒ์ด ์๋๋ผ ์ฝ๊ด ๋ฑ ์ถ๊ฐ๋ก ๋ฐ๋ ์ฌํญ์ด ๋ง๋ค.
๊ทธ๋์ Item์ ์ง์ ์ ๋ฌ๋ฐ๊ธฐ ๋ณด๋ค๋, ๋ณต์กํ ํผ์ ๋ฐ์ดํฐ๋ฅผ ์ปจํธ๋กค๋ฌ๊น์ง ์ ๋ฌํ ๋ณ๋์ ๊ฐ์ฒด๋ฅผ ๋ง๋ค์ด ์ ๋ฌํ๋ค.
์ฅ์ : Item ๋๋ฉ์ธ ๊ฐ์ฒด๋ฅผ ์ปจํธ๋กค๋ฌ, ๋ ํ์งํ ๋ฆฌ๊น์ง ์ง์ ์ ๋ฌํด ์ค๊ฐ Item์ ๋ง๋๋ ๊ณผ์ ์ด ์์ด ๊ฐ๋จ
๋จ์ : ๊ฐ๋จํ ๊ฒฝ์ฐ์๋ง ์ ์ฉ ๊ฐ๋ฅ. ์์ ์ ๊ฒ์ฆ์ด ์ค๋ณต๋ ์ ์๊ณ groups๋ฅผ ์ฌ์ฉํด์ผ ํจ.
์ฅ์ : ์ ์กํ๋ ํผ๋ฐ์ดํฐ๊ฐ ๋ณต์กํด๋ ๋ณ๋์ ํผ ๊ฐ์ฒด๋ฅผ ์ฌ์ฉํด ๋ฐ์ดํฐ๋ฅผ ์ ๋ฌ ๋ฐ์ ์ ์์. ๋ฑ๋ก/์์ ๋ณ๋์ ํผ ๊ฐ์ฒด๋ฅผ ๋ง๋ค๊ธฐ ๋๋ฌธ์ ๊ฒ์ฆ์ด ์ค๋ณต๋์ง ์์
๋จ์ : ํผ ๋ฐ์ดํฐ๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ์ปจํธ๋กค๋ฌ์์ Item ๊ฐ์ฒด๋ฅผ ์์ฑํ๋ ๋ณํ ๊ณผ์ ์ด ์ถ๊ฐ(๊ฒฐ๊ตญ ์ฝ๋ ๋์ด๋จ)
์์ ์ ๊ฒฝ์ฐ ๋ฑ๋ก๊ณผ ์์ ํ ๋ค๋ฅธ ๋ฐ์ดํฐ๊ฐ ์ ๋ฌ๋๋ค. ๋ฑ๋ก์ ํ์ ์์ด๋์ ์ฃผ๋ฏผ ๋ฒํธ๋ฅผ ์ ๋ ฅ๋ฐ์ง๋ง ์์ ์ ์ด๋ ์์ ํ ํ์๊ฐ ์๋ค.
๊ทธ๋์ (์ด ์์ ์ ๊ฒฝ์ฐ) ItemUpdateForm์ด๋ผ๋ ๋ณ๋์ ๊ฐ์ฒด๋ก ๋ฐ์ดํฐ๋ฅผ ์ ๋ฌ ๋ฐ์๋ค.
์์์ ๋งํ๋ฏ Item ๋์ ItemSaveForm
์ ์ ๋ฌ๋ฐ์ @Validated
๋ก ๊ฒ์ฆ์ ์ํํ๊ณ BindingResult
๋ก ๊ฒ์ฆ ๊ฒฐ๊ณผ๋ ๋ฐ๋๋ค.
๊ทธ๋ฆฌ๊ณ ์ฐธ๊ณ ๋ก
@ModelAttribute("item")
์ item ์ด๋ฆ์ ๋ฃ์ด์ค ๊ฒ์ ItemSaveForm์ ๊ฒฝ์ฐ ๊ท์น์ ์ํด ์ด ์ด๋ฆ์ผ๋ก MVC Model์ ๋ด๊ธฐ๊ธฐ ๋๋ฌธ์ ๋ทฐ ํ ํ๋ฆฟ์์ ์ ๊ทผํ๋ th:object์ด๋ฆ์ ๋ณ๊ฒฝํ์ง ์์ผ๋ ค๊ณ ๋ฃ์ด์ฃผ์๋ค.
HttpMessageConverter์๋ @Valid
, @Validated
๋ฅผ ์ ์ฉํ ์ ์๋ค.
๐
@ModelAttribute
: HTTP ์์ฒญ ํ๋ผ๋ฏธํฐ(URL ์ฟผ๋ฆฌ ์คํธ๋ง, POST Form)๋ฅผ ๋ค๋ฃฐ ๋ ์ฌ์ฉ
@RequestBody
: HTTP ๋ฐ๋์ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ฒด๋ก ๋ณํํ ๋ ์ฌ์ฉ. ์ฃผ๋ก API JSON ์์ฒญ์ ๋ค๋ฃฐ ๋ ์ฌ์ฉ
API์ ๊ฒฝ์ฐ 3๊ฐ์ง ๊ฒฝ์ฐ๋ฅผ ์๊ฐํด๋ด์ผ ํจ
1. ์ฑ๊ณต ์์ฒญ: ์ฑ๊ณต
2. ์คํจ ์์ฒญ: JSON์ ๊ฐ์ฒด๋ก ์์ฑํ๋ ๊ฒ ์์ฒด๋ฅผ ์คํจ
3. ๊ฒ์ฆ ์ค๋ฅ ์์ฒญ: JSON์ ๊ฐ์ฒด๋ก ์์ฑํ๋ ๊ฒ์ ์ฑ๊ณตํ์ผ๋ ๊ฒ์ฆ์์ ์คํจ
์ด๋ HttpMessageConverter์์ ์์ฒญ JSON์ Item ๊ฐ์ฒด๋ก ์์ฑํ๋ ๊ฒ์ ์คํจํ ์ํฉ์ด๋ค. ๊ทธ๋์ ์ปจํธ๋กค๋ฌ ์์ฒด๊ฐ ํธ์ถ๋์ง ์์๋ค.
๊ฐ์ฒด๋ฅผ JSON์ผ๋ก ๋ณํํด ํด๋ผ์ด์ธํธ์ ์ ๋ฌํ๊ณ ObjectError์ FieldError๊ฐ ๋ฐํ๋๋ค.
@ModelAttribute
vs @RequestBody
HTTP ์์ฒญ ํ๋ผ๋ฏธํฐ๋ฅผ ์ฒ๋ฆฌํ๋ @ModelAttribute
๋ ๊ฐ๊ฐ์ ํ๋ ๋จ์๋ก ์ธ๋ฐํ๊ฒ ์ ์ฉ๋๋ค.
ํน์ ํ๋์ ํ์
์ด ๋ง์ง ์๋ ์ค๋ฅ๊ฐ ๋ฐ์ํด๋ ๋๋จธ์ง ํ๋๋ ์ ์ ์ฒ๋ฆฌ
HttpMessageConverter๋ @ModelAttribute
์ ๋ค๋ฅด๊ฒ ์ ์ฒด ๊ฐ์ฒด ๋จ์๋ก ์ ์ฉ๋๋ค.
๋ฐ๋ผ์ ๋ฉ์์ง ์ปจ๋ฒํฐ ์๋์ ์ฑ๊ณตํ์ฌ Item ๊ฐ์ฒด๋ฅผ ๋ง๋ค์ด์ผ @Valid
, @Validated
๊ฐ ์ ์ฉ๋๋ค.
@ModelAttribute
: ํ๋ ๋จ์๋ก ์ ๊ตํ๊ฒ ๋ฐ์ธ๋ฉ ์ ์ฉ. ํน์ ํ๋๊ฐ ๋ฐ์ธ๋ฉ ๋์ง ์์๋ ๋๋จธ์ง ํ๋๋ ์ ์ ๋ฐ์ธ๋ฉ. Validator๋ฅผ ์ฌ์ฉํ ๊ฒ์ฆ๋ ์ ์ฉ ๊ฐ๋ฅ.
@RequestBody
: HttpMessageConverter ๋จ๊ณ์์ JSON ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ฒด๋ก ๋ณ๊ฒฝํ์ง ๋ชปํ๋ฉด ์ดํ ๋จ๊ณ๋ ๋ฌด์ฉ์ง๋ฌผ(์งํ X). ์ปจํธ๋กค๋ฌ ํธ์ถ X. Validator ์ ์ฉ X.