• ABOUT
  • PORTFOLIO
  • POSTS
  • GUESTBOOK

ยฉ 2025-2026 BlueCool12 All rights reserved.

2025.07.17Spring

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

1. ์˜์กด์„ฑ ์ถ”๊ฐ€

Spring Boot 2.3 ๋ฒ„์ „ ์ดํ›„๋ถ€ํ„ฐ๋Š” ๋ถˆํ•„์š”ํ•œ ์˜์กด์„ฑ์„ ์ค„์ด๊ธฐ ์œ„ํ•ด ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ ๊ธฐ๋Šฅ์ด ๊ธฐ๋ณธ ์›น ์Šคํƒ€ํ„ฐ(spring-boot-starter-web)์—์„œ ๋ถ„๋ฆฌ๋˜์—ˆ๋‹ค. ๋”ฐ๋ผ์„œ @Valid ๊ธฐ๋ฐ˜์˜ Bean Validation์„ ์‚ฌ์šฉํ•˜๋ ค๋ฉด ๋ณ„๋„์˜ ์˜์กด์„ฑ์„ ์ถ”๊ฐ€ํ•ด์•ผ ํ•œ๋‹ค.

// build.gradle (Gradle)
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-validation'
}
// pom.xml (Maven)
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>

ํ•ด๋‹น ์Šคํƒ€ํ„ฐ์—๋Š” Jakarta Bean Validation ํ‘œ์ค€ API์™€ ์ด๋ฅผ ๊ตฌํ˜„ํ•œ Hibernate Validator๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ์–ด ๋ณ„๋„์˜ ์„ค์ • ์—†์ด ๋ฐ”๋กœ ๊ฒ€์ฆ ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.


2. ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ ์–ด๋…ธํ…Œ์ด์…˜ ์ ์šฉ

์˜์กด์„ฑ์„ ์ถ”๊ฐ€ํ•œ ํ›„์—๋Š” ํด๋ผ์ด์–ธํŠธ๋กœ๋ถ€ํ„ฐ ์ „๋‹ฌ๋ฐ›์„ ๋ฐ์ดํ„ฐ ๊ฐ์ฒด(DTO)์˜ ํ•„๋“œ์— ๊ฒ€์ฆ ๊ทœ์น™์„ ์–ด๋…ธํ…Œ์ด์…˜์œผ๋กœ ์ •์˜ํ•œ๋‹ค.

(์ฐธ๊ณ : Spring Boot 3.x ๋ฒ„์ „๋ถ€ํ„ฐ๋Š” javax.validation ๋Œ€์‹  jakarta.validation ํŒจํ‚ค์ง€๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.)

import lombok.Getter;
import lombok.NoArgsConstructor;
โ€‹
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Pattern;
import jakarta.validation.constraints.Size;

@Getter
@NoArgsConstructor
public class CommentCreateRequest {
@NotNull(message = "postId๋Š” ํ•„์ˆ˜์ž…๋‹ˆ๋‹ค.")
@Positive(message = "postId๋Š” 1 ์ด์ƒ์ด์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.")
private Long postId;

// null ํ—ˆ์šฉ
private Long parentId;

@NotBlank(message = "๋‹‰๋„ค์ž„์„ ์ž…๋ ฅํ•˜์„ธ์š”.")
@Size(max = 10, message = "๋‹‰๋„ค์ž„์€ ์ตœ๋Œ€ 10์ž์ž…๋‹ˆ๋‹ค.")
private String nickname;

@NotBlank(message = "๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ ์ž…๋ ฅํ•˜์„ธ์š”.")
@Pattern(regexp = "^\\d{4}$", message = "๋น„๋ฐ€๋ฒˆํ˜ธ๋Š” 4์ž๋ฆฌ ์ˆซ์ž์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค.")
private String password;

@NotBlank(message = "๋Œ“๊ธ€ ๋‚ด์šฉ์„ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”.")
@Size(max = 250, message = "๋Œ“๊ธ€์€ ์ตœ๋Œ€ 250์ž๊นŒ์ง€ ์ž…๋ ฅํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.")
private String content;
}


