티스토리 뷰

728x90

이 4개는 매일 사용하면서도 매일 헷갈린다.

내용 정리를 확실하게 해놔야 할 필요성을 느껴 정리한다.

 

@RequestBody 

HTTP 요청으로 넘어오는 body의 내용을 HttpMessageConverter를 통해 Java Object로 역직렬화한다.

multipart 요청이 아닌, 즉 어떤 바이너리 파일을 포함하고 있지 않은 데이터를 받는 역할을 한다.

HttpMessageConverter란?
간단하게 HTTP 요청과 응답에 대해서 "전략 패턴"을 사용해서 converting 해주는 역할.

전략 패턴은 하나의 메서드가 여러 가지의 대응 방법을 미리 준비해두고 필요한 상황마다 대응 방법을 달리 하는 방법을 말한다.

 

RequestBody는 HTTP 요청으로 같이 넘어오는 Header의 Content-type을 보고 어떤 Converter를 사용할지 정하기에 Content-type을 반드시 명시해야 한다.

Content-type의 종류 (중 일부)

application/json: {key : value}의 형태로 전송
application/x-www-form-urlencoded: key=value&key=value 형태로 전송(HTML form의 default 값)
multipart/form-data: 파일 업로드시 사용되며 '파일을 비롯한 여러 데이터가 있음'이라는 뜻을 가짐. (@RequestBody로 받을 수 없음 !!)

 

사용 방법: REST API를 통해 단순 데이터를 주고 받는 일반적인 경우에 사용할 수 있다. 

Controller에서 받을때 어노테이션 생략시 @ModelAttribute가 default이므로 @RequestBody를 사용하고자 하는 경우에는 반드시 기술해야 한다.

 

@RequestPart

Content-type이 'multipart/form-data'와 관련된 경우에 사용한다.

MultipartFile이 포함되는 경우에 MutliPartResolver가 동작하여 (여기서도 전략 패턴이 사용된다) 역직렬화를 하게 됨.

MultipartFile이 포함되지 않는 경우는 @RequestBody와 같이 HttpMessageConverter가 동작하게 된다.

 

사용 방법: @RequestBody가 필요하지만 Binary Stream이 포함되는 경우(MultipartFile과 같은)에 사용할 수 있다.

 

@RequestParam

하나의 파라미터만을 받을때 사용된다. 기본적으로 파라미터가 필수적으로 들어오게 설정되어 있기에 파라미터가 들어오지 않는 경우 BadRequest가 발생하므로 파라미터가 들어올 수도, 들어오지 않을 수도 있다면 required = false를 주어야 한다.

 

@RequestParam 또한 @RequestPart와 같이 MultipartFile을 받을 때 사용할 수 있다.

@RequestPart와의 다른 점은 @RequestParam의 경우 파라미터가 String이나 MultipartFile이 아닌 경우 Converter나 PropertyEditor에 의해 처리 되지만 @RequestPart는 HttpMessageConverter를 이용하여 Content-type을 참고하여 처리한다는 점이다.

 

이때 하나의 요청 파라미터에만 대응한다고 해서 1개의 MultipartFile만 받을 수 있는게 아닌 List<MultipartFile>의 형태로도 받을 수 있으며

모든 파라미터를 Map<String, String>처럼 한 번에 받을 수 있으나 많은 데이터를 하나의 파라미터로 받는 것은 유지 보수성의 측면에서 좋지 못 하므로 많은 데이터를 주고받는 경우에는 @RequestBody와 DTO를 이용하는 편이 좋다.

 

사용 방법: 간단한 name-value 형태의 데이터를 주고받을 때 사용할 수 있으며 파라미터가 복잡해지는 경우 @RequestBody나 @RequestPart를 이용하여 DTO를 사용하는 것이 좋다.

 

@ModelAttribute

상술했듯이 Spring Controller에서 값을 받을때 default가 @ModelAttribute이며 다음과 같은 상황에 사용할 수 있다.

  • Content-type이 multipart/form-data의 형태를 받을때
  • HTTP 파라미터를 받는 경우

HTTP body로 오든 파라미터로 오든 다 받을 수 있고 body와 파라미터가 같이 오는 경우에도 값이 바인딩된다.

 

이런 형태가 가능한 이유는 @ModelAttribute는 필드 내부와 1:1로 값이 Setter나 Constructor를 통해 매핑되기 때문이다.

 

@RequestPart와 다른 점은 HttpMessageConverter에 의해 값이 바인딩되는 것이 아닌 적절한 Setter 혹은 Constructor를 통해 값이 주입된다는 점이다.

 

즉 해당 DTO의 필드에 접근할 수 있는 적절한 수단이 존재하지 않으면 값이 바인딩 될 수 없다.

 

HttpMessageConverter가 동작하는 @RequestPart나 @RequestBody의 경우 필드를 찾을때 ObjectMapper를 이용하고 이 ObjectMapper는 NoArgsConstructor와 Getter나 Setter 등을 통해 private field에 접근 할 수 있게 구현되어 있다.
이때 접근할 수 있는 이유는 Jackson 라이브러리는 Reflection을 통해서 private field에 값을 할당할 수 있기 때문이다.

ObjectMapper를 Override하면 어떤 접근자도 필요없게 만들 수도 있다!

 

정리

@RequestBody

application/json을 주고받을때 주로 사용함. multipart/form-data이 포함되는 경우는 사용 불가.

@RequestPart

@RequestBody + multipart/form-data인 경우에 사용. 

 

RequestBody와 RequestPart는 HttpMessageConverter에 의해 동작하므로 Setter 없이 Object 생성됨.

@RequestParam

1개의 HTTP 파라미터를 받을 때 사용. 

multipart/form-data을 받아야 되는 경우에 사용 가능.

기본 설정으로 필요 여부가 필수로 되어있음.

@ModelAttribute

@RequestPart와 유사하지만 동작 원리는 완전히 다르다.

값에 직접적으로 접근할 수 있는 수단이 필요.

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/07   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31
글 보관함