대용량 파일을 WAS에 직접 올려야 했던 비극 (feat. Chunk Upload)
대용량 파일을 WAS에 직접 올려야 했던 비극 (feat. Chunk Upload)
문제 상황
회사 프로젝트 중 2~6GB에 달하는 대용량 압축파일을 업로드해야 하는 상황이 있었다.하지만 적절한 인프라가 갖춰지지 않아, S3 같은 외부 저장소 없이 WAS(Web Application Server)에 직접 업로드해야만 했다.
시스템 구조
화면 → A 시스템(통합포탈 백엔드) → B 시스템(파일 업로드 처리 서버) → 외부 API
화면 -> B 시스템 ←→ 외부 API
: 직접 접근 시 문제 없음화면 → A 시스템 → B 시스템
: 대용량 업로드 시 통신 중단 발생
원인
화면 -> A 시스템의 WAS로 업로드하는 과정이 불안정했고, 특정 크기 이상에서 업로드가 중단되었다.
중간 시도 (실패한 해결책)
multipart.maxFileSize
,maxRequestSize
등 파일 크기 제한 조정connection timeout
,read timeout
등 네트워크 설정 조정- 톰캣 업로드 버퍼 설정 변경
-> 하지만 모두 일정 용량(수백 MB 이상)을 넘기면 실패.
-> 대용량 파일 자체가 WAS에서 안정적으로 처리되기 어려웠음.
해결: Chunk Upload 도입
클라이언트(프론트엔드)에서 파일을 500MB 단위로 청크 분할해 업로드하는 방식을 도입했다.
구현 방식 요약
- 프론트에서
File.slice()
API로 파일 분할 - 동일 API에 청크별로 반복 전송 (
chunkNumber
,totalChunks
전달) - 서버에서는 각 청크를 임시 디렉토리에 저장
- 마지막 청크가 도착하면 파일을 병합 후 외부 API 전송
고려했던 세부 포인트
1. API 호출 횟수 최소화
- 기존 로직: 파일 업로드 + 상태 조회 + 외부 API 요청 1회 요청
- 청크 방식: 불필요한 (심지어 실패하는) 외부 API 다중 요청 발생 위험
- 해결책:
chunkNumber == 0
일 때만 외부 API 상태 조회 요청 수행
2. 업로드 실패 대비 & 자원 정리
업로드 중단이나 실패 시 임시 파일 정리 기준을 명확히 정의
- 청크 도중 네트워크 중단
- 외부 API 전송 실패
- 검증 완료(성공/실패)
- 애플리케이션 종료 (
@PreDestroy
or Shutdown hook)
실제 당시 메모했던 고민들
아래는 개발 도중 실제로 내가 작성한 주석이다. 문제를 파악하고 해결책을 고민하는 흐름이 그대로 담겨 있다. 그 때의 고통이 느껴져서 가져왔다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/*
* 지금 고민
* - 배경: 포탈 시스템에서는 멀티파트 파일이 WAS에 업로드 되지만,
* 중간 시스템을 통하면 알 수 없는 이유로 통신이 멈춤
* → 그래서 파일을 500MB씩 청킹해서 통신을 여러 번 하려고 함.
*
* - 문제: 기존 로직은, 성능 검증을 요청할 때
* 파일 업로드와 상태 조회, 성능 검증 시작을 모두 하나의 요청에서 수행함
* → 청킹으로 바꾸면 동일 API를 여러 번 호출해야 함
* → 그러면 파일이 다 올라갔을 때 상태 조회를 해야 하나?
* → 하지만 그렇게 하면 사용자는 대기 시간이 너무 김
*
* - 해결: chunkNumber가 0일 때만 상태 조회 요청
*
* - 예외 처리: 청킹 하다가 중단되면?
* → 서버에 남은 임시 파일 정리 필요
*
* 파일을 지워야 하는 경우
* - 청킹이 의도치 않게 중단된 경우
* - 성능 검증 요청이 완료된 경우(성공/실패)
* - 애플리케이션 종료 시
*/
회고 및 정리
- WAS에 직접 대용량 파일을 업로드하는 건 마지막 수단이어야 한다.
- 가능하다면 S3, FTP 등 외부 저장소를 사용하는 게 훨씬 안정적이다.
- Chunk Upload는 구현이 까다롭지만, 현실적인 제약 하에서는 좋은 해결책이 될 수 있다.
- 특히, 예외 상황에 대한 처리와 리소스 정리 정책은 반드시 함께 고려해야 한다.
This post is licensed under CC BY 4.0 by the author.