์ž์ฃผ ์‚ฌ์šฉํ•˜๋Š” ๋Œ€ํ‘œ์ ์ธ ๊ฒ€์ฆ ์–ด๋…ธํ…Œ์ด์…˜


  • @NotNull
    null์„ ํ—ˆ์šฉํ•˜์ง€ ์•Š๋Š”๋‹ค.
  • @NotEmpty
    null๊ณผ ๊ธธ์ด/ํฌ๊ธฐ๊ฐ€ 0์ธ ๊ฐ’์„ ํ—ˆ์šฉํ•˜์ง€ ์•Š๋Š”๋‹ค. (String, ๋ฐฐ์—ด, ์ปฌ๋ ‰์…˜, ๋งต ๋“ฑ์— ์ ์šฉ ๊ฐ€๋Šฅ)
  • @NotBlank
    null, ๋นˆ ๋ฌธ์ž์—ด(""), ๊ณต๋ฐฑ๋งŒ ์žˆ๋Š” ๋ฌธ์ž์—ด์„ ํ—ˆ์šฉํ•˜์ง€ ์•Š๋Š”๋‹ค. (String ํƒ€์ž…์—๋งŒ ์ ์šฉ ๊ฐ€๋Šฅ)
  • @Size(min, max)
    ๋ฌธ์ž์—ด, ๋ฐฐ์—ด, ์ปฌ๋ ‰์…˜ ๋“ฑ์˜ ๊ธธ์ด/ํฌ๊ธฐ๋ฅผ ์ œํ•œํ•œ๋‹ค.
  • @Min(value) / @Max(value)
    ์ง€์ •๋œ ๊ฐ’ ์ด์ƒ/์ดํ•˜์ธ์ง€ ๊ฒ€์ฆํ•œ๋‹ค. (long, int ๋“ฑ ์ •์ˆ˜ ๊ธฐ๋ฐ˜ ์ˆซ์ž ํƒ€์ž…)
  • @DecimalMin(value) / @DecimalMax(value)
    ์ง€์ •ํ•œ ๊ฐ’ ์ด์ƒ/์ดํ•˜์ธ์ง€ ๊ฒ€์ฆํ•œ๋‹ค. (BigDecimal, Double ๋“ฑ ์†Œ์ˆ˜์  ์ˆซ์ž ํƒ€์ž…, ๊ฐ’์€ ๋ฌธ์ž์—ด๋กœ ์ง€์ •)
  • @Positive / @PositiveOrZero
    0๋ณด๋‹ค ํฌ๊ฑฐ๋‚˜(๋˜๋Š” 0 ์ด์ƒ)์ธ ๊ฐ’์„ ๊ฒ€์ฆํ•œ๋‹ค.
  • @Past / @PastOrPresent
    ํ˜„์žฌ ์‹œ์ ์„ ๊ธฐ์ค€์œผ๋กœ ๊ณผ๊ฑฐ(๋˜๋Š” ํ˜„์žฌ ํฌํ•จ) ๋‚ ์งœ์ธ์ง€ ๊ฒ€์ฆํ•œ๋‹ค.
  • @Future / @FutureOrPresent
    ํ˜„์žฌ ์‹œ์ ์„ ๊ธฐ์ค€์œผ๋กœ ๋ฏธ๋ž˜(๋˜๋Š” ํ˜„์žฌ ํฌํ•จ) ๋‚ ์งœ์ธ์ง€ ๊ฒ€์ฆํ•œ๋‹ค.
  • @Pattern(regexp)
    ์ •๊ทœ ํ‘œํ˜„์‹์„ ์ด์šฉํ•ด ๋ฌธ์ž์—ด ํ˜•์‹์„ ๊ฒ€์ฆํ•œ๋‹ค. (String ํƒ€์ž…์—๋งŒ ์ ์šฉ ๊ฐ€๋Šฅ)
  • @Email
    ์œ ํšจํ•œ ์ด๋ฉ”์ผ ํ˜•์‹์ธ์ง€ ๊ฒ€์ฆํ•œ๋‹ค.


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

