대용량 엑셀 다운로드 이슈 해결하기
18만 건의 대용량 엑셀 다운로드 시 발생하는 브라우저 OOM 문제를 Stream 처리와 비동기 작업으로 해결한 과정을 공유합니다.
고객이 엑셀 다운로드하려고 하는데 브라우저가 죽는다는 CS가 들어왔습니다.
확인 결과 DB에서 데이터를 읽어온 후 클라이언트 단에서 엑셀 파일을 생성하고 있었습니다. 기존에는 3만 건 이하의 데이터를 처리했는데, 이슈가 된 데이터 수는 18만 건이었습니다.
왜 브라우저가 죽는가?
XLSX 파일의 형식은 OOXML(Open Office XML)입니다. XLSX 파일은 여러 XML 파일을 포함하는 폴더를 압축한 형태입니다.
확장자를
.zip으로 변경 후 압축을 해제하면 내부 구조를 볼 수 있습니다.
row의 정보는 {sheetName}.xml 파일에 저장되는데 이 파일에는 필요한 정보 외에 XML 오버헤드도 많기 때문에 몇 만의 row 정보를 한 번에 메모리에 올리면 OOM이 발생합니다.
첫 번째 개선: 서버 사이드 Stream 처리
엑셀 다운로드 요청이 오면, 빈 엑셀 파일을 생성하고 DB에서 데이터를 Stream으로 읽어와 row 하나씩 엑셀 파일에 append합니다. 완료되면 클라우드 스토리지에 업로드 후 사용자에게 내려줍니다.
브라우저 OOM 문제는 해결됐지만, 데이터가 많아질수록 사용자 대기 시간이 길어지는 문제가 생겼어요.
두 번째 개선: 비동기 처리 도입
클라이언트에서 엑셀 파일 요청을 보내면 서버에선 대기열에 쌓아두고 Status 200으로 즉시 응답합니다. 서버에선 대기열에 쌓인 요청들을 백그라운드에서 처리합니다.
유저는 로딩화면을 계속 볼 필요없이 다른 작업을 하다가 엑셀 다운로드 페이지에서 생성된 엑셀을 다운로드하면 됩니다.
정리
아키텍처 변화:
1
2
3
4
5
6
7
8
[Before]
클라이언트 → DB 조회 → 클라이언트 엑셀 생성 (OOM 발생)
[After - 1단계]
클라이언트 → 서버 → DB Stream → 서버 엑셀 생성 → 클라우드 저장 → 다운로드
[After - 2단계]
클라이언트 → 서버 (즉시 응답) → Queue → 백그라운드 처리 → 다운로드 페이지
이 해결 방안은 소규모 사용자(10명 미만)를 위한 것입니다. 더 큰 규모라면 분산 작업 큐 시스템, 작업 우선순위 관리, 재시도 로직, 파일 자동 삭제 정책 등을 추가로 고려해야 해요.
참고 자료:



