실제 증상과 처리 흐름
CES 결과 다운로드는 여러 결과 파일을 임시 폴더로 복사한 뒤 ZIP으로 압축해 내려주는 흐름이었다. 파일 수가 늘어나면 다운로드 준비 시간이 크게 길어졌지만, 사용자에게 보이는 한 번의 요청 안에는 파일 조회, 복사, 압축, HTTP 전송이 함께 들어 있었다.
전체 응답시간만 보면 압축이나 네트워크가 느리다고 추측하기 쉽다. 그래서 먼저 처리 단계를 나누고 각 구간이 소비하는 시간을 확인했다.
- 다운로드 대상 파일 목록 확인
- 원본 파일을 임시 폴더로 복사
- 임시 폴더의 파일을 ZIP으로 압축
- 압축 결과를 HTTP 응답으로 전송
- 작업 후 임시 파일과 폴더 정리
병목을 파일 복사 구간으로 좁힌 근거
동일한 558개 파일을 기준으로 구간별 시간을 확인한 결과, 기존 FileInputStream·FileOutputStream 기반 복사에 160,556ms가 걸렸다. 우선 압축 알고리즘보다 파일 복사 경로를 개선 대상으로 정했다.
여기서 측정한 값은 사용자가 버튼을 누른 뒤 다운로드가 끝날 때까지의 시간이 아니다. 임시 폴더에 파일을 복사하는 구간만 분리해 측정한 결과다. 압축과 네트워크 전송을 포함하지 않았기 때문에 이 수치를 HTTP 전체 응답시간 개선으로 표현하지 않았다.
Java NIO 기반 복사 구조로 변경
주요 병목이었던 FileInputStream·FileOutputStream 기반 복사 구간을 Java NIO 기반 복사 구조로 변경했다. 개선 효과를 특정 API나 버퍼 크기 하나의 결과로 좁히지 않고, 기존 구현과 개선 구현의 복사 구조 전체를 비교했다.
중요한 변경 단위는 API 이름 하나가 아니라 기존 복사 루프와 개선된 NIO 기반 복사 구조 전체였다. 파일 선택 조건, 임시 경로 구성, 압축 대상 파일명과 다운로드 결과 계약은 유지하고 실제 I/O 구간을 교체했다.
병목 분석, NIO 전환, 같은 파일 집합을 이용한 성능 비교, 회귀 테스트와 운영 반영까지 직접 수행했다.
출력과 임시 파일 생명주기도 함께 정비
기존 처리 과정에는 System.out.println 중심의 출력이 섞여 있었다. 운영 환경에서 처리 단계와 실패 원인을 일관된 방식으로 추적할 수 있도록 애플리케이션 로깅으로 변경했다.
성능 개선과 함께 임시 파일 정리 순서도 점검했다. 복사나 압축 도중 예외가 발생하면 일부 파일이나 폴더가 남아 다음 작업과 디스크 사용량에 영향을 줄 수 있었다.
- 압축 성공 후 사용이 끝난 임시 파일을 정리한다.
- 복사 또는 압축 실패 시에도 생성된 임시 파일을 정리한다.
- 내부 파일을 제거한 뒤 임시 폴더를 삭제하도록 순서를 맞춘다.
- 정리 과정의 실패가 원래 복사·압축 실패 원인을 가리지 않도록 로그를 남긴다.
복사 속도만 빨라지고 예외 경로에 임시 리소스가 누적되는 변경은 운영 개선으로 볼 수 없기 때문에, 파일 생명주기를 같은 작업 범위에서 보완했다.
같은 파일 집합으로 개선 전후 비교
개선 전후 모두 동일한 558개 파일을 입력으로 사용하고 복사 구간을 비교했다.
- 대상 파일: 558개
- 개선 전: 160,556ms
- 개선 후: 714ms
- 개선 폭: 약 224배
약 224배는 특정 NIO API 하나의 순수 성능 효과를 뜻하지 않는다. 기존 Stream 기반 구현과 개선된 NIO 기반 구현 전체를 같은 파일 집합으로 비교한 결과다. 실행 환경의 캐시와 스토리지 상태도 측정에 영향을 줄 수 있으므로, 다른 서버나 파일 구성에서도 같은 배율이 재현된다고 일반화하지 않았다.
기능과 예외 경로 검증
- 558개 파일이 누락 없이 임시 폴더에 복사되는지 확인
- 파일명과 파일 내용이 기존 결과와 같은지 비교
- 압축 성공 후 임시 파일과 디렉터리 삭제 확인
- 복사 또는 압축 실패 시에도 정리 로직이 실행되는지 확인
- 운영 로그가 파일 처리 흐름을 추적할 수 있는 수준으로 남는지 확인
성능 측정만 통과시키지 않고 최종 ZIP의 파일 구성과 기존 다운로드 계약이 유지되는지 확인했다. 예외를 의도적으로 발생시키는 조건에서도 임시 파일과 폴더가 남지 않는지 함께 점검했다.
운영 반영 결과
동일한 558개 파일의 복사 시간이 160,556ms에서 714ms로 줄어 약 224배의 구간 성능 개선을 확인했다. 테스트와 운영 검증을 거쳐 2023.08.22 운영에 반영했다.
운영 반영 범위에는 NIO 기반 복사뿐 아니라 출력 로깅 변경과 압축 성공·실패 후 임시 리소스 정리가 포함됐다. 다만 확인된 정량 수치는 파일 복사 구간에 한정하며, ZIP 압축과 네트워크 전송까지 포함한 전체 응답시간 수치는 별도로 제시하지 않는다.
정리
파일 다운로드가 느릴 때 HTTP나 압축부터 바꾸기보다 처리 단계를 나눠 실제 병목을 측정해야 한다. 이 사례에서는 CES 결과 ZIP 생성 흐름에서 복사 구간을 분리하고, 동일한 558개 파일로 기존 구현과 NIO 기반 구현을 비교했다. 성능 수치의 범위를 명확히 제한하고 임시 파일 정리와 운영 로그까지 함께 보완한 것이 실제 운영 가능한 개선의 핵심이었다.