ํŠนํžˆ ๋ฌธ์ž์—ด, ์ˆซ์ž, ๋‚ ์งœ, ์ปฌ๋ ‰์…˜ ๋“ฑ ํƒ€์ž…๋ณ„๋กœ ์ง€์›ํ•˜๋Š” ์–ด๋…ธํ…Œ์ด์…˜์ด ๋‹ค๋ฅด๊ธฐ ๋•Œ๋ฌธ์— ๋‹จ์ˆœํžˆ ํ•„์ˆ˜๊ฐ’ ์—ฌ๋ถ€๋งŒ์ด ์•„๋‹ˆ๋ผ ๊ฐ’์˜ ๋ฒ”์œ„, ํ˜•์‹, ๊ธธ์ด, ์‹œ์  ์กฐ๊ฑด๊นŒ์ง€ ํ•จ๊ป˜ ๊ฒ€ํ† ํ•ด์•ผ ํ•œ๋‹ค.


@NotNull, @NotEmpty, @NotBlank ์ฐจ์ด

์ฒ˜์Œ ์‚ฌ์šฉํ•  ๋•Œ ๊ฐ€์žฅ ํ—ท๊ฐˆ๋ฆฌ๋Š” ๋ถ€๋ถ„์ด๊ธฐ ๋•Œ๋ฌธ์— 3๊ฐ€์ง€ ์–ด๋…ธํ…Œ์ด์…˜์— ๋Œ€ํ•ด ๋‹ค์‹œ ํ•œ ๋ฒˆ ์ •๋ฆฌํ•ด๋ณด์ž.

@NotNull
1. ๋ชจ๋“  ํƒ€์ž…์— ์ ์šฉ ๊ฐ€๋Šฅ
2. ๊ฐ’์ด null์ด ์•„๋‹Œ์ง€๋งŒ ๊ฒ€์‚ฌ
3. ๋ฌธ์ž์—ด์˜ ๊ฒฝ์šฐ ๋นˆ ๋ฌธ์ž์—ด("")๊ณผ ๊ณต๋ฐฑ(" ")์€ ํ—ˆ์šฉ

@NotEmpty
1. String, ๋ฐฐ์—ด, Collection, Map ๋“ฑ์— ์ ์šฉ ๊ฐ€๋Šฅ
2. null์ด ์•„๋‹ˆ๊ณ  ๊ธธ์ด/ํฌ๊ธฐ๊ฐ€ 0์ด ์•„๋‹Œ์ง€ ๊ฒ€์‚ฌ
3. ๋ฌธ์ž์—ด์˜ ๊ฒฝ์šฐ ๊ณต๋ฐฑ(" ")์€ ํ—ˆ์šฉ

@NotBlank
1. String ํƒ€์ž… ์ „์šฉ ์–ด๋…ธํ…Œ์ด์…˜
2. null, ๋นˆ ๋ฌธ์ž์—ด(""), ๊ณต๋ฐฑ๋งŒ ์žˆ๋Š” ๋ฌธ์ž์—ด ๋ชจ๋‘ ํ—ˆ์šฉํ•˜์ง€ ์•Š๋Š”๋‹ค.
3. ๋ฌธ์ž์—ด ํ•„์ˆ˜๊ฐ’ ๊ฒ€์ฆ ์‹œ ๊ฐ€์žฅ ๋งŽ์ด ์‚ฌ์šฉ๋œ๋‹ค.


@Valid๋กœ ์ค‘์ฒฉ ๊ฐ์ฒด ๊ฒ€์ฆ

DTO ์•ˆ์— ๋˜ ๋‹ค๋ฅธ DTO๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ๋Š” ๊ฒฝ์šฐ ์ƒ์œ„ DTO ํ•„๋“œ์— @Valid๋ฅผ ๋ถ™์—ฌ์•ผ ๋‚ด๋ถ€ ๊ฐ์ฒด๊นŒ์ง€ ํ•จ๊ป˜ ๊ฒ€์ฆ๋œ๋‹ค.

