• ABOUT
  • POSTS
  • GUESTBOOK

ยฉ 2025 BlueCool12 All rights reserved.

2025.07.17Spring

๐Ÿ‘ท @Valid๋กœ ์‰ฝ๊ฒŒ ๊ตฌํ˜„ํ•˜๋Š” ์Šคํ”„๋ง ๋ถ€ํŠธ ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ

์Šคํ”„๋ง ๋ถ€ํŠธ์—์„œ๋Š” @Valid ์–ด๋…ธํ…Œ์ด์…˜์„ ํ†ตํ•ด ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ๋ฅผ ์‰ฝ๊ฒŒ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค. 

์œ ํšจ์„ฑ ๊ฒ€์‚ฌ๋ž€? 

์‚ฌ์šฉ์ž๊ฐ€ ์ž…๋ ฅํ•œ ๋ฐ์ดํ„ฐ๊ฐ€ ์˜ฌ๋ฐ”๋ฅด๊ณ  ๊ธฐ๋Œ€ํ•œ ํ˜•์‹์ด๋‚˜ ์กฐ๊ฑด์— ๋งž๋Š”์ง€ ํ™•์ธํ•˜๋Š” ๊ณผ์ •์„ ์˜๋ฏธํ•œ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ์ž˜๋ชป๋œ ๋ฐ์ดํ„ฐ๊ฐ€ ์‹œ์Šคํ…œ์— ๋“ค์–ด์˜ค๋Š” ๊ฒƒ์„ ์‚ฌ์ „์— ์ฐจ๋‹จํ•  ์ˆ˜ ์žˆ๋‹ค. 

์œ ํšจ์„ฑ ๊ฒ€์‚ฌ๋ฅผ ํ•˜์ง€ ์•Š์œผ๋ฉด ์˜ˆ์ƒ์น˜ ๋ชปํ•œ ์ž…๋ ฅ์œผ๋กœ ์ธํ•ด ํ”„๋กœ๊ทธ๋žจ์ด ๋น„์ •์ƒ ์ข…๋ฃŒ๋˜๊ฑฐ๋‚˜ ์ž˜๋ชป๋œ ๋ฐ์ดํ„ฐ๊ฐ€ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์ €์žฅ๋˜์–ด ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ ๋ณด์•ˆ ์œ„ํ—˜๋„ ์ฆ๊ฐ€ํ•œ๋‹ค. 

๋”ฐ๋ผ์„œ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์— ๋งž๋Š” ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ๋ฅผ ํ†ตํ•ด ์˜ฌ๋ฐ”๋ฅธ ๋ฐ์ดํ„ฐ๋งŒ ์ฒ˜๋ฆฌํ•˜๊ณ  ์ž˜๋ชป๋œ ์ž…๋ ฅ์— ๋Œ€ํ•ด์„œ๋Š” ์‚ฌ์šฉ์ž์—๊ฒŒ ์ ์ ˆํ•œ ํ”ผ๋“œ๋ฐฑ์„ ์ œ๊ณตํ•  ํ•„์š”๊ฐ€ ์žˆ๋‹ค. 
 

- Spring Boot ์™€ ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ


์Šคํ”„๋ง ๋ถ€ํŠธ์—์„œ๋Š” @Valid ์–ด๋…ธํ…Œ์ด์…˜์„ ์‚ฌ์šฉํ•ด ๊ฐ์ฒด์˜ ์œ ํšจ์„ฑ์„ ๊ฐ„๋‹จํžˆ ๊ฒ€์‚ฌํ•  ์ˆ˜ ์žˆ๋‹ค. ์–ด๋…ธํ…Œ์ด์…˜์„ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ๋จผ์ € Validation ๊ด€๋ จ ์˜์กด์„ฑ์„ ํ”„๋กœ์ ํŠธ์— ์ถ”๊ฐ€ํ•˜์—ฌ์•ผ ํ•œ๋‹ค.

java
// build.gradle
dependencies {
  implementation 'org.springframework.boot:spring-boot-starter-validation'
}

Jakarta Bean Validation API์™€ Hibernate Validator๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ๋‹ค.


์˜์กด์„ฑ์„ ์ถ”๊ฐ€ํ•œ ํ›„์—๋Š” DTO์— ์œ ํšจ์„ฑ ๊ฒ€์ฆ ์–ด๋…ธํ…Œ์ด์…˜์„ ๋ถ™์ธ๋‹ค.

java
public class PostCreateRequest {

  @NotBlank(message = "์ œ๋ชฉ์€ ํ•„์ˆ˜์ž…๋‹ˆ๋‹ค.")
  @Size(max = 255, message = "์ œ๋ชฉ์€ 255์ž ์ด๋‚ด์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค.")
  private String title;
  
  @NotBlank(message = "๋‚ด์šฉ์€ ํ•„์ˆ˜์ž…๋‹ˆ๋‹ค.")
  private String content;
  
  @NotNull(message = "์นดํ…Œ๊ณ ๋ฆฌ๋ฅผ ์„ ํƒํ•˜์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค.")
  private Long categoryId;
  
  @NotNull
  private Boolean isPublic;
  
}


๋Œ€ํ‘œ์ ์œผ๋กœ DTO์— ๋ถ™์ผ ์ˆ˜ ์žˆ๋Š” ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ ์–ด๋…ธํ…Œ์ด์…˜์œผ๋กœ๋Š” ์•„๋ž˜์™€ ๊ฐ™์€ ๊ฒƒ๋“ค์ด ์žˆ๋‹ค.

1. @NotNull - null ๊ฐ’์„ ํ—ˆ์šฉํ•˜์ง€ ์•Š๋Š”๋‹ค.

