λ³Έλ¬Έ λ°”λ‘œκ°€κΈ°

Spring boot

@Valid 둜 DTO 검증

728x90
λ°˜μ‘ν˜•

πŸ€” 검증이 ν•„μš”ν•œ 이유 ?!

컨트둀러의 μ€‘μš”ν•œ μ—­ν•  쀑 ν•˜λ‚˜λŠ” 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

728x90
λ°˜μ‘ν˜•