@Getter
public class OrderRequest {
@Valid
@NotNull
private AddressRequest address;
}
@Getter
public class AddressRequest {
@NotBlank
private String city;

@NotBlank
private String street;
}

Bean Validation์€ ๊ธฐ๋ณธ์ ์œผ๋กœ ํ•ด๋‹น ๊ฐ์ฒด์˜ ์ง์ ‘์ ์ธ ํ•„๋“œ๊นŒ์ง€๋งŒ ๊ฒ€์‚ฌํ•œ๋‹ค. ๋”ฐ๋ผ์„œ ์ค‘์ฒฉ ๊ฐ์ฒด์˜ ๋‚ด๋ถ€ ํ•„๋“œ๊นŒ์ง€ ๊ฒ€์ฆํ•˜๋ ค๋ฉด ๊ฒ€์ฆ์ด ํ•˜์œ„ ๊ฐ์ฒด๋กœ ์ „ํŒŒ๋˜๋„๋ก @Valid๋ฅผ ๋ช…์‹œ์ ์œผ๋กœ ์„ ์–ธํ•ด์•ผ ํ•œ๋‹ค.

๋งŒ์•ฝ OrderRequest์—์„œ address ํ•„๋“œ์— @Valid๋ฅผ ๋ถ™์ด์ง€ ์•Š์œผ๋ฉด AddressRequest ๋‚ด๋ถ€์˜ city, street ํ•„๋“œ์— ๋Œ€ํ•œ ๊ฒ€์ฆ์€ ์ˆ˜ํ–‰๋˜์ง€ ์•Š๋Š”๋‹ค.


์ปฌ๋ ‰์…˜ ๋‚ด๋ถ€ ์š”์†Œ ๊ฒ€์ฆ

์ปฌ๋ ‰์…˜ ์ž์ฒด๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ๋‚ด๋ถ€ ์š”์†Œ๊นŒ์ง€ ํ•จ๊ป˜ ๊ฒ€์ฆํ•  ์ˆ˜ ์žˆ๋‹ค.

@Getter
public class PostRequest {
@NotEmpty
private List<@NotBlank String> tags;
}

์ด ๋ฌธ๋ฒ•์€ Java 8 ์ดํ›„์˜ ์ปจํ…Œ์ด๋„ˆ ์š”์†Œ ์ œ์•ฝ ๊ธฐ๋Šฅ์ด๋ฉฐ @NotEmpty๋ฅผ ํ†ตํ•ด ๋ฆฌ์ŠคํŠธ๊ฐ€ null์ด ์•„๋‹ˆ๊ณ  ๋น„์–ด์žˆ์ง€ ์•Š์€์ง€๋ฅผ ์šฐ์„  ๊ฒ€์‚ฌํ•˜๊ณ  @NotBlank๋ฅผ ํ†ตํ•ด ๋ฆฌ์ŠคํŠธ์— ํฌํ•จ๋œ ๊ฐ ์š”์†Œ๊ฐ€ null, ๋นˆ ๋ฌธ์ž์—ด, ๊ณต๋ฐฑ ๋ฌธ์ž์—ด์ด ์•„๋‹Œ์ง€ ์ถ”๊ฐ€ ๊ฒ€์ฆํ•œ๋‹ค.

์ฆ‰ ์ปฌ๋ ‰์…˜์˜ ๊ตฌ์กฐ์™€ ๊ฐ ์š”์†Œ์˜ ๊ฐ’์„ ๋™์‹œ์— ๊ฒ€์ฆํ•  ์ˆ˜ ์žˆ๋‹ค.


3. Controller์— @Valid ์ ์šฉ

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

