@RequestPart란?
@RequestPart는 @RequestParam과 마찬가지로 String, form, multipart데이터를 받지만, JSON, multipart 복잡한 데이터를 받는데 주로 사용된다.
@RequestParam VS @RequestPart VS @ ReqeustBody
그럼 차이점이 무엇일까? 이 세가지 어노테이션을 비교해보며 ReqeustPart에대해 알아보자.
@RequestParam과 @RequestPart는 둘 다 파라메터를 받는데서 사용한다. String, from, Multipart 데이터를 받을 수 있다.
@RequestBody는 바디에 있는 데이터를 꺼내는 역할을 한다.
@RequestBody
post등의 방식으로 body에 데이터를 넣어주었을 때만 사용한다. body에 데이터를 넣는 방식이 아닌데 @RequestBody를 사용하려고 하면 415등의 에러가 날 수 있다.
따라서 FormData를 @RequestBody로 받으면 오류가 나고, JSON데이터를 body에 보내서 받으면 정상 작동한다.
@RequestParam
등록된 Converter또는 PropertyEditor로 변환을 시도한다.
* Spring은 데이터 바인딩을 위해 Converter, PropertyEditor, Formatter를 제공한다.
데이터 바인딩하는 예시를 들어보자.
VO의 구조가 아래와 같이 매핑되기를 원한다고 하자.
InsSymbolVO = {symbNm: "test2", symbType: "04"}
//getter
//setter
//pseudocode
public ResponseEntity<ResVO<Void>> insSymbol(@RequestParam InsSymbolVO param,
@RequestParam List<MultipartFile> images)
fornt에서는 form의 형식으로 보냈다.
const fileEle = document.querySelector("#file");
//form데이터 만들기
const formData = new FormData();
formData.append("param", JSON.stringify({symbNm: "test2", symbType: "04"}));
for(const file of fileEle.files) {
formData.append("images", file);
}
//전송
const response = await axios.post("/symbol/insert", formData, {
headers: { 'Content-Type': "multipart/form-data"},
});
JSON데이터를 @Requestparam VO로 받으면, string으로 VO를 파싱할 수 없다는 오류가 뜬다.
@RequestParam은 key-value를 기반으로 데이터를 매핑하기 때문에 param이라는 key에 매핑되는 데이터(JSON형식인) string을 InsSymblVO에 매핑하려고 하니 에러가 나는 것이다.
따라서 InsSymblVO대신 String으로 받으면 매핑이 된다. 물론 Gson등의 라이브러리로 string을 json으로 변환해줘야 하는 불편함이 생긴다.
public ResponseEntity<ResVO<Void>> insSymbol(String param,
@RequestParam List<MultipartFile> images)
* @RequestParam으로 받고싶으면, key를 맞춰줘야하므로 form에 JSON을 통째로 넣지 말고 sysmbNm, symbType을 쪼개서 넣고, 쪼개서 받아야 한다.
const fileEle = document.querySelector("#file");
//form데이터 만들기
const formData = new FormData();
formData.append("symbNm", "test2");
formData.append("symbType", "04");
for(const file of fileEle.files) {
formData.append("images", file);
}
//전송
const response = await axios.post("/symbol/insert", formData, {
headers: { 'Content-Type': "multipart/form-data"},
});
public ResponseEntity<ResVO<Void>> insSymbol(@RequestParam String symbNm,
@RequestParam String symbType,
@RequestParam List<MultipartFile> images)
*또는 (프론트를 위처럼 쪼개서 보내고) 아예 @RequestParamd을 쓰지 않아도 된다.
public ResponseEntity<ResVO<Void>> insSymbol(InsSymbolVO param,
@RequestParam List<MultipartFile> images)
보내는 형식이 FormData(QueryString)일 때는 아무 어노테이션 없이 VO만 있어도 데이터가 바인딩된다. VO의 getter, setter를 이용하여 spring에 내장되어있는 jackson이 알아서 데이터를 매핑해주기 때문이다. 단, 보내는 데이터 형식이 JSON인 경우 @RequestBody등 어노테이션이 있어야 매핑된다.
@RequestPart
요청 헤더의 Content-Type에 해당하는 HttpMessageConverter로 변환을 시도한다.
JSON, XML과 Multipart데이터를 함께 받을 때(복잡한 데이터) 사용된다.
예를들어 위의 VO를 아래와 같이 받을 수 있다.
public ResponseEntity<ResVO<Void>> insSymbol(InsSymbolVO param,
@RequestPart List<MultipartFile> images)
내부적으로 작동하는 방식은 아마 다르겠지만, 겉으로 보기에는 @RequestParam과 똑같이 사용할 수 있다.
@ReuqestParam과 다른점이라는 JSON을 매핑할 수 있다는 것이다.
@RequestPart로는 JSON데이터를 쪼개지 않고도 받을 수 있다.
다만, JSON는 application/json으로, 이미지는 multipart로 mime type을 설정해 주어야 한다.
const fileEle = document.querySelector("#file");
//form데이터 만들기
const formData = new FormData();
const data = {symbNm: "test2", symbType: "04"};
formData.append("param", new Blob([JSON.stringify(data)], {type: "application/json"}));
for(const file of fileEle.files) {
formData.append("images", file);
}
//전송
const response = await axios.post("/symbol/insert", formData, {
headers: { 'Content-Type': "multipart/form-data"},
});
public ResponseEntity<ResVO<Void>> insSymbol(@RequestPart InsSymbolVO param,
@RequestPart List<MultipartFile> images)
사실 이 문제는 Postman에서 formdata를 보낼때 contentType을 key마다 부여해서 보내는 것을 보고 의문을 가지고 파헤치게 되었다.
어떻게 이렇게 보낼 수 있는거지? 했는데, 위에 설명했듯이 JSON의 경우 Blob으로 만들어서 content type을 지정해 준 것이다.
@RequestParam에 대한 참고
https://wouldyou.tistory.com/89#%40ResponseBody-1
https://velog.io/@rudwnd33/TIL-11%EC%9B%94-27%EC%9D%BC
https://haenny.tistory.com/302
'Spring' 카테고리의 다른 글
[spring] swagger-fox 연동하기 (0) | 2023.08.04 |
---|---|
[springboot] ApplicationPidFileWriter 란? (0) | 2023.08.03 |
[spring] spring scheduler vs quartz scheduler (0) | 2023.06.29 |
[spring] @RequestBody @ResquestParam 등 정리 (0) | 2022.10.31 |
[spring] (1) springboot, mysql, mybatis 연결, DB에서 데이터가져오기 (5) | 2022.10.20 |