๐Ÿ“Œ ์Šคํ”„๋ง Validation ๊ธฐ์ดˆ - 3ํŽธ: @Valid์™€ BindingResult๋กœ ์ž…๋ ฅ๊ฐ’ ๊ฒ€์ฆํ•˜๊ธฐ

My Pale Blue Dotยท2025๋…„ 4์›” 23์ผ
0

SPRING

๋ชฉ๋ก ๋ณด๊ธฐ
4/36
post-thumbnail

๐Ÿ“… 2025-04-23

๐Ÿ“ ํ•™์Šต ๋‚ด์šฉ

1๏ธโƒฃย Validation์ด๋ž€? ์™œ ํ•„์š”ํ•œ๊ฐ€?

  • Validation(๊ฒ€์ฆ)์€ ํด๋ผ์ด์–ธํŠธ๋กœ๋ถ€ํ„ฐ ์ „๋‹ฌ๋ฐ›์€ ๋ฐ์ดํ„ฐ๊ฐ€ ์œ ํšจํ•œ์ง€ ํ™•์ธํ•˜๋Š” ๊ณผ์ •์ž…๋‹ˆ๋‹ค.

๋‹จ์ˆœํ•œ ์ž…๋ ฅ ์ฒดํฌ๋ฅผ ๋„˜์–ด, ์„œ๋น„์Šค์˜ ๋ฐ์ดํ„ฐ ๋ฌด๊ฒฐ์„ฑ๊ณผ ๋ณด์•ˆ์„ ์ง€ํ‚ค๊ธฐ ์œ„ํ•œ ์ฒซ ๋ฒˆ์งธ ๋ฐฉ์–ด์„ ์ž…๋‹ˆ๋‹ค.

๐Ÿ’ก ์˜ˆ์‹œ

  • ํšŒ์›๊ฐ€์ž… ์‹œ ํ•„์ˆ˜ ํ•ญ๋ชฉ ๋ˆ„๋ฝ ๋ฐฉ์ง€
  • ๋น„๋ฐ€๋ฒˆํ˜ธ ์ตœ์†Œ ๊ธธ์ด ์ œํ•œ
  • ์ˆซ์ž ๋ฒ”์œ„ ๊ฒ€์ฆ
  • ์•…์˜์  ์ž…๋ ฅ(Injection) ์‚ฌ์ „ ์ฐจ๋‹จ

2๏ธโƒฃย ์Šคํ”„๋ง Validation ๋ฐฉ์‹

  • ์Šคํ”„๋ง์€ JSR-380(Bean Validation 2.0) ํ‘œ์ค€ ๊ธฐ๋ฐ˜.
  • ๋Œ€ํ‘œ ๊ตฌํ˜„์ฒด: Hibernate Validator
  • DTO์— ์–ด๋…ธํ…Œ์ด์…˜๋งŒ ์ถ”๊ฐ€ํ•˜๋ฉด ์ž๋™์œผ๋กœ ๊ฒ€์ฆ ๊ฐ€๋Šฅ.

3๏ธโƒฃย ํ™˜๊ฒฝ ์„ค์ • (Maven ์˜์กด์„ฑ ์ถ”๊ฐ€)

<!-- Validation API -->
<dependency>
    <groupId>jakarta.validation</groupId>
    <artifactId>jakarta.validation-api</artifactId>
    <version>3.0.2</version>
</dependency>

<!-- Hibernate Validator -->
<dependency>
    <groupId>org.hibernate.validator</groupId>
    <artifactId>hibernate-validator</artifactId>
    <version>7.0.1.Final</version>
</dependency>

<!-- Expression Language (ํ•„์š”์‹œ) -->
<dependency>
    <groupId>org.glassfish</groupId>
    <artifactId>jakarta.el</artifactId>
    <version>3.0.3</version>
</dependency>

โœ…ย Note

์Šคํ”„๋ง ๋ถ€ํŠธ๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค๋ฉด hibernate-validator๊ฐ€ ๊ธฐ๋ณธ ํฌํ•จ๋˜์–ด ์žˆ์–ด ๋ณ„๋„ ์„ค์ •์ด ํ•„์š” ์—†๋‹ค.


4๏ธโƒฃย @Valid vs @Validated

์–ด๋…ธํ…Œ์ด์…˜ํŠน์ง•์‚ฌ์šฉ์ฒ˜
@ValidJSR-380 ํ‘œ์ค€, ๋‹จ์ผ ๊ฒ€์ฆ์ผ๋ฐ˜์ ์ธ ๊ฒ€์ฆ
@Validated์Šคํ”„๋ง ์ „์šฉ, ๊ทธ๋ฃน ๊ฒ€์ฆ ์ง€์›๋ณต์žกํ•œ ๊ฒ€์ฆ ๋กœ์ง ํ•„์š” ์‹œ

5๏ธโƒฃย DTO ํด๋ž˜์Šค์— ๊ฒ€์ฆ ์–ด๋…ธํ…Œ์ด์…˜ ์ ์šฉ

import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;

