대용량 엑셀 다운로드 요청을 안정적으로 처리하는 방법
대용량 엑셀 다운로드 기능은 처음에는 단순해 보인다. 조회 쿼리를 실행하고, 결과를 엑셀 파일로 만든 뒤, 응답으로 내려주면 끝이기 때문이다. 하지만 사용자 수가 늘고 다운로드 대상 건수가 커지면 이 기능은 API 서버, DB, 스토리지 모두를 압박하는 고비용 작업으로 바뀐다.
특히 다음 조건이 겹치면 문제가 빠르게 드러난다.
- 같은 사용자가 같은 조건으로 반복 다운로드를 시도한다.
- 한 번의 다운로드에 수만 건 이상이 포함된다.
- 엑셀 생성 중 메모리 사용량이 급격히 증가한다.
- 생성이 끝날 때까지 HTTP 요청을 붙잡고 있다.
이 글에서는 이런 상황에서 엑셀 다운로드를 어떻게 안정적으로 운영할 수 있는지 정리한다.
왜 동기 처리만으로는 버티기 어려운가
동기 방식의 가장 큰 문제는 요청 하나가 너무 많은 책임을 가진다는 점이다.
- 요청 검증
- 대량 데이터 조회
- 엑셀 파일 생성
- 파일 저장
- 사용자 응답
이 구조에서는 다음과 같은 현상이 반복된다.
- 긴 요청 시간으로 인한 타임아웃
- 메모리 사용량 급증
- 동일 요청 중복 수행
- 다운로드 처리 때문에 일반 API 응답 저하
문제는 엑셀 다운로드가 “중요한 기능”이면서도 “즉시 응답이 꼭 필요하지는 않은 작업”이라는 데 있다. 따라서 요청 처리와 파일 생성을 분리하는 것이 핵심이다.
기본 방향: 요청과 생성을 분리한다
가장 먼저 해야 할 일은 다운로드 요청을 파일 생성 작업과 분리하는 것이다.
- 사용자는 다운로드를 요청한다.
- 서버는 요청을 접수하고 작업 ID를 반환한다.
- 실제 파일 생성은 비동기 워커가 처리한다.
- 사용자는 상태 조회나 완료 알림으로 결과를 확인한다.
이 구조로 바꾸면 API 서버는 긴 엑셀 생성 작업을 직접 수행하지 않아도 된다.
중복 요청을 막는 기준이 필요하다
대용량 엑셀 다운로드에서 흔한 문제는 같은 요청이 여러 번 들어오는 것이다.
예:
- 같은 사용자가 버튼을 여러 번 클릭
- 브라우저 재시도
- 네트워크 지연으로 인한 중복 호출
이때 요청을 식별할 수 있는 키가 필요하다. 보통은 다음 조합이 유효하다.
1
userId + exportType + normalizedFilterHash
필터를 정규화한 뒤 해시를 만들면 “실질적으로 같은 요청”을 같은 작업으로 묶을 수 있다.
상태 테이블을 두는 이유
비동기화 이후에는 작업 상태를 추적할 저장소가 필요하다.
예를 들어 이런 형태가 유용하다.
1
2
3
4
5
6
7
8
9
excel_export_requests
- id
- requester_id
- request_hash
- status
- result_file_path
- error_message
- created_at
- updated_at
상태는 보통 다음 정도로 나눈다.
REQUESTEDPROCESSINGCOMPLETEDFAILED
이 테이블이 있으면 다음이 가능해진다.
- 중복 요청 차단
- 실패한 작업 재시도
- 오래 걸리는 요청 모니터링
- 운영 중 장애 원인 추적
락은 어디에 써야 하나
동일 조건의 다운로드가 동시에 실행되지 않게 하려면 분산 락이 유용하다. Redis를 사용한다면 다음처럼 생각할 수 있다.
1
lock key = export:{request_hash}
락의 목적은 단순하다.
- 같은 요청이 두 번 생성되지 않게 한다.
- 이미 처리 중인 요청이 있으면 기존 상태를 반환한다.
중요한 점은 락 자체보다 락과 상태 테이블을 같이 사용해야 한다는 것이다. 락만으로는 완료 결과나 실패 이력을 설명할 수 없기 때문이다.
파일 저장은 응답 본문이 아니라 외부 스토리지로
파일이 크다면 생성 후 바로 HTTP 응답으로 흘려보내는 구조보다 외부 스토리지에 저장하는 쪽이 안정적이다.
예를 들면:
- 워커가 엑셀 파일 생성
- S3 같은 스토리지에 업로드
- 사용자에게 presigned URL 제공
이 방식의 장점은 다음과 같다.
- 웹 서버 메모리 점유 감소
- 다운로드 재시도 비용 절감
- 만료 시간 제어 가능
- 같은 파일 재사용 가능
생성 비용을 줄이는 실무 포인트
엑셀 다운로드는 애플리케이션 로직보다 라이브러리 사용 방식에서 병목이 생기는 경우가 많다.
실무에서 주의할 지점:
- 전체 데이터를 한 번에 메모리에 올리지 않는다.
- 스트리밍 기반 워크북 API를 사용한다.
- 셀 스타일 객체를 반복 생성하지 않는다.
- 문자열, 포맷, 헤더를 재사용한다.
- 대량 데이터는 조회 자체도 청크 단위로 나눈다.
엑셀 생성 라이브러리를 쓴다면 메모리 사용량과 임시 파일 사용 방식을 반드시 확인해야 한다.
어느 시점에 비동기 전환이 필요한가
다음 중 하나라도 만족하면 동기 다운로드를 유지하기 어렵다.
- 다운로드 건수가 크다.
- 평균 생성 시간이 수 초를 넘는다.
- 같은 조건의 반복 요청이 잦다.
- 피크 시간대에 서버 부하가 눈에 띄게 상승한다.
즉, 비동기화는 “아주 큰 시스템에서만 필요한 최적화”가 아니라, 비용이 큰 작업을 운영 가능한 형태로 바꾸는 구조 개선이다.
정리
대용량 엑셀 다운로드를 안정적으로 운영하려면 핵심은 세 가지다.
- 요청과 파일 생성을 분리한다.
- 요청 해시와 상태 테이블로 중복을 통제한다.
- 결과 파일은 외부 스토리지에 저장해 재사용한다.
엑셀 다운로드는 단순한 부가기능처럼 보이지만, 실제로는 대량 조회, 파일 생성, 장기 실행, 중복 요청이라는 문제를 한 번에 품고 있다. 그래서 기능 자체보다 운영 구조를 어떻게 설계하느냐가 더 중요하다.
댓글
아직 댓글이 없습니다