• 카테고리

    질문 & 답변
  • 세부 분야

    백엔드

  • 해결 여부

    해결됨

@RequestBody의 바인딩에러를 잡는 방법

21.12.24 14:44 작성 조회수 1.1k

1

안녕하세요 기선님, 좋은 강의를 해주셔서 감사합니다.

다름이 아니라, event 의 limit을 integer가 아닌 string으로 요청을 보냈을 때,

@ModelAttribute 로 요청 파라미터로 보낼 때는 데이터바인딩 에러를 감지해서 BindingResult에 에러가 담겼는데,

@RequestBody 로 요청 바디로 보낼때는 BindingResult에 에러가 담기지 않고, 400 에러를 발생시켰습니다.

제 예상으로는 HttpMessageConverter에서 데이터 변환을 할 때 발생하는 에러는 BindingResult에 담기지 않는 것 같은데, 이러한 바인딩 에러를 핸들러에서 받아서 처리할 수 있는 방법이 있을까요?

그리고 @RequestBody와 함께 사용하는 BindingResult는 Validation 체크에 대한 에러만 담기는 건지 궁금합니다.

 

==테스트 코드==

@RestController
public class TestController {

	@PostMapping("/events/ma")
	public Event maEvent(@ModelAttribute Event event, BindingResult bindingResult) {
		return event;
	}
	
	@PostMapping("/events/rb")
	public Event rbEvent(@RequestBody Event event, BindingResult bidningResult) {
		return event;
	}
	
}

==============

@RunWith(SpringRunner.class)
@SpringBootTest
@AutoConfigureMockMvc
public class TestControllerTest {

  @Autowired
  MockMvc mockMvc;
  
  @Test
  public void createEvent() throws Exception {
    
    String json = "{\"name\":\"juni\",\"limit\":\"juni\"}";
        
    mockMvc.perform(post("/events/rb")
                        .contentType(MediaType.APPLICATION_JSON)
                        .content(json))
              .andDo(print())
              .andExpect(status().isBadRequest())
    ;
    System.out.println("===============================");
    
    mockMvc.perform(post("/events/ma")
                        .param("name", "juni")
                        .param("limit", "juni"))
              .andDo(print())
              .andExpect(status().isOk())
    ;
  }
}

=====================

public class Event {

	private String name;
	private Integer limit;
	
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public Integer getLimit() {
		return limit;
	}
	public void setLimit(Integer limit) {
		this.limit = limit;
	}
	
}

답변 2

·

답변을 작성해보세요.

2

안녕하세요. 좋은 질문이네요.

조금 어려운 이슈인데, 이 이슈는 안타깝게도 현재 @RequestBody로는 해결할 수 없습니다.

https://github.com/spring-projects/spring-framework/issues/11406

이 링크에 보이는 마지막 두개의 댓글만 읽으시면 이해하실 수 있을텐데요. 바인딩을 하는 주체가 스프링이면 int 값을 받아야 하는데 문자열을 받은 경우에도 BindingResult로 넣어줄 수 있겠지만, @RquestBody는 Jackson이나 Gson같은 외부 라이브러리가 그런 일을 담당하고 거기선 일반적인 에러만 던져주기 때문에 @ModelAttribute와 동일하게 처리하긴 어려운 것으로 보입니다.

대신 바인딩이 가능한 값이라면 @Valid와 함께 사용해서 Event라는 모델에 사용하는 JSR-303 애노테이션으로 추가적인 검증 작업은 가능합니다.

감사합니다.

0

링크와 답변을 통해 @ModelAttribute와 @RequestBody에 대해 좀 더 깊게 이해하게 된 것 같습니다.

좋은 답변을 해주셔서 감사합니다.