bindingResult 가 무엇일까? (feat. Valid)

스프링 부트를 이용해 api를 구현하다보면, 입력값을 받아야 하는 경우가 존재한다. 사용자에게서 데이터를 받아 저장할 일이 반드시 생기기 때문이다. 이 때 사용자가 어떤 데이터를 마음대로 커스텀해서 보낼지 모르기 때문에 반드시 데이터 검증을 해야한다. 스프링부트에서는 검증을 빠르게 해주는 validation이 있다. 단, 2.3이상부터는 따로 분리되었기 때문에 반드시 의존성을 따로 추가해 주어야 한다.

    implementation 'org.springframework.boot:spring-boot-starter-validation'

gradle

 

내가 정의한 Dto에 @Null과 같은 validation annotation을 붙이고 컨트롤러 인자에 @Valid(자바에서 지원) 혹은 @Validated(스프링에서 지원)를 사용하면 알아서 검증해준다. 아래와 같이 사용할 수 있다.

public class PostController {
	@PostMapping()
	public void createPost(@Valid PostDto PostDto) {
	}
}


// PostDto.java
public class PostDto {
	@NotBlank
	String title;
	@NotBlank
	String content;
}

여러가지 어노테이션이 있는데 어지간한건 다 있으니까 검색해보면 된다. 아래 참고 링크를 들어가면 더 다양한 어노테이션에 대한 설명이 있다. 지금 주제의 핵심이 아니기 때문에 이정도로 넘어간다.

 

만약 스프링부트는 요청이들어왔을 때 검증에 실패한다면 자동으로 exception을 발생시키고 status code 400 응답을 보낸다.

Field error in object 'postDto' on field 'test': rejected value [null];
codes [NotBlank.postDto.test,NotBlank.test,NotBlank.java.lang.String,NotBlank];
arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [postDto.test,test];
arguments [];
default message [test]];
default message [공백일 수 없습니다]


org.springframework.validation.BindException: org.springframework.validation.BeanPropertyBindingResult

 

알아서 검증해주고 응답 반환해주는건 좋은데.. 만약 내가 응답을 커스텀하고 싶다면 어떻게 해야할까? 이때 사용하는게 BindingResult다.

BindingResult는 검증 오류를 보관해주는 객체이다.

컨트롤러 파라미터에 BindingResult를 선언해 주지 않으면 스프링은 알아서 400 오류를 반환해주고 컨트롤러는 호출되지 않는다.

컨트롤러 파라미터에 BindingResult를 선언해주면 여기에 오류가 담기게 되고 컨트롤러가 호출되어 특정 동작을 수행할 수 있다.

 

public class PostController {
	@PostMapping()
	public void createPost(@Valid PostDto PostDto, BindingResult bindingResult) {
    		System.out.println(bindingResult.toString());
	}
}


// PostDto.java
public class PostDto {
	@NotBlank
	String title;
	@NotBlank
	String content;
}

BindingResult를 추가하고 올바른 입력값을 요청으로 보낸 뒤 어떻게 나오나 출력해 보았다.

org.springframework.validation.BeanPropertyBindingResult: 0 errors

 

다음은 에러를 고의로 발생시키고 어떻게 나오나 출력해 보았다.

org.springframework.validation.BeanPropertyBindingResult: 1 errors

이 문장과 함께 아까 위에서 나왔던 검증 실패 에러 메시지가 출력되는것을 볼수 있었다.

 

더 구체적으로 어떤식으로 동작하는지는 잘 이해하지 못했다. 희한하게 자바 스프링은 뭔가 제대로된(?) 자료를 찾기가 더 힘든것 같다. 한국어 블로그가 너무 많이보여서 그런가 싶기도 하다. 참고에 공식문서 링크도 달아놨는데 솔직히 저것만으로는 잘 이해가 안된다.

 

결론

결론적으로.. 자동으로 반환하게 한 뒤 exception handler를 구현해 예외처리를 해주어도 되지만, 만약 검증에 실패했더라도 어떤 동작을 수행하게 하고 싶으면 BindingResult를 사용하면 될것같다. 구체적인 내용까지 하나하나 다 기억하는 것은 힘드니 키워드와 이것이 어쩔때 유용할지 정도만 기억해두고 넘어가자.

 

참고

validation

https://velog.io/@mooh2jj/Spring-Boot-Validation-%EC%A0%81%EC%9A%A9%ED%95%98%EB%8A%94-%EB%B2%95

 

공식문서

https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/validation/BindingResult.html

 

공식문서 가이드

https://spring.io/guides/gs/validating-form-input/