public class PersonDto {
    @NotNull(message = "์ด๋ฆ„์€ ํ•„์ˆ˜ ์ž…๋ ฅ๊ฐ’์ž…๋‹ˆ๋‹ค.")
    private String name;

    @NotNull(message = "๋‚˜์ด๋ฅผ ์ž…๋ ฅํ•ด ์ฃผ์„ธ์š”.")
    private Integer age;

    @Size(min = 2, max = 20, message = "์ฃผ์†Œ๋Š” 2์ž ์ด์ƒ 20์ž ์ดํ•˜๋กœ ์ž…๋ ฅํ•˜์„ธ์š”.")
    private String addr;

    // Getter, Setter, ์ƒ์„ฑ์ž ์ƒ๋žต
}

6๏ธโƒฃย ์ปจํŠธ๋กค๋Ÿฌ์—์„œ ๊ฒ€์ฆ ์ฒ˜๋ฆฌ

@PostMapping("/validate")
public String validateTest(@Valid PersonDto dto, BindingResult result, Model model) {
    if (result.hasErrors()) {
        // ๊ฒ€์ฆ ์‹คํŒจ ์‹œ ์—๋Ÿฌ ๋ชฉ๋ก ์ „๋‹ฌ
        model.addAttribute("errors", result.getAllErrors());
        return "param/errorPage";
    }
    // ๊ฒ€์ฆ ์„ฑ๊ณต ์‹œ
    return "param/successPage";
}

๐Ÿ’กย BindingResult๋Š” ๋ฐ˜๋“œ์‹œ @Valid ๋ฐ”๋กœ ๋’ค์— ์œ„์น˜ํ•ด์•ผ ๊ฒ€์ฆ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ›์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค!


7๏ธโƒฃ

์—๋Ÿฌ ๋ฉ”์‹œ์ง€ ์ปค์Šคํ„ฐ๋งˆ์ด์ง•

  • resources/messages.properties ํŒŒ์ผ ์ƒ์„ฑ
NotNull.personDto.name=์ด๋ฆ„์„ ์ž…๋ ฅํ•ด ์ฃผ์„ธ์š”.
Size.personDto.addr=์ฃผ์†Œ๋Š” {min}์ž ์ด์ƒ {max}์ž ์ดํ•˜๋กœ ์ž…๋ ฅํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๐Ÿ’กย TIP ์Šคํ”„๋ง ์„ค์ •์—์„œ ๋ฉ”์‹œ์ง€ ์†Œ์Šค๋ฅผ ๋“ฑ๋กํ•˜๋ฉด ๋‹ค๊ตญ์–ด ์ฒ˜๋ฆฌ๋„ ๊ฐ€๋Šฅ!


๐Ÿ”ฅ ์š”์•ฝ

  • Validation์€ ์„œ๋น„์Šค์˜ ์•ˆ์ „๋ง!
  • @Valid + BindingResult ์กฐํ•ฉ์œผ๋กœ ์œ ์—ฐํ•œ ๊ฒ€์ฆ ์ฒ˜๋ฆฌ.
  • ๋ณต์žกํ•œ ๊ฒ€์ฆ์ด ํ•„์š”ํ•˜๋‹ค๋ฉด @Validated + ๊ทธ๋ฃน ๊ธฐ๋Šฅ ํ™œ์šฉ.
  • ์‚ฌ์šฉ์ž ์นœํ™”์ ์ธ ์—๋Ÿฌ ๋ฉ”์‹œ์ง€ ์ œ๊ณต์€ ๊ธฐ๋ณธ.
  • ์‹ค๋ฌด์—์„œ๋Š” ์ปค์Šคํ…€ Validator๋„ ์ ๊ทน ํ™œ์šฉ ํ•„์š”.

๐Ÿ”— ์ฐธ๊ณ  ์ž๋ฃŒ


๋А๋‚€ ์ 

์ด๋ฒˆ ํ•™์Šต์„ ํ†ตํ•ด ์ž…๋ ฅ๊ฐ’ ๊ฒ€์ฆ์ด ๋‹จ์ˆœํ•œ ์˜ต์…˜์ด ์•„๋‹ˆ๋ผ ํ•„์ˆ˜๋ผ๋Š” ๊ฑธ ๋‹ค์‹œ ๋А๊ผˆ๋‹ค.

ํŠนํžˆ BindingResult๋ฅผ ํ™œ์šฉํ•˜๋ฉด ๋””๋ฒ„๊น…๊ณผ ์‚ฌ์šฉ์ž ํ”ผ๋“œ๋ฐฑ ์ฒ˜๋ฆฌ๊ฐ€ ํ›จ์”ฌ ์ˆ˜์›”ํ•ด์ง„๋‹ค.

์•ž์œผ๋กœ๋Š” ๊ฒ€์ฆ ๋กœ์ง์„ ํ‘œ์ค€ํ™”ํ•˜์—ฌ, ์„œ๋น„์Šค ์•ˆ์ •์„ฑ์„ ๋†’์ด๋Š” ๋ฐ ์ง‘์ค‘ํ•  ๊ณ„ํš์ด๋‹ค.

profile
Here, My Pale Blue.๐ŸŒ

0๊ฐœ์˜ ๋Œ“๊ธ€