๋งŒ์•ฝ @Valid๋ฅผ ๋ถ™์ด์ง€ ์•Š์œผ๋ฉด DTO์— ๊ฒ€์ฆ ์–ด๋…ธํ…Œ์ด์…˜์ด ์ •์˜๋˜์–ด ์žˆ์–ด๋„ ๊ฒ€์ฆ์€ ์ˆ˜ํ–‰๋˜์ง€ ์•Š๋Š”๋‹ค. ์ฆ‰ DTO์— ์ œ์•ฝ ์กฐ๊ฑด์„ ์„ ์–ธํ•˜๋Š” ๊ฒƒ๊ณผ ์‹ค์ œ ๊ฒ€์ฆ ์‹คํ–‰์€ ๋ณ„๊ฐœ์˜ ๋‹จ๊ณ„์ด๋‹ค.

@Valid๋Š” ์ „๋‹ฌ๋ฐ›์€ ๊ฐ์ฒด์— ์ •์˜๋œ ์ œ์•ฝ ์กฐ๊ฑด์„ ๊ธฐ๋ฐ˜์œผ๋กœ ์š”์ฒญ ๋ฐ์ดํ„ฐ๊ฐ€ ์œ ํšจํ•œ์ง€ ๊ฒ€์‚ฌํ•˜๋Š” ์—ญํ• ์„ ํ•œ๋‹ค. ์ฃผ๋กœ @RequestBody๋‚˜ @ModelAttribute์™€ ํ•จ๊ป˜ ์‚ฌ์šฉ๋œ๋‹ค.

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

ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์š”์ฒญ์„ ๋ณด๋‚ด๋ฉด Spring์ด ์š”์ฒญ ๋ฐ์ดํ„ฐ๋ฅผ DTO๋กœ ๋ฐ”์ธ๋”ฉํ•˜๊ณ  @Valid๊ฐ€ ๋ถ™์–ด ์žˆ๋‹ค๋ฉด Bean Validation์„ ์ˆ˜ํ–‰ํ•œ๋‹ค. ์ด๋•Œ ๊ฒ€์ฆ ๊ณผ์ •์—์„œ ํ•˜๋‚˜๋ผ๋„ ์ œ์•ฝ ์กฐ๊ฑด์„ ๋งŒ์กฑํ•˜์ง€ ๋ชปํ•˜๋ฉด ๊ฒ€์ฆ์ด ์‹คํŒจํ•˜๋ฉฐ ์ปจํŠธ๋กค๋Ÿฌ ๋ฉ”์„œ๋“œ๊ฐ€ ์‹คํ–‰๋˜๊ธฐ ์ „์— ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.


4. ์˜ˆ์™ธ ์ฒ˜๋ฆฌ

@Valid์— ์˜ํ•œ ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ๊ฐ€ ์‹คํŒจํ•˜๋ฉด ๋Œ€ํ‘œ์ ์œผ๋กœ ๋‘ ๊ฐ€์ง€ ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.

  • @RequestBody๋กœ ์ „๋‹ฌ๋œ DTO์˜ ๊ฒ€์ฆ์ด ์‹คํŒจํ•œ ๊ฒฝ์šฐ
    MethodArgumentNotValidException
  • @ModelAttribute ๋˜๋Š” @RequestParam ๋ฐฉ์‹์œผ๋กœ ์ „๋‹ฌ๋œ ๋ฐ์ดํ„ฐ์˜ ๊ฒ€์ฆ์ด ์‹คํŒจํ•œ ๊ฒฝ์šฐ
    BindException

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


BindingResult๋กœ ์ง์ ‘ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐฉ๋ฒ•

์ปจํŠธ๋กค๋Ÿฌ ๋ฉ”์„œ๋“œ์—์„œ @Valid ๋ฐ”๋กœ ๋’ค์— BindingResult๋ฅผ ์„ ์–ธํ•˜๋ฉด ๊ฒ€์ฆ ์‹คํŒจ ์‹œ ์˜ˆ์™ธ๋ฅผ ๋ฐœ์ƒ์‹œํ‚ค์ง€ ์•Š๊ณ  ์˜ค๋ฅ˜ ์ •๋ณด๋ฅผ ์ง์ ‘ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค.

