단일 이미지 파일을 Spring Boot에서 Python(FastAPI)으로 넘겨 JSON 응답을 받아오는 데 성공했다. 하지만 기쁨도 잠시, 실무 환경을 가정해 보니 새로운 의문이 들었다.
당근마켓이나 인스타그램처럼 사용자가 한 번에 수십 장의 사진을 업로드하는 상황을 가정해 보았다. 고화질 사진 50장을 한 번에 서버로 던진다면 어떻게 될까?
테스트 결과, 컨트롤러 로직이 실행되기도 전에 톰캣(Tomcat) 단에서 에러를 뱉어내며 입구컷을 당했다.
413 Content Too Large
1. 원인 파악: Spring Boot의 방패
스프링 부트는 악의적인 대용량 파일 공격을 막기 위해 기본 파일 업로드 제한을 아주 보수적인 '1MB'로 설정해 둔다. 요즘 스마트폰 사진 한 장이 2~3MB를 가뿐히 넘기기 때문에, 이 설정을 바꾸지 않으면 다중 업로드는커녕 단일 업로드도 실패할 수밖에 없다.
2. 꼬리를 무는 의문: 무작정 500MB로 늘리면 안전할까?
그렇다면 설정 파일에서 제한 용량을 500MB 정도로 뚫어주면 해결될까? 여기서 아키텍처에 대한 찝찝함이 밀려왔다.
위 고민들을 바탕으로, 안전하고 효율적인 다중 파일 업로드 처리 전략을 3단계로 도출했다.
Step 1. Spring Boot 설정 변경
먼저 application.properties에서 1MB 제한을 현실적으로 풀어준다. 이때 파일 1개당 크기와, 요청 1번당 총크기를 다르게 설정하는 것이 핵심이다.
# 파일 1개당 최대 크기 (단건 제한)
spring.servlet.multipart.max-file-size=10MB
# 요청 1번에 담길 수 있는 전체 크기 (총합 제한)
spring.servlet.multipart.max-request-size=500MB
Step 2. Controller 파라미터 수정
단일 객체로 받던 파라미터를 자바의 List 자료구조로 변경하여 여러 장을 줄줄이 엮어 받을 준비를 한다.
@PostMapping("/upload-images")
public String uploadImages(@RequestParam("files") List<MultipartFile> files) {
for (MultipartFile file : files) {
// 파일을 하나씩 꺼내어 파이썬으로 순차 전송
}
return "다중 업로드 성공";
}
Step 3. 궁극적인 해결책: 프론트엔드 분할 전송
가장 중요한 포인트다. 500MB를 한 번의 POST 요청으로 통째로 보내는 짓은 하지 않기로 했다. 프론트엔드 개발자와 협의하여 사용자가 50장을 고르더라도 내부적으로는 1장씩 서버로 50번 던지도록(분할 전송) 아키텍처를 잡아야 한다.
이렇게 하면 우리가 흔히 보는 "업로드 중... 10% ➔ 20% ➔ 100%" 같은 진행률 바를 구현할 수 있고, 무거운 파이썬 AI 모델도 한 번에 하나씩 차분하게 이미지를 분석할 수 있어 서버 다운의 위험을 원천 차단할 수 있다.
단순한 기능 구현을 넘어, 시스템의 안정성까지 챙기는 의미 있는 트러블슈팅이었다.