์Šคํ”„๋ง Bean Validation

Updated:     Updated:

Categories:

Tags: ,

๊ฒ€์ฆ๋กœ์ง์„ ๋งค๋ฒˆ ์ฝ”๋“œ๋กœ ์ž‘์„ฑํ•˜๋Š” ์ผ์€ ์ฒ˜๋ฆฌํ•ด์ฃผ์–ด์•ผ ํ•  ์ผ์ด ๋„ˆ๋ฌด ๋งŽ๋‹ค. ๊ฒ€์ฆ์˜ ๋Œ€๋ถ€๋ถ„์€ ํ•„๋“œ์˜ ๊ฐ’์— ๋Œ€ํ•œ ๊ฒ€์ฆ์ด๋‚˜ ๋นˆ ๊ฐ’์ธ์ง€, ์ดˆ๊ณผ์ธ์ง€, ๋ฏธ๋งŒ์ธ์ง€๋“ฑ์˜ ์ผ๋ฐ˜์ ์ธ ๋กœ์ง์ด๋‹ค. ์ด ๊ฒ€์ฆ๋“ค์„ ์Šคํ”„๋ง์„ ํ†ตํ•ด ์–ด๋…ธํ…Œ์ด์…˜ ๊ธฐ๋ฐ˜์œผ๋กœ ์‰ฝ๊ฒŒ ๊ฒ€์ฆํ•  ์ˆ˜ ์žˆ๋‹ค.


Bean Validation

Bean Validation์€ ํŠน์ •ํ•œ ๊ตฌํ˜„์ฒด๊ฐ€ ์•„๋‹ˆ๋ผ Bean Validation 2.0(JSR-380)์ด๋ผ๋Š” ๊ธฐ์ˆ  ํ‘œ์ค€์ด๋‹ค. ๊ตฌํ˜„์ฒด๋กœ๋Š” Hibernate์˜ Validator๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.

Validation์€ ๋ชจ๋“  application layer์—์„œ ์ ์šฉ๋œ๋‹ค. ์•„๋ž˜์˜ ๊ทธ๋ฆผ๊ณผ ๊ฐ™์€ ๋ฐฉ์‹์€ ์ค‘๋ณต๋˜๋Š” validation์ด ์žˆ์„ ์ˆ˜ ์žˆ๋‹ค.

์ถœ์ฒ˜ : https://docs.jboss.org/hibernate/validator/8.0/reference/en-US/html_single/#preface

๊ทธ๋ ‡๊ธฐ ๋•Œ๋ฌธ์— validation ๋กœ์ง์„ ๋„๋ฉ”์ธ ์˜์—ญ์— ๋ฌถ์–ด์„œ ํด๋ž˜์Šค์˜ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ๋ฅผ ํ‘œํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค.

๊ฒ€์ฆ ์• ๋…ธํ…Œ์ด์…˜

์• ๋…ธํ…Œ์ด์…˜ ๊ธฐ๋ฐ˜์˜ ๋ฐฉ์‹์„ ํ†ตํ•ด ๋ฐ”๋กœ ์ง๊ด€์ ์œผ๋กœ ์ดํ•ด๋˜๊ฒŒ ๊ฒ€์ฆ ๋กœ์ง์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค.

  • @NotBlank: ๋นˆ๊ฐ’ + ๊ณต๋ฐฑ์ธ ๊ฒฝ์šฐ ํ—ˆ์šฉํ•˜์ง€ ์•Š๋Š”๋‹ค.
  • @NotNull : null ์„ ํ—ˆ์šฉํ•˜์ง€ ์•Š๋Š”๋‹ค.
  • @Range(min = 1000, max = 1000000) : ๋ฒ”์œ„ ์•ˆ์˜ ๊ฐ’์ด์–ด์•ผ ํ•œ๋‹ค.
  • @Max(9999) : ์ตœ๋Œ€ 9999๊นŒ์ง€๋งŒ ํ—ˆ์šฉํ•œ๋‹ค.

@NotBlank
private String itemName;

@NotNull
@Range(min = 1000, max = 1000000)
private Integer price;

@NotNull
@Max(9999)
private Integer quantity;

๊ฒ€์ฆ๊ธฐ ๊บผ๋‚ด๊ธฐ