2. @NotBlank - null ๋ฐ ๋นˆ ๋ฌธ์ž์—ด(""), ๊ณต๋ฐฑ๋งŒ ์žˆ๋Š” ๋ฌธ์ž์—ด(" ")์„ ๋ชจ๋‘ ํ—ˆ์šฉํ•˜์ง€ ์•Š๋Š”๋‹ค.

3. @NotEmpty - null ๋ฐ ๋นˆ ๊ฐ’์„ ํ—ˆ์šฉํ•˜์ง€ ์•Š๋Š”๋‹ค. (๋ฌธ์ž์—ด, ๋ฐฐ์—ด, ๋ฆฌ์ŠคํŠธ, ๋งต ๋ชจ๋‘ ํฌํ•จ)

4. @Size - ๊ธธ์ด ๋˜๋Š” ํฌ๊ธฐ๋ฅผ ์ œํ•œํ•œ๋‹ค.

5. @Pattern - ์ •๊ทœ ํ‘œํ˜„์‹์„ ํ†ตํ•ด ๋ฌธ์ž์—ด ํŒจํ„ด์„ ๊ฒ€์ฆํ•œ๋‹ค.

6. @Min, @Max - ์ˆซ์ž ํƒ€์ž…์˜ ์ตœ์†Ÿ๊ฐ’, ์ตœ๋Œ“๊ฐ’์„ ์ง€์ •ํ•œ๋‹ค.

๊ฐ ํ•„๋“œ์˜ ํƒ€์ž…์— ๋”ฐ๋ผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์–ด๋…ธํ…Œ์ด์…˜๊ณผ ์˜ต์…˜๋“ค์ด ๋ชจ๋‘ ๋‹ค๋ฅด๊ธฐ ๋•Œ๋ฌธ์— ๋ฐ์ดํ„ฐ์˜ ํŠน์„ฑ๊ณผ ์š”๊ตฌ์‚ฌํ•ญ์— ๋”ฐ๋ผ ์ ์ ˆํ•˜๊ฒŒ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ค‘์š”ํ•˜๋‹ค.

DTO์— ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ ์–ด๋…ธํ…Œ์ด์…˜์„ ์„ค์ •ํ•œ ํ›„์—๋Š” ์‹ค์ œ๋กœ ์ด ๊ฒ€์‚ฌ๊ฐ€ ์ž‘๋™ํ•˜๋„๋ก ํ•˜๊ธฐ ์œ„ํ•ด ์ปจํŠธ๋กค๋Ÿฌ์—์„œ @Valid๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.

java
@PostMapping
public PostCreateResponse createPost(@Valid @RequestBody PostCreateRequest request) {
  // ...์ปจํŠธ๋กค๋Ÿฌ ๋กœ์ง
}

 



*์œ ํšจ์„ฑ ๊ฒ€์‚ฌ ์‹คํŒจ ์‹œ ์˜ˆ์™ธ ์ฒ˜๋ฆฌ

@Valid๋กœ ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ๋ฅผ ์ˆ˜ํ–‰ํ•  ๋•Œ ์ž…๋ ฅ ๊ฐ’์ด ์กฐ๊ฑด์„ ๋งŒ์กฑํ•˜์ง€ ๋ชปํ•˜๋ฉด ๋‘  ๊ฐ€์ง€ ์˜ˆ์™ธ ์ค‘ ํ•˜๋‚˜๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋‹ค.

@RequestBody๋กœ ์ „๋‹ฌ๋œ DTO์˜ ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ๊ฐ€ ์‹คํŒจํ–ˆ์„ ๋•Œ ๋ฐœ์ƒํ•˜๋Š” MethodArgumentNotValidException, @ModelAttribute ๋˜๋Š” @RequestParam ๋ฐฉ์‹์œผ๋กœ ์ „๋‹ฌ๋œ ๋ฐ์ดํ„ฐ๊ฐ€ ์œ ํšจ์„ฑ ์กฐ๊ฑด์„ ๋งŒ์กฑํ•˜์ง€ ๋ชปํ•  ๋•Œ ๋ฐœ์ƒํ•˜๋Š” BindException์ด ์žˆ๋‹ค.

์ด๋ฅผ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ์ปจํŠธ๋กค๋Ÿฌ์—์„œ @Valid ๋ฐ”๋กœ ๋’ค์— BindingResult๋ฅผ ํ•จ๊ป˜ ์„ ์–ธํ•˜์—ฌ ์˜ค๋ฅ˜ ์ •๋ณด๋ฅผ ์ˆ˜๋™์œผ๋กœ ์ฒ˜๋ฆฌํ•˜๊ฑฐ๋‚˜ @RestControllerAdvice๋ฅผ ์ด์šฉํ•ด ์ „์—ญ์—์„œ ๊ณตํ†ต์ ์œผ๋กœ ์˜ˆ์™ธ๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐฉ์‹์ด ์žˆ๋‹ค.
 

์ด์ „ ๊ธ€
๐Ÿ–ผ๏ธ ์›น ์„ฑ๋Šฅ์„ ์œ„ํ•œ ์ด๋ฏธ์ง€ ์••์ถ• ๋„๊ตฌ ์ •๋ฆฌ (TinyPNG & Squoosh)
๋‹ค์Œ ๊ธ€
๐ŸŒœ Next.js๋กœ ๋‹คํฌ๋ชจ๋“œ ๊ตฌํ˜„ํ•˜๊ธฐ (next-themes)
์žฅ์‹์šฉ ๋กœ๊ณ