@Slf4j
@RestController
@RequestMapping("/validation/api/items")
public class ValidationItemApiController {
@PostMapping("/add")
public Object addItem(@RequestBody @Validated ItemSaveForm form, BindingResult bindingResult){
log.info("API 컨트롤러 호출");
if(bindingResult.hasErrors()){
log.info("검증 오류 발생 errors = {}", bindingResult);
return bindingResult.getAllErrors();
}
log.info("성공 로직 실행");
return form;
}
}
@RestController를 쓴다.
@Controller + @ResponseBody이다.
즉, 응답을 ResponseBody, HttpMessageConverter를 이용해 해준다.
(자세한 건 https://qwefdg3.tistory.com/270)
대충 다시 설명을 하자면,
ResponseBody는 응답을 view같은 템플릿 이름이 아니라 HttpMessageConverter를 사용하면서 반환된다.
이거는 Http 메시지 바디에 그대로 넣어주는거다.
어떤 형태로 반환할 지는 요청의 Accept 헤더와 반환 타입등을 보고 어떤 컨버터를 쓸 지 결정한다.
지금의 경우 Object이니 아마 Json 형태로 반환할 것이다. (만약 요청의 Accept가 */* 전체이거나 application/json일 경우)
@RequestBody는 Http 메시지 바디에 있는 데이터를 자동형변환 해서 가져오는 것이다.
@ModelAttribute와의 차이점은 먼지 @ModelAttribute는 GET 쿼리파라미터나 form의 POST(이것도 바디를 통해서 오지만)만 받아들일 수 있다.
@RequestBody는 바디에 있는 데이터를 받아들이는 것이다. 기본 값은 @ModelAttribute이므로, form의 POST를 제외하고 메시지 바디의 데이터를 받아들이고 싶을 때에는 @RequestBody라고 명시해 줘야 한다.
@RequestBody로 받으면
요청의 Body -> HttpMessageConverter -> 객체
이렇게 HttpMessageConverter를 거치며 변환이 된다.
(이 부분 참고하면 좋다. https://qwefdg3.tistory.com/267 )
여튼 HttpMessageConverter는 컨트롤러의 반환타입이나 인자 타입을 검사, 요청의 경우 대상 헤더의 Content-type을 검사, 응답의 경우 요청 헤더의 Accept를 검사 등을 해서 Json, String 등 어떤 타입으로 바꿀 지 결정
HttpMessageConverter는 @RequestBody로 데이터를 받거나 @ResponseBody로 데이터를 보낼 때 거침.
참고로, 이 HttpMessageConverter를 거치는 것들은 @Validated가 있어도 객체를 만들지 못하면 끝이다.
HttpMessageConverter를 통해 객체를 만들어야 하는데
원래 그냥 @ModelAttribute경우 타입 등이 안 맞아도 @Validated가 있으면 이어서 컨트롤러가 실행됐지만,
@RequestBody나 @ResponseBody경우 아예 멈추고 오류를 반환한다.
그러니까 @Validated 이전에 뭘 하는 것인지, 아예 @Validated 자체가 호출이 안된다.
HttpMessageConverter가 먼저인가 보다.
객체를 만들고 나서, 그 후 검증을 하는 모양이다.
객체는 제대로 만들게 끔 해야 한다. 타입이라든지. 제대로 객체가 안만들어지면
이런 식으로 오류가 나는데, 만약 이렇게 되지 않게끔 하려면 따로 예외처리를 해 줘야 한다.
그리고 뭐 객체는 제대로 만들어 졌는데, 우리가 만든 검증 로직을(아니 우리가 만든 게 아니고 스프링이 만든 @Validated를 통해) 통과하지 못했다면
이런 긴 bindingResult의 모든 에러들을 반환하게 했는데,
실제로 쓸 때는 우리가 API 스펙(HTTP 메시지의 Json 형식을 말하는 듯)을 잘 정의하여 저 에러들에서 필요한 부분만 뽑아 반환토록 해야 한다.
@ModelAttribute 는 필드단위로 정교하게 바인딩 되지만, @ResponseBody, @RequestBody 등 HttpMessageConverter를 거치는 것 들은 객체를 만들 지 못하면 그냥 끝이다.
'스프링 > 4. 스프링 MVC-2' 카테고리의 다른 글
44. 멤버 회원가입 구현 (0) | 2023.09.04 |
---|---|
43. 도메인과 표현 분리 (0) | 2023.09.04 |
41. Form 전송객체 분리 (0) | 2023.09.04 |
40. 컨트롤러 간 검증이 다른 경우. (0) | 2023.09.03 |
39. 빈 검증 오브젝트 에러 (0) | 2023.09.03 |