2 분 소요

프로젝트에서 파일 업로드 기능을 구현해야 했는데, 이 에러가 참 많이 속을 썩였다.
javascript에서는 FormData에 file을 포함한 텍스트 data를 함께 넘겨주고 있었고, spring에서는 controller에서 FormData를 받아 처리하고 있었다.

let formData = new FormData();
/* formData.append()로 넘길 data 포함 시켜줌 */

$.ajax({
        type: "post",
        url: "/api/upload/",
        data : formData,
        contentType : false,
        processData : false
    }).done(res => {
        console.log("[post 업로드] 전송 성공", res);
    }).fail(error => {
        console.log("[post 업로드] 불러오기 오류", error); // 계속 여기만 표시됐다!
    });
@PostMapping("/upload")
public ResponseEntity<?> uploadPost(@RequestParam("uploadText") String text,
                                    @RequestParam("uploadTag") String tag,
                                    @RequestParam("uploadImgUrl") MultipartFile file,
                                    @AuthenticationPrincipal PrincipalDetails principalDetails) {
    /* 생략 */
    return new ResponseEntity<>("업로드 성공", HttpStatus.OK);
}


사실은 이번에 파일 업로드 기능 구현을 처음부터 막 시작하던 와중에 뜬 에러는 아니다. 이전에 여러 번의 삽질끝에 구현을 마치고 다른 내용을 고치던 찰나에 어쩌다 테스트 해봤는데, 갑자기 업로드한 파일 정보가 나오질 않는 거였다. 위 javascript 코드에서 ajax request가 시작되기 전에 formData.get("uploadImgUrl")을 콘솔에 찍어서 확인했을 땐 정상적인 정보가 들어갔었고 희한하게도 ajax request 코드로 넘어가자 마자 fail()로 넘어가서 [post 업로드] 불러오기 오류를 출력해댔다.

Spring org.springframework.web.multipart.support.MissingServletRequestPartException, Required request part 'uploadImgUrl' is not present


출력된 오류 내용대로, uploadImgUrl로 넘어오는 파라미터가 계속 null인걸 확인할 수 있었고(@RequestParam에서 required = false로 체크했음) text, tag에는 정상적인 정보가 들어오는걸 확인할 수 있었다. 다 같은 formData를 타고 넘어오는 건데 저건 되고 왜 저건 안될까?
검색해보니 다양한 해결 방법들이 존재했는데, 나같은 경우 application.yml에서 다음 설정을 최근에 해둔 적이 있었다.

# application.yml
spring:
  mvc:
    hiddenmethod:
      filter:
        enabled: true


회원탈퇴 기능을 구현하면서 repository에 구현해뒀던 delete 쿼리를 날렸는데 계속 삭제가 되질 않아 찾았던 해결책이었다.
분명 DELETE 쿼리를 날렸는데 에러에는 POST 신호로 잡히는 모양이었고 그걸 해소해주는 코드였던 걸로 기억한다.
controller에 정의해둔 함수는 @DeleteMapping을 적용했는데 POST request만 계속 들어오니 오류를 뱉어냈었고
이걸 적용하고 나니 당장 회원탈퇴 기능을 구현하는 데는 괜찮았지만, 이걸 쓰고나서 MultipartFile 파라미터 값이 계속
null로 들어왔다😐

// 이전에 겪었던 에러
there was an unexpected error (type=method not allowed status=405).
Resolved [org.springframework.web.HttpRequestMethodNotSupportedException: Request method 'POST' not supported]

임시 해결

놀랍게도.. DELETE API는 동작하는데 문제가 없어서 업로드 기능을 살리기 위해 위에서 설정한 application.yml 코드를 주석 처리했다. 그리고 회원탈퇴 기능은 js에서 ajax request로 DELETE API를 호출해 처리하도록 했다😁
(즉, API controller만 거침)

function deleteUser(userId) {
    $.ajax({
        type: "delete",
        url: "/api/user/delete/" + userId,
    }).done(res => {
        console.log("[회원탈퇴] 성공");
    }).fail(error => {
        console.log("[회원탈퇴] 실패", error);
    });
}


정확한 이유가 뭔지는 모르겠지만, 위에서 application.yml에 설정한 내용과 ajax request와 충돌이 있는 것 같다.
controller에서 @DeleteMapping(또는 @PutMapping)을 쓸 수 있다는건 확실히 좋게 다가올 수 있을 것 같은데 아쉽다.
MultipartFile 앞에 적은 @RequestParam@RequestPart로 바꾸면 해결된다는 답변도 본적이 있으니 이 에러때문에
잠을 못자는 분들은 적용해봐도 좋을 것 같다. 나는 해당되지 않았다..😑

카테고리:

업데이트:

댓글남기기