사이트 개발을 진행하다 보면 가끔 한번씩 등장하게 되는 기능이 바로 "엑셀 다운로드" 기능이다.
엑셀 다운로드의 셀 병합 기능과 관련된 속도 이슈와 이를 개선했던 경험을 써보려고 한다.
EXCEL 라이브러리?
엑셀 업로드/다운로드 기능을 자바에서 사용하기 위해서는 대부분 POI 라이브러리를 사용하게 된다.
POI에서 제공하는 엑셀 라이브러리는 대표적으로 HSSF, XSSF, SXSSF가 있다(매번 발음하기 너무 어렵다)
사용방법이나 예제의 경우 인터넷에 많으니 구글 검색을 추천..
속도 이슈 발생기
기존에 회사 설문조사 결과를 엑셀로 다운로드 할 수 있는 기능이 있었는데
응답자 정보를 추가로 넣어 출력해주는 기능의 작업을 진행했었다.
그런데 기능 개선 이후 약 10달이 지난 시점, 설문 결과 다운로드를 누르면 502에러가 발생한다는 문의를 받게 된다.
실제 확인결과 응답자는 백여명 정도이고, 응답수 역시 천건 정도로 엄청난 양은 아니었지만
엑셀 다운로드시 30초 이상이 정도 소요되는 것을 확인하였다.
그러나 어디에서 속도 이슈가 발생한건지 확인하기 어려워 한 줄 한 줄의 실행 시간을 계산하기에 이르렀고,
addMergedRegion라는 메소드를 사용하는 부분에서의 속도 이슈를 확인할 수 있었다.
addMergedRegion의 경우 셀 병합을 하면서 이 셀을 병합할 수 있는지 없는지 유효 체크를 한다.
하지만 이 유효성 체크를 하는 부분의 소스코드를 보면 이중 for문을 실행하고 있다
당시 소스코드의 로직을 보면
설문 항목에 대한 for -> 설문 응답에 대한 for -> 응답자에 대한 for 총 3중 for문의 구조로 되어있었고,
3중 for문 내의 addMergedRegion를 사용하면서 총 5중 for문이라는 어마어마한 반복문을 사용하고 있었던 것이다.
셀 병합 자체는 큰 이슈가 안되지만 나의 경우 응답 갯수 곱하기 3 만큼 addMergedRegion를 호출하고 있었기 때문에
응답수가 많아질수록 속도 이슈가 발생할 수 밖에 없는 부분이었다.
셀 병합은 해야하는데, 이 어마어마한 반복문을 어떻게 해야할까 하는 고민중에 해당 메소드에서 해답을 찾을 수 있었다.
XSSFSHEET.class의 addMergedRegion 이라는 메소드를 확인해보면, 동일한 이름의 메소드를 return 하면서
두번째 매개변수로 true 값을 넘겨주고 있다.
addMergedRegion의 두번째 매개변수는 validate를 의미하는데, 해당 매개변수가 true인 경우 validateArrayFormulars 라는 메소드를 호출하게 되고, 이 메소드에 아까의 이중 for문이 위치하고 있다.
validate가 false인 경우 해당 메소드를 실행하지 않으므로 이중 for문을 피할 수 있게 되는 것!
즉, addMergedRegion의 두번째 매개변수가 false를 호출하는 메소드를 찾으면 해결이 되지 않을까?
그 메소드가 바로 addMergedRegion 아래에 있는 addMergedRegionUnsafe 이다
addMergedRegionUnsafe는 addMergedRegion에서 유효성 체크부분의 로직을 Skip 하는 메소드라고 설명이 되어있다.
addMergedRegion를 사용한 로직에서 셀 자체에 대해 유효성 체크가 불필요했기 때문에 해당 메소드를 모두 ~Unsafe로 변경하였고,
그 결과 5초 이내로 엑셀 다운로드 속도가 개선됨을 알 수 있었다.
(지금 생각해보니 굳이 셀 병합할게 아니라 그냥 셀 길이를 늘렸어도 되는데 하핫...)