Validation ๊ตฌํ˜„์ฒด์—์„œ validator๋ฅผ ๊บผ๋‚ด์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. ์Šคํ”„๋ง์„ ์‚ฌ์šฉํ•˜๋ฉด ๋นˆ์„ ํ†ตํ•ด ๋“ฑ๋ก๋จ์œผ๋กœ ์•„๋ž˜์˜ ์ฝ”๋“œ๋ฅผ ์•ˆ์จ๋„ ๋œ๋‹ค.

ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
Validator validator = factory.getValidator();

Set<ConstraintViolation<Item>> violations = validator.validate(item); // ๊ฒ€์ฆ์— ๊ฑธ๋ฆฐ ๋กœ์ง๋“ค์ด ๋ฐ˜ํ™˜๋œ๋‹ค.
violation={interpolatedMessage='๊ณต๋ฐฑ์ผ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค', propertyPath=itemName, rootBeanClass=class hello.itemservice.domain.item.Item, messageTemplate='{javax.validation.constraints.NotBlank.message}'} violation.message=๊ณต๋ฐฑ์ผ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค

์Šคํ”„๋ง MVC ๊ฒ€์ฆ

์Šคํ”„๋ง ๋ถ€ํŠธ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ, spring-boot-starter-validation ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ๋„ฃ์œผ๋ฉด ์ž๋™์œผ๋กœ Bean Validator๋ฅผ ์Šคํ”„๋ง์— ํ†ตํ•ฉํ•œ๋‹ค.

์Šคํ”„๋ง ๋ถ€ํŠธ๋Š” LocalValidatorFactoryBean๋ฅผ ๊ธ€๋กœ๋ฒŒ Validator๋กœ ๋“ฑ๋กํ•˜๊ธฐ ๋•Œ๋ฌธ์—, ๊ฒ€์ฆ์„ ํ•˜๋ ค๋Š” ๊ณณ์— @Validated๋งŒ ์ž‘์„ฑํ•˜๋ฉด ๋œ๋‹ค. ๊ฒ€์ฆ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด FieldError, ObjectError๋ฅผ ์ƒ์„ฑํ•ด์„œ BindingResult์— ๋‹ด์•„์ค€๋‹ค.

Bean Validation ์—๋Ÿฌ ์ฝ”๋“œ

์Šคํ”„๋ง์€ ์˜ค๋ฅ˜ ์ฝ”๋“œ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ MessageCodesResolver ๋ฅผ ํ†ตํ•ด ๋‹ค์–‘ํ•œ ๋ฉ”์‹œ์ง€ ์ฝ”๋“œ๊ฐ€ ์ˆœ์„œ๋Œ€๋กœ ์ƒ์„ฑ๋œ๋‹ค.

@NotBlank

NotBlank.item.itemName NotBlank.itemName NotBlank.java.lang.String NotBlank

BeanValidation๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ˆœ์„œ๋กœ ๋ฉ”์‹œ์ง€๋ฅผ ์ฐพ๋Š”๋‹ค.

  1. ์ƒ์„ฑ๋œ ๋ฉ”์‹œ์ง€ ์ฝ”๋“œ ์ˆœ์„œ๋Œ€๋กœ messageSource ์—์„œ ๋ฉ”์‹œ์ง€๋ฅผ ์ฐพ๋Š”๋‹ค.
  2. ์• ๋…ธํ…Œ์ด์…˜์˜ message ์†์„ฑ ์‚ฌ์šฉ @NotBlank(message = โ€œ๊ณต๋ฐฑ! {0}โ€)
  3. ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ์ œ๊ณตํ•˜๋Š” ๊ธฐ๋ณธ ๊ฐ’ ์‚ฌ์šฉ

์ƒํ™ฉ๋ณ„ ๋„๋ฉ”์ธ ์ œ์•ฝ์กฐ๊ฑด์ด ๋‹ค๋ฅธ ๊ฒฝ์šฐ

๋ฐ์ดํ„ฐ๋ฅผ ๋“ฑ๋กํ•  ๋•Œ์™€ ์ˆ˜์ •ํ•  ๋•Œ ์ œ์•ฝ์กฐ๊ฑด์ด ๋‹ค๋ฅธ ๊ฒฝ์šฐ๋Š” ๋ณ„๋„์˜ ๋ชจ๋ธ ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค์–ด ์ƒํ™ฉ๋ณ„๋กœ validation์„ ๋‹ค๋ฅด๊ฒŒ ๋งŒ๋“ค์–ด ์ฃผ์–ด์•ผ ํ•œ๋‹ค.

