π€ κ²μ¦μ΄ νμν μ΄μ ?!
컨νΈλ‘€λ¬μ μ€μν μν μ€ νλλ HTTP μμ²μ΄ μ μμΈμ§ κ²μ¦νλ κ²μ΄λ€.
ν΄λΌμ΄μΈνΈ κ²μ¦μ μ‘°μμ΄ κ°λ₯νκΈ° λλ¬Έμ 보μμ μ·¨μ½νλ€.
μλ²μμλ μλͺ»λ μμ²μ κ²μ¦νλ λ‘μ§μ νμλ‘ νλ€.
Bean Validation
νΉμ ν ꡬνμ²΄κ° μλλΌ Bean Validation 2.x κΈ°μ νμ€μ΄λ€.
κ²μ¦ μ΄λ Έν μ΄μ κ³Ό μ¬λ¬ μΈν°νμ΄μ€μ λͺ¨μμ΄λ€.
Bean Validationμ μ νμ©νλ©΄ μ΄λ Έν μ΄μ νλλ‘ κ²μ¦ λ‘μ§μ νΈλ¦¬νκ² μ μ©ν μ μλ€.
//build.gradle
implementation 'org.springframework.boot:spring-boot-starter-validation'

@AssertFalse : false κ° ν΅κ³Ό
@AssertTrue : true κ° ν΅κ³Ό
@DecimalMax(value=, inclusive=) : μ§μ λ κ° μ΄νμ μ€μ ν΅κ³Ό
@DecimalMin(value=, inclusive=) : μ§μ λ κ° μ΄μμ μ€μ ν΅κ³Ό
@Digits(integer=, fraction=) : λμ μκ° μ§μ λ μ μμ μλ¦Ώμλ³΄λ€ μ μ κ²½μ° ν΅κ³Ό
@Email : μ΄λ©μΌ νμ ν΅κ³Ό
@Future : λμ λ μ§κ° νμ¬λ³΄λ€ λ―ΈλμΌ κ²½μ° ν΅κ³Ό
@Past : λμ λ μ§κ° νμ¬λ³΄λ€ κ³Όκ±°μΌ κ²½μ°λ§ ν΅κ³Ό
@Max(value=) : μ§μ λ κ°λ³΄λ€ μλμΌ κ²½μ°λ§ ν΅κ³Ό
@Min(value=) : μ§μ λ κ°λ³΄λ€ μ΄μμΌ κ²½μ°λ§ ν΅κ³Ό
@NotNull : null κ°μ΄ μλ κ²½μ°λ§ ν΅κ³Ό
@NotEmpty : null, "" μ΄ μλ κ²½μ° ν΅κ³Ό
@NotBlank : null, "", " " μ΄ μλ κ²½μ° ν΅κ³Ό
@Null : nullμΌ κ²½μ°λ§ ν΅κ³Ό
@Pattern(regex=, flag=, message=) : ν΄λΉ μ κ·μμ λ§μ‘±ν κ²½μ°λ§ ν΅κ³Ό
@Size(min=, max=) : λ¬Έμμ΄ λλ λ°°μ΄μ΄ μ§μ λ κ° μ¬μ΄μΌ κ²½μ° ν΅κ³Ό
λ¬Έμμ΄μ 곡백κΉμ§ μ²΄ν¬ -> @NotBlank
@NotEmpty -> Collection, @NotNull -> κ°μ²΄
//valiation μ΄λ
Έν
μ΄μ
μ μ¬μ©νλ €λ©΄ 컨νΈλ‘€λ¬μ λ©μλ λ§€κ°λ³μμ @Valid μ΄λ
Έν
μ΄μ
μ λΆμ¬μΌ νλ€.
@PostMapping("...")
public RespnseEntity<> getDiary(@RequestBody @Valid ...)
//DTOμ μ μ©νκΈ°
@Builder
@Getter
@AllArgsConstructor
@NoArgsConstructor
public class diaryReqeust {
@NotNull(message = "μ§μΆ λΉμ© μ
λ ₯")
@Min(value = 0, message = "μ§μΆ λΉμ© μ΅μ 0")
@Max(value = 99, message = "μ§μΆ λΉμ© μ΅λ 99")
private Long price;
@NotBlank(message = "μ§μΆ λͺ
μ
λ ₯")
@Size(min = 1, max = 16, message = "μ§μΆ λͺ
μ 16μ μ΄ν")
private String title;
@NotBlank(message = "λ΄μ©μ μ
λ ₯νμ
")
@Size(min = 1, max = 80, message = "λ΄μ©μ 80μ μ΄ν")
private String context
......
//@Email(message = "μ¬λ°λ₯΄μ§ μμ μ΄λ©μΌ νμ: ${validatedValue}")
Spring MVC ꡬ쑰

@Validλ νΈλ€λ¬ μ΄λν°κ° νΈλ€λ¬λ₯Ό νΈμΆνλ κ³Όμ μμ λμνλ€.(컨νΈλ‘€λ¬μμλ§ λμ)
RequestMappingHadlerAdapter λμ λ°©μ

Controller Test Code
컨νΈλ‘€λ¬λ‘ λ€μ΄μ€λ μ λ ₯ κ°μ λν κ²μ¦μ΄ μ λλ‘ μ΄λ£¨μ΄μ§λμ§ ν μ€νΈ μ½λ
titleμ @NotBlankκΈ° λλ¬Έμ 곡백μ μ λ ₯νλ©΄ μμΈμ²λ¦¬κ° λμΌ λλ€.
@Test
@DisplayName("exception test")
@NullAndEmptySource
void test() throw Exception {
DiaryRequest diary =
DiaryRequest.builder()
.price(3000)
.title(" ")
.content("i like it")
.imgUrl("")
.evaluation(1)
.build();
MockHttpServletRequestBuilder requestBuilder =
MockMvcRequestBuilders.post("...", 1)
.with(csrf())
.content(objectMapper.writeValueAsString(diary))
.contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON);
mockMvc.perform(requestBuilder)
.andDo(print())
.andExpect(
result -> {
Exception exception = result.getResolvedException();
Objects.requireNonNull(exception);
assertTrue(
exception.getClass()
.isAssignableFrom(
MethodArgumentNotValidException.class));
});
}
βοΈ μ΅κ·Όμ 3.3 κ³Όμ λ₯Ό 보μκ³ JUnitμΌλ‘ ν μ€νΈ μ½λ μμ±νλ κ²μ΄ λ§μ§λ§ λ§λ¬΄λ¦¬μλλ° μμ±νμ§ λͺ»νλ κΈ°μ΅μ΄ μλ€.
μλΉμ€μ μμ μ±μ μν΄μλ μλͺ»λ μμ²μ λν κ²μ¦μ΄ νμμΈ κ²κ°λ€.
DTOμμ μ μ½μ‘°κ±΄μΌλ‘ μλͺ»λ μμ²μ κ²μ¦νλ κ²μ 컨νΈλ‘€λ¬ λ¨μμ λ§μ μ μκΈ° λλ¬Έμ ν¨κ³Όμ μ΄λ€.
μ°Έκ³ μλ£ : https://github.com/devSquad-study/2023-CS-Study/blob/main/Spring/spring_%40valid.md
'Spring boot' μΉ΄ν κ³ λ¦¬μ λ€λ₯Έ κΈ
| iOS In-App Purchase μλ² κ²μ¦ ꡬννκΈ° (JWS λ°©μ) (0) | 2025.12.01 |
|---|---|
| [ JPA ] Eager, Lazy Fetching (0) | 2024.01.15 |
| [ Spring ] @Bean (1) | 2024.01.11 |
| νμ κ°μ κΈ°λ₯ ꡬννκΈ° (0) | 2023.09.12 |
| μ€νλ§ μν리ν°(Spring Security) (0) | 2023.09.06 |