개발 메모장

[Java] Apache.POI 엑셀 업로드 구현 - Controller(2/3) 본문

Java

[Java] Apache.POI 엑셀 업로드 구현 - Controller(2/3)

yyyyMMdd 2024. 1. 4. 15:18
728x90

#. 이전에 엑셀 파일을 데이터로 처리하는 핸들러를 구현했었습니다.

 

#. 아래 로직을 통해 엑셀 데이터를 호출하고 데이터 처리된 엑셀 파일을 후처리 하는 방법에 대해 소개하려 합니다.

 


#. Controller 로직 구성

  • Service에 구성하는 것이 바람직하나 편의상 Controller에 처리하도록 하겠습니다.

  • 이곳에서도 마찬가지로 xlsx와 xls를 처리하는 로직을 구분하였습니다.

  • xlsx와 xls 모두 업로드 처리를 위한 것으로 처리 로직은 차이가 없습니다.
@RequestMapping(value = "/test.do", method = RequestMethod.POST )
@Transactional
@ResponseBody
public void test(MultipartHttpServletRequest request, MultipartFile mfile, Model model) throws JsonProcessingException, SQLException {
    // 업로드 한 파일 받기
    MultipartFile excelFile = request.getFile("HTML에서 지정한 name");
    // 파일 및 폴더 생성
    File destFile = new File("파일경로"+excelFile.getOriginalFilename());
    Boolean isSuccess = true;

    // 폴더 없을 시 생성
    if(!destFile.exists()) {
        destFile.mkdirs();
    }

    try {
    	// 업로드한 파일 데이터를 생성한 파일로 전송
        excelFile.transferTo(destFile);
    } catch (IllegalStateException | IOException e) {
        e.printStackTrace();
    }

    // 생성한 파일 경로 변수 생성
    String filePath = "파일경로"+excelFile.getOriginalFilename();
    // 파일의 확장자 변수 생성
    String extension = StringUtils.getFilenameExtension(filePath);

    Map<String, Object> cntResult = new HashMap<String, Object>();
    List<List<String>> excelDatas ;
    List<String> headList ;

	// xls 처리
    if(extension.equals("xls")) {
    	// 핸들러 > xls 처리 메서드 호출
        ExcelSheetHandler excelSheetHandler = ExcelSheetHandler.readExcelXls(destFile);
        // 핸들러 > 행 데이터 가져오기
        excelDatas = excelSheetHandler.getsRows();
        // 핸들러 > 헤더 행 데이터 가져오기
        headList = excelSheetHandler.getHeadersRow();

        List<HashMap<String, String>> params = new ArrayList<>();
        // 헤더 키에 따른 밸류 값 넣기
        for(List<String> row : excelDatas) {
            HashMap<String, String> item = new HashMap<>();
            int idx = 0;
            // 헤더 키 값 넣기
            for(String headerName : headList) {
                item.put(headerName, row.get(idx));
                idx++;
            }
            params.add(item);
        }

	// DB 처리 시 5000건씩 데이터 보내기
        int UPLOAD_UNIT = 5000;

        // 파티션을 이용한 배열 데이터 자르기
        List<List<HashMap<String, String>>> partedPostData = ListUtils.partition(params, UPLOAD_UNIT);
        for(List<HashMap<String, String>> postData : partedPostData) {
            try {
            	// DB와 연동하여 처리할 메서드
                addBatch(headList, postData);
            } catch (Exception e) {
                System.out.println(e.getMessage());
                isSuccess = false;
                break;
            }
        }
    // xlsx 처리
    } else {
        ExcelSheetHandler excelSheetHandler = ExcelSheetHandler.readExcelXlsx(destFile);
        excelDatas = excelSheetHandler.getRows();
        headList = excelSheetHandler.getHeaderRow();

        List<HashMap<String, String>> params = new ArrayList<>();
        for(List<String> row : excelDatas) {
            HashMap<String, String> item = new HashMap<>();
            int idx = 0;
            for(String headerName : headList) {
                item.put(headerName, row.get(idx));
                idx++;
            }
            params.add(item);
        }

        int UPLOAD_UNIT = 5000;

        List<List<HashMap<String, String>>> partedPostData =  ListUtils.partition(params, UPLOAD_UNIT);
        for(List<HashMap<String, String>> postData : partedPostData) {
            try {
                addBatch(headList, postData);
            } catch (Exception e) {
                System.out.println(e.getMessage());
                isSuccess = false;
                break;
            }
        }
    }
    // 생성한 파일 삭제하기
    destFile.delete();
   }

 

  • 특별한 내용은 없고 데이터를 보낼 때 메모리에 먼저 데이터들을 올리게 됩니다.

  • 이때 대량의 데이터인 경우 메모리가 부족하여 OOM이 발생할 수 있습니다.

  • 따라서 데이터를 메모리에 올릴 때 건수를 조절할 수 있도록 ListUtils의 partition을 사용하였습니다.

  • 몇 건의 데이터를 처리할 때 가장 효율적인지 확인해 보고 그에 맞게 조절해 주면 좋을 것 같습니다.

#. 이어서 대량용 인서트를 위해 생성한 addBatch 메서드에 대한 포스팅을 하도록 하겠습니다.

 

 

 

===========================================================
틀린 내용이 있거나 이견 있으시면 언제든 가감 없이 말씀 부탁드립니다!
===========================================================

728x90