날이 점점 풀려가지만 오늘도 나의 코드는 꼬여간다.
분명 POSTMAN 호출은 문제 없이 잘 작동하는 아주 평화로운 API 였다.
이미지와 JSON 형식으로 string이 들어간다.
그런데 오잉 프론트에서 계속해서 415에러를 뱉어내는게 아닌가???
참을 수 없는 나는 415에러를 먼저 검색해봤다.
contentType 을 확인 해주면 됩니다. ajax와 controller의 contentType이 맞지 않는 경우 발생 됩니다. 경우 데이터가 정상적으로 전달 되지 않아 에러가 발생 될 수 있습니다.
흠 그렇군. 백엔드 controller에서 내가 생각한 multipart/form-data로 넘어가지 않는 듯 했다.
그래서 한번 backend 로그를 살펴보았다.
2022-03-25 14:11:21.496 WARN 1 --- [io-8080-exec-10] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.web.HttpMediaTypeNotSupportedException: Content type 'application/octet-stream' not supported]
이번에도 처음 보는 Content type이 있었다.
옥텟 스트림은 이름에서처럼 8비트 단위의 바이너리 데이터를 의미합니다.
특별히 표현할 수 있는 프로그램이 존재하지 않는 데이터의 경우 기본값으로 octet-stream을 사용합니다.
Content-Disposition 헤더를 attachment 로 줌으로써 해당 데이터를 수신받은 브라우저가 파일을 저장 또는 다른이름으로 저장 여부를 설정하게 할 수 있습니다.
그러나 모든 데이터에 대해 octet-stream 타입을 남용하는 것은 권장하지 않습니다.
출처: https://dololak.tistory.com/130 [코끼리를 냉장고에 넣는 방법]
아아 그렇구나..!
멀티파트 form-data의 경우 다음과 같이 HTML의 form 태그 안에서 post 와 같은 방식으로 여러가지 데이터를 함께 묶어 전송하는 경우 사용된다고 한다.
아마 내 코드에서 header에 명세를 해주었지만 formdata에 이미지와 json을 append 하는 과정에서 올바르지 못하게 들어간 것 같다.
formdata형식의 value는 무조건 스트링으로 변환된다.
blob객체와 텍스트 형식 데이터만 append할 수 있는 것 같다. (File도 blob객체에 속합)
그렇기에 formdata 타입으로 json타입 데이터를 보낼 때에는 blob함수로 감싸고, 두번째 인자로type: 'application/json'을 같이 넣어줘야 한다.
backend 에선 .json 으로 dto를 받았는데 react에선 JSON.stringify를 통해 javascript object를 생성해서 보내니깐 415 에러가 발생 했던 것이다.
JSON.stringify를 통해 javascript object를 생성하고 blob 객체의 타입을 application/json으로 만들어서 formdata에 append 하면된다.
이러면 안됩니다. 💩
fd.append("dto", JSON.stringify(inputs);
이렇게 하셔야죠 ✨
const json = JSON.stringify(inputs);
const blob = new Blob([json], { type: "application/json" });
fd.append("dto", blob);
const blob = new Blob([json], { type: "application/json" });
전 프로젝트는 이걸 안써도 이상 없었는데...
좀 더 확인해 봐야 겠네요... 무슨 차이였는지...
좋은 정보 감사합니다!!