@PostMapping
public ResponseEntity<?> createPost(
@Valid @RequestBody PostCreateRequest request,
BindingResult bindingResult) {

if (bindingResult.hasErrors()) {
return ResponseEntity.badRequest().body(bindingResult.getAllErrors());
}

return ResponseEntity.ok().build();
}โ€‹

@Valid๊ฐ€ ๊ฒ€์ฆ์„ ์ˆ˜ํ–‰ํ•œ ํ›„ ๊ฒ€์ฆ ์‹คํŒจ ์‹œ ์˜ˆ์™ธ๋ฅผ ๋˜์ง€๋Š” ๋Œ€์‹  ์˜ค๋ฅ˜ ์ •๋ณด๋ฅผ BindingResult ๊ฐ์ฒด์— ์ €์žฅํ•œ๋‹ค. ์ดํ›„ bindingResult.hasErrors()๋ฅผ ํ†ตํ•ด ๊ฒ€์ฆ ์‹คํŒจ ์—ฌ๋ถ€๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

์ด ๋ฐฉ์‹์€ ๊ฐ„๋‹จํ•œ API์—์„œ ๋น ๋ฅด๊ฒŒ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ์žฅ์ ์ด ์žˆ์ง€๋งŒ ์ปจํŠธ๋กค๋Ÿฌ๋งˆ๋‹ค ์œ ์‚ฌํ•œ ๊ฒ€์ฆ ์ฒ˜๋ฆฌ ์ฝ”๋“œ๊ฐ€ ๋ฐ˜๋ณต๋  ์ˆ˜ ์žˆ์œผ๋ฉฐ ๊ณตํ†ต ์‘๋‹ต ํฌ๋งท์„ ์œ ์ง€ํ•˜๊ธฐ ์–ด๋ ต๋‹ค๋Š” ๋‹จ์ ์ด ์žˆ๋‹ค.


@RestControllerAdvice๋ฅผ ์ด์šฉํ•œ ์ „์—ญ ์˜ˆ์™ธ ์ฒ˜๋ฆฌ

์‹ค๋ฌด์—์„œ๋Š” ๋ณดํ†ต ์ „์—ญ ์˜ˆ์™ธ ์ฒ˜๋ฆฌ ๋ฐฉ์‹์„ ์‚ฌ์šฉํ•œ๋‹ค.

@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<?> handleValidationException(
MethodArgumentNotValidException ex) {

List<String> errors = ex.getBindingResult()
.getFieldErrors()
.stream()
.map(error -> error.getField() + ": " + error.getDefaultMessage())
.toList();

return ResponseEntity.badRequest().body(errors);
}
}

๋ชจ๋“  ์ปจํŠธ๋กค๋Ÿฌ์—์„œ ๋ฐœ์ƒํ•˜๋Š” ์˜ˆ์™ธ๋ฅผ ๊ณตํ†ต์œผ๋กœ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ ์ผ๊ด€๋œ ์—๋Ÿฌ ์‘๋‹ต ํฌ๋งท์„ ์œ ์ง€ํ•  ์ˆ˜ ์žˆ์–ด ์œ ์ง€๋ณด์ˆ˜ ์ธก๋ฉด์—์„œ ์œ ๋ฆฌํ•˜๋‹ค.

ๅ‰ใฎ่จ˜ไบ‹
๐Ÿ–ผ๏ธ ์›น ์„ฑ๋Šฅ์„ ์œ„ํ•œ ์ด๋ฏธ์ง€ ์••์ถ• ๋„๊ตฌ ์ •๋ฆฌ (TinyPNG & Squoosh)
ๆฌกใฎ่จ˜ไบ‹
๐ŸŒœ Next.js๋กœ ๋‹คํฌ๋ชจ๋“œ ๊ตฌํ˜„ํ•˜๊ธฐ (next-themes)
่ฃ…้ฃพใƒญใ‚ด