Backend

[SpringBoot] Apache Poi를 이용한 엑셀다운로드는 SXSSF를 쓰자..!

연_우리 2022. 12. 3. 00:07
반응형

목차

     

     

     

    에러 발생!!!!!!!!!!!!

     

    https://lotuus.tistory.com/145

     

    [SpringBoot] Apache Poi를 이용한 엑셀 다운로드 구현

    목차 통계 API를 만들다보면 화면에도 값을 보여주어야하고, 엑셀 다운로드도 가능해야합니다 ㅎㅎ 대표적으로 사용되는 Apache Poi를 이용하여 엑셀 다운로드를 구현해보겠습니당! 예제 UserPoint En

    lotuus.tistory.com

     

    예전에도 엑셀다운로드 게시글을 올렸었는데, 

    운영에서 갑자기 힙메모리가 부족하다며 Out Of Memory 에러가 발생했다.....

    이유는 두가지였다

     

     

     

    첫번째 ) 요청 중복 필터링 안함

    화면에 보이는 엑셀 다운로드 버튼을 누르고, 실제 다운로드 창이 뜰때까지는 시간이 좀 걸린다

    그런데 참을성 없는 분들이 기다리지 않고(사실 그렇게 오래 걸리지도 않는다...고 생ㄱ가한다 ㅜㅜㅜ)

    여러번 계속 중복해서 엑셀 다운로드 버튼을 클릭했었다

     

    프론트에서도 중복 클릭 방지가 없고.. 백엔드에서도 중복 클릭을 필터링하지 않았기 때문에

    요청이 들어오는대로 엑셀파일을 만들기 위해 서버에서 엄청난 메모리를 잡아먹고 있던것이였고

    결국 Out Of Memory가 발생하게되었다!

     

     

     

     

    두번째 ) XSSF 구현체를 선택하여 엑셀 파일 생성함

    - XSSF는 메모리에 파일데이터를 쌓아두고 다운로드하는 방식
    - SXSSF는 임시파일을 중간중간 생성하여 메모리를 적게 사용하는 방식

    (위의 차이점을 일찍 알았더라면 Out Of Memory 발생빈도가 줄지 않았을까...? 눈물...)

     

    XSSF를 사용하여 엑셀다운로드를 구현해놨는데

    첫번째 요인이 겹치면서 다운로드 요청이 들어올때마다 메모리에 데이터를 계속 계속 올려놓는 상황이 되니 

    Out Of Memory가 발생되는건 당연한 문제였다....

     

     

     

     

     

     

    해결방법

    첫번째 ) 중복 요청 필터링

    내가 운영하고 있는 서버는 엑셀다운로드가 하루에 한두번? 정도만 요청이 들어오고있어서 

    실제로 해보진않았지만 아이디어는 있다.

    다운로드 요청 시 Request Parameter를 해시값으로 만들어 가지고있다가

    다음 요청이 들어왔을 때 Request Parameter를 해시값으로 바꾼값과 서로 비교해보는 것이다.

     

    1번째 요청 파라미터의 해시값과 2번째 요청 파라미터의 해시값이 같다면 중복요청이므로 걸러내면 된다.

     

    일단 나는... 에러가 막 터지고 있던 상황이였어서 빠르게 프론트에 막아달라고 요청했다 ^^..

     

     

     

     

    두번째 ) SXSSF 구현체로 엑셀파일을 생성한다

    위에서 설명한대로 SXSSF는

    [임시파일을 중간중간 생성하여 메모리를 적게 사용하는 방식]으로 엑셀파일을 만들어준다.

    바로 적용해보자.

     

    /**
     * 엑셀 다운로드 구현 🔥🔥🔥
     */ 
    private void createExcelDownloadResponse(HttpServletResponse response, List<UserPoint> userPointList) {
    
        try{
            //제거
            //Workbook workbook = new XSSFWorkbook();  
            
            //추가🔥 : SXSSF 사용
            Workbook workbook = new SXSSFWorkbook();
            Sheet sheet = workbook.createSheet("사용자 포인트 통계");
    
    
            //숫자 포맷 처리
            //파일명 처리
            //헤더 처리
            //바디 처리
    
    
            response.setContentType("application/vnd.ms-excel");
            response.setHeader("Content-Disposition", "attachment;filename="+ URLEncoder.encode(fileName, "UTF-8")+".xlsx");
            //파일명은 URLEncoder로 감싸주는게 좋다!
            
            
            //제거
            //workbook.write(response.getOutputStream());
            //workbook.close();
    
            
            //추가🔥 : 중간중간 임시파일을 만들어 OOM을 방지한다
            OutputStream tempFile = response.getOutputStream();
            workbook.write(tempFile);
            tempFile.close();
            
            response.getOutputStream().flush();
            response.getOutputStream().close();
            
            workbook.dispose();  //임시파일 삭제
    	    
        }catch(IOException e){
            e.printStackTrace();
        }
    
    }

     

     

     

     

    엑셀다운로드 SXSSF로 바꾼 후 Out Of Memory 문제를 잡을 수 있었다!

    편안한 주말을 보내고 싶다면 꼭. 필수로 SXSSF 방식을 사용하자!!!

     

     

     

     

     

     

    반응형
    • 네이버 블러그 공유하기
    • 페이스북 공유하기
    • 트위터 공유하기
    • 구글 플러스 공유하기
    • 카카오톡 공유하기