새로운 서버를 구축하는 과정에서 file upload 중 발생한 에러를 해결한 과정을 정리해보려고 합니다.
문제상황
이전 프로젝트(Photosend)
에서 구축한 Server에는 File Upload
가 문제없이 이루어지는 반면, 새로 구축한 Server(TourCash)
에서는 File Upload
시 Server측에서, File을 핸들러의 parameter로 맵핑하지 못하는 에러가 발생했습니다.
환경
저의 개발 환경은 다음과 같았습니다. Photosend(이전 프로젝트) 와 Tourcash(현재 프로젝트)의 환경은 동일한 기술스택을 이용하여 구축하였습니다.
Server
- Spring Boot
Front
- React-Native
Infra
- AWS 사용(ec2, s3)
에러원인 추측 및 해결과정
제가 생각한 에러의 원인은 크게 아래와 같이 4가지로 나뉘었습니다.
1. Front 코드
1.1 첫번째 시도(이전 프로젝트를 참고하여 코드를 구성)
처음은 우선, 기존 서버에 대응하는 프론트측의 코드를 다시한번 참고하여, 현재 프로덕트의 프론트코드를 고쳤습니다.
위와 같이 "stream ended unexpectedly" 라는 에러가 발생했습니다. 구글링을 해보아도 정확한 답변은 보이지 않았습니다. 추측을 통해 이것저것 변경하며 테스트를 하는 수 밖에없었습니다.
1.2 두번째 시도(header Content-Type:multipart/form-data 명시)
보통 타입이 잘못된경우, Spring에서 Error Message를 띄워주기는 하지만, Http Post 요청에 담길 Content의 Type이 파일이거나, 2가지 이상의 종류의 데이터가 포함되는 경우, 이 두개의 파일의 경계를 구분하기 위해, Content-Type이
따라서 위와같이 Content-Type에 multipart/form-data
을 명시해주었습니다.
1.3 세번째 시도(프론트 코드를 완전히 동일하게 하여 서로다른 서버에 요청)
하지만 이번에는 Rquired request part "file"이 존재하지 않는다는 에러가 발견되었습니다.
하지만, 분명히, formdata에는,
하지만, 분명히, formdata에는, file
을 키로하는 image가 포함되어있었고, console창에 image역시 잘 출력이 되었습니다.
이번에는 완전히 동일한 front 코드가 문제인지를 파악하기 위해서 완전히 동일한 코드로 서로다른 서버에 요청을 해봐야겠다는 생각이 들었습니다.
정상작동하는 이전 프로젝트 서버(Photosend), 그리고 현재 문제가 있는 프로젝트의 서버(TourCash)에 위 그림과 같이 테스트를 위해 목적에 딱 맞는, 다른 생각을 할 필요가 없는 핸들러를 만들었습니다.
정상작동하는 이전 프로젝트 서버(Photosend), 그리고 현재 문제가 있는 프로젝트의 서버(TourCash)에 위 그림과 같이 테스트를 위해 목적에 딱 맞는, 다른 생각을 할 필요가 없는 핸들러를 만들었습니다.
서로 다른 서버에 같은 프론트 코드로 요청한 결과, 이전 프로젝트 서버에서는 정상적으로 파일의 이름이 출력되었고, 현재 문제의 서버에서는 같은 오류가 발생했습니다.
서로 다른 서버에 같은 프론트 코드로 요청한 결과, 이전 프로젝트 서버에서는 정상적으로 파일의 이름이 출력되었고, 현재 문제의 서버에서는 같은 오류가 발생했습니다.
2. Server 코드
그렇다면, Server측의 코드가 달라서 발생하는 문제가 아닐까요?
하지만, 앞서 마지막 세번째 시도에서, 서로다른 서버에 똑같은 핸들러의 코드를 작성하여 배포했었던것을 미루어보아, 서버의 코드가 달라 발생하는 문제는 아닐것 같습니다.
3. Server 설정
추측해볼 수 Server 설정중 문제가 될만한 부분은, Formatter
입니다. (Formatter는 String -> Object
그리고 그반대의 데이터 바인딩을 수행해주는 역할을 합니다.)
하지만, 1.3
에서 제가 작성한 핸들러에서는, Spring Boot에서 기본으로 제공하는 MultipartResolver
가 사용되기 때문에 이전 프로젝트에서 생성한 어떠한 formatter도 간섭하지 않음을 알 수 있습니다.
4. Ec2 Server
마지막으로 생각해볼 수 있는 문제는, Ec2 Server문제입니다.
때문에, 이전 프로젝트와 완전히 같은 서버를 구축해 보았습니다. (ios ,android 는 서버가 https 즉, ssl 설정이 되어있지 않은 경우, 요청자체가 불가능하기 때문에, ssl역시 재발급 받아 설정을 해주어야 했습니다.)
하지만, 이역시도 문제의 원인이 아니였습니다.
해결
울며 겨자먹기로, 마지막으로 이전 프로젝트와 현재 프로젝트의 서버의 문제가 될만한 설정이 다른 부분들을 샅샅이 살펴보았습니다.
문제가 될만한 부분들은 다음과 같았습니다.
- Spring Configruration Class : 직접 설정한 클래스 파일의 문제.
- Build.gradle : Spring 동작시 사용되는 빈들의 문제가 원인이 될수도 있음.
- application.yml : Spring 관련 설정 문제가 될수도 있음.
이전 프로젝트의 Spring Boot version
문제의 현재 프로젝트 Spring Boot version
앞서 가정한 문제가 될만한 설정파일들을 찾던 도중 이전 프로젝트와 현재 프로젝트에서 다른 한 부분을 발견했고, 그것은 Spring boot의 버전이었습니다.
!!!!!!!!!!!!!
spring boot version을 2.2.4로 내린뒤 테스트하니 다음과 같이 성공했습니다.
혹시나 해서, spring boot 2.2.5 file upload error를 검색해보니, 저와 같은 문제가 있던 단한사람이 있었습니다.
Spring boot 2.2.6에서 해결이 되었다고 합니다....
'FrameWork > Spring Boot' 카테고리의 다른 글
Spring Boot - rest docs 사용방법과 자동 목차생성(spring boot restdocs 설정) (2) | 2020.06.03 |
---|---|
Spring Boot - 스프링 부트 통합테스트 방법과 팁(Spring boot Integration Test) (2) | 2020.05.29 |
Spring Boot - Custom Validator를 생성해야하는 경우와 생성방법(Collection 검증) (0) | 2020.04.10 |
Spring Boot - 한글, 한자 인코딩(Encoding) 에러시 체크리스트! (0) | 2020.01.17 |
Spring Boot - resourceLoader가 jar에 포함된 File을 찾지 못하는 에러(classPath 사용시 발생) (0) | 2020.01.08 |