ํผ ๋ฐ์ดํ„ฐ ์ „๋‹ฌ์„ ์œ„ํ•œ ๋ณ„๋„์˜ ๊ฐ์ฒด ์‚ฌ์šฉ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋ฐฉ๋ฒ•์œผ๋กœ ์ง„ํ–‰๋œ๋‹ค.

** HTML Form -> ํŠน์ • ํผ -> Controller -> ๋„๋ฉ”์ธ ์ƒ์„ฑ ๋ฐ ๋ฐ์ดํ„ฐ ์ถ”๊ฐ€ -> Repository **

ํŠน์ • ํผ์„ ๋งŒ๋“ค์–ด์•ผํ•˜๊ณ , ๊ฐ์ฒด ์ƒ์„ฑํ•˜๋Š” ๊ณผ์ •์ด ์žˆ๋‹ค. ์ „์†กํ•˜๋Š” ํผ ๋ฐ์ดํ„ฐ๊ฐ€ ๋ณต์žกํ•ด๋„ ๊ฑฐ๊ธฐ์— ๋งž์ถ˜ ๋ณ„๋„์˜ ํผ ๊ฐ์ฒด๋ฅผ ์‚ฌ์šฉํ•ด์„œ ๋ฐ์ดํ„ฐ๋ฅผ ์ „๋‹ฌ ๋ฐ›์„ ์ˆ˜ ์žˆ๋‹ค. ๋˜ํ•œ, ๋ณ„๋„์˜ ํผ ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค๊ธฐ ๋•Œ๋ฌธ์— ๊ฒ€์ฆ์ด ์ค‘๋ณต๋˜์ง€ ์•Š๋Š”๋‹ค.

HttpMessageConverter

@Validated๋Š” @RequestBody์—๋„ ์ ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

  • @ModelAttribute : HTTP์š”์ฒญ ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ๋‹ค๋ฃฐ ๋•Œ ์‚ฌ์šฉํ•œ๋‹ค. => URL query string, POST form
  • @RequestBody : HTTP Body ์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ์ฒด๋กœ ๋ณ€ํ™˜ํ•  ๋•Œ ์‚ฌ์šฉ

API ์š”์ฒญ์˜ ๊ฒฝ์šฐ 3๊ฐ€์ง€์˜ ๊ฒฝ์šฐ๊ฐ€ ์žˆ๋‹ค.

  1. ์„ฑ๊ณต : ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ›๋Š”๋ฐ๋„ ๋ฌธ์ œ๊ฐ€ ์—†์—ˆ๊ณ , ๊ฒ€์ฆ์—๋„ ๋ฌธ์ œ๊ฐ€ ์—†๋Š” ๊ฒฝ์šฐ
  2. ์‹คํŒจ : JSON ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ์ฒด๋กœ ๋งŒ๋“œ๋Š” ๊ณผ์ •์—์„œ ๋ฌธ์ œ๊ฐ€ ์ƒ๊ธฐ๋Š” ๊ฒฝ์šฐ
  3. ๊ฒ€์ฆ ์‹คํŒจ : ๊ฐ์ฒด๋Š” ๋งŒ๋“ค์—ˆ์ง€๋งŒ, ๊ฒ€์ฆ์— ์‹คํŒจํ•œ ๊ฒฝ์šฐ

@ModelAttribute๋Š” ํŠน์ • ํ•„๋“œ๊ฐ€ ๋ฐ”์ธ๋”ฉ ๋˜์ง€ ์•Š์•„๋„ ๋‚˜๋จธ์ง€ ํ•„๋“œ๋Š” ์ •์ƒ ๋ฐ”์ธ๋”ฉ ๋œ๋‹ค. @RequestBody๋Š” JSON ๋ฐ์ดํ„ฐ์—์„œ ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค์ง€ ๋ชปํ•˜๋ฉด ๊ฒ€์ฆ ๋‹จ๊ณ„์— ๋„๋‹ฌํ•˜์ง€ ๋ชปํ•œ๋‹ค.

spring ์นดํ…Œ๊ณ ๋ฆฌ ๋‚ด ๋‹ค๋ฅธ ๊ธ€ ๋ณด๋Ÿฌ๊ฐ€๊ธฐ

Leave a comment