Apache POI가 아니라 GcExcel을 사용해야 하는 12가지 이유
페이지 정보
작성자 GrapeCity
본문
관련링크
GcExcel Java는 Java 개발자를 위한 빠르고 완전한 기능을 갖춘 스프레드시트입니다. GcExcel은 가장 널리 사용되는 Java용 스프레드시트 라이브러리인 Apache POI에 비해 기능 및 성능 면에서 훨씬 뛰어납니다.
이 게시물에서는 두 제품의 기능과 성능을 비교하고 Apache POI가 아니라 GcExcel을 사용해야 하는 12가지 주된 이유를 제시합니다.
비교에 사용한 빌드
이 비교에서는 다음과 같은 빌드 버전의 GcExcel과 Apache POI(벤치마크 응용 프로그램용 build.gradle에서 발췌)를 참조합니다.
- implementation 'com.grapecity.documents:gcexcel:3.1.0'
- implementation 'org.apache.poi:poi-ooxml:4.1.1'
- implementation 'org.apache.poi:poi-ooxml-schemas:4.1.1'
- implementation 'org.apache.poi:poi:4.1.1'
성능 샘플 - 벤치마크 샘플 다운로드
기능 비교
다음은 Apache POI가 아니라 GcExcel을 사용해야 하는 12가지 주된 이유입니다.
GcExcel은 훨씬 더 빠르고 훨씬 더 적은 메모리를 사용합니다. 여러 플랫폼에서 성능을 비교한 결과 GcExcel이 Apache POI보다 평균 15-25배 빠르고 6배 더 효율적인 것으로 나타났습니다(아래의 성능 결과 참조).
큰 범위에 대한 수식 설정과 같은 일부 작업은 100배 이상 더 빨랐습니다.
GcExcel은 셀 수식에 452가지 계산 함수를 지원하는 반면, Apache POI는 다양한 최신 함수를 지원하지 않아 157-280개의 계산 함수만 사용할 수 있으며 그 밖의 함수는 개발자가 구현해야 합니다.
GcExcel은 페이지 설정 옵션 제어에 대한 완벽한 지원, PDF 보안 옵션 및 문서 속성에 대한 기본 제공 지원 등 PDF로 내보내기를 지원하는 반면, Apache POI는 PDF로 내보내기를 지원하지 않고 예제도 제공하지 않습니다.
GcExcel은 아이콘 집합, 평균 이상, 발생 날짜, 위쪽/아래쪽, 중복/고유 등 Excel VSTO API와 호환되는 조건부 서식 규칙을 지원하는 반면, Apache POI는 조건부 서식을 지원하지 않으므로 내부용으로 표시된 하위 수준 클래스를 사용해야 합니다.
GcExcel은 상자 수염, 깔때기형, 히스토그램, 파레토, 선버스트, 트리맵, 폭포 등 모든 최신 차트 유형을 포함하여 Excel VSTO API와 호환되는 53가지 차트 유형을 지원하는 반면, Apache POI는 가로 막대형, 세로 막대형, 꺾은선형, 방사형, 분산형 차트만 지원합니다.
GcExcel은 셀 안에 직접 작은 차트를 넣어 셀에서 바로 데이터를 시각화할 수 있는 스파크라인 및 스파크라인 그룹을 지원하는 반면, Apache POI는 스파크라인을 전혀 지원하지 않습니다.
GcExcel은 도형 및 그림의 자르기/복사/붙여넣기를 지원하는 반면, Apache POI는 도형이나 그림에 대한 클립보드 작업을 전혀 지원하지 않습니다.
GcExcel은 숫자, 텍스트, 색, 아이콘 등 고급 필터 적용을 지원하는 반면, Apache POI는 기본 AutoFilter만 매우 제한적으로 지원합니다.
GcExcel은 값 기준, 여러 값 기준, 사용자 정의 정렬, 내부 기준, 글꼴 색 기준, 아이콘 기준 등 정렬 기능을 지원하는 반면, Apache POI는 정렬을 지원하지 않습니다.
GcExcel 은 기본 제공 슬라이서 스타일 및 사용자 정의 슬라이서 스타일 적용, 잘라내기/복사, 중복, 필터 작업 수행 등 표가 포함된 슬라이서 및 피벗 테이블이 포함된 슬라이서를 지원하는 반면, Apache POI는 이를 지원하지 않습니다.
GcExcel은 손쉬운 CSV 가져오기 및 내보내기 기능을 지원하는 반면, Apache POI는 이를 지원하지 않습니다.
GcExcel은 그라디언트 채우기를 지원하지만 Apache POI에서는 이를 지원하지 않습니다. 그라디언트 채우기는 셀, 도형, 차트 계열을 눈에 잘 띄게 표시하는 데 유용합니다.
아래 표에는 Apache POI가 아니라 GcExcel을 사용해야 하는 그 밖의 여러 가지 이유가 정리되어 있습니다.
GcExcel Java와 Apache POI 비교 - 상세 비교표
기능 |
GcExcel |
Apache POI |
|
값 |
서식 있는 텍스트 |
✔ |
✔ |
스타일 |
Excel과 유사한 숫자 포맷터 |
✔ |
✔ |
패턴 채우기 |
✔ |
✔ |
|
그라데이션 채우기 |
✔ |
✘ |
|
표시 형식 스타일 가져오기 |
✔ |
✘ |
|
workbook.Styles.Add(문자열 이름, IStyle baseOn) |
✔ |
✘ |
|
수식 |
지원되는 합계 수식 |
452 |
157 |
IS External 참조 가져오기 |
✔ |
✘ |
|
ArrayFormula |
✔ |
✔ |
|
모든 Excel 함수 |
✔ |
✘ |
|
전체 Excel2016 함수 |
✔ |
✘ |
|
FormulaArrayR1C1 지원 |
✔ |
✘ |
|
수식의 종속성을 가져오기 위한 API 제공 |
✔ |
✘ |
|
표 |
표 스타일 |
✔ |
✔ |
사용자 정의 표 스타일 |
✔ |
✔ |
|
표 수식 |
✔ |
✔ |
|
셀 복사/이동 |
✔ |
✔ |
조건부 서식 |
데이터 막대 |
✔ |
✔ |
셀 값 |
✔ |
✔ |
|
아이콘 집합 |
✔ |
✔ |
|
색조 |
✔ |
✔ |
|
사용자 정의 아이콘 집합 |
✔ |
✘ |
|
평균 초과 |
✔ |
✘ |
|
발생 날짜 |
✔ |
✘ |
|
위쪽/아래쪽10 |
✔ |
✘ |
|
중복/고유 |
✔ |
✔ |
|
수식 표현 규칙 |
✔ |
✔ |
|
차트 |
세로 막대형 차트 |
✔ |
✔ |
꺾은선형 차트 |
✔ |
✔ |
|
원형 차트 |
✔ |
✘ |
|
가로 막대형 차트 |
✔ |
✔ |
|
영역형 차트 |
✔ |
✘ |
|
분산형 차트 |
✔ |
✔ |
|
주식형 차트 |
✔ |
✘ |
|
풍선 차트 |
✔ |
✘ |
|
방사형 차트 |
✔ |
✔ |
|
조합 차트 |
✔ |
✘ |
|
이중 축 차트 | ✔ | ✘ | |
차트 시트 | ✔ | ✘ | |
새로운 Excel 2016 통계 및 특수 차트 유형 | ✔ | ✘ | |
스파크라인 |
| ✔ | ✘ |
도형 | 도형 | ✔ | ✔ |
도형 조정 | ✔ | ✔ | |
도형 좌표(이동, 크기 조정, 행/열 변경) | ✔ | ✔ | |
도형(차트/그림/메모/슬라이서) 잘라내기/복사/붙여넣기 | ✔ | ✘ | |
도형 스타일 지원 | ✔ | ✔ | |
도형 그룹 API | ✔ | ✔ | |
도형 하이퍼링크 | ✔ | ✘ |
이미지 |
✔ |
✔ |
|
필터 |
텍스트 필터 |
✔ |
✘ |
숫자 필터 |
✔ |
✘ |
|
날짜 필터 |
✔ |
✘ |
|
아이콘 필터 |
✔ |
✘ |
|
색 필터 |
✔ |
✘ |
|
그룹화 |
데이터 그룹화 |
✔ |
✔ |
정렬 |
행 정렬 |
✔ |
✘ |
여러 열 정렬 |
✔ |
✘ |
|
사용자 정의 정렬 |
✔ |
✔ |
|
글꼴 색 정렬 |
✔ |
✘ |
|
내부 색 정렬 |
✔ |
✘ |
|
아이콘 정렬 |
✔ |
✘ |
|
데이터 유효성 검사 |
✔ |
✔ |
|
표 |
표 |
✔ |
✔ |
슬라이서 |
✔ |
✘ |
|
피벗 테이블 |
피벗 테이블 |
✔ |
✔ |
슬라이서 |
✔ |
✘ |
|
메모 |
✔ |
✔ |
|
가져오기 |
CSV |
✔ |
✘ |
XLSX | ✔ | ✔ | |
XSLM | ✔ | ✔ | |
내보내기 | CSV | ✔ | ✘ |
XLSX | ✔ | ✔ | |
XSLM | ✔ | ✔ | |
✔ | ✘ | ||
PDF 보안 옵션 | ✔ | ✔ | |
시트/범위/도형을 이미지로 내보내기 | ✔ | ✘ | |
인쇄 및 보기 | 인쇄 설정 | ✔ | ✔ |
Excel 보기 설정 | ✔ | ✔ | |
테마 | 테마 | ✔ | ✔ |
테마 개선 | ✔ | ✘ | |
하이퍼링크 | 하이퍼링크 지원 | ✔ | ✔ |
사용자 정의 함수 | 사용자 정의 함수 지원 | ✔ | ✔ |
워크시트 | 워크시트 복사 및 이동 | ✔ | ✔ |
통합 문서 내 또는 통합 문서 간 워크시트 복사 또는 이동 | ✔ | ✘ | |
검색 | 텍스트 찾기 및 바꾸기 | ✔ | ✘ |
VBA 매크로 | 추가 기능, VBA, 매크로 보존 또는 제거 | ✔ | ✔ |
템플릿 언어 | 데이터베이스의 데이터를 Excel 시트에 채울 수 있는 템플릿 언어 지원 | ✔ | ✘ |
기타 | 창 고정/고정 취소 | ✔ | ✔ |
Excel 읽기/쓰기 옵션 | ✔ | ✔ | |
페이지 설정 | ✔ | ✔ |
성능 비교
테스트 시스템 구성
- Linux: Intel i7-8700 @ 3.2GHz x 12 32GB RAM / Ubuntu 18.04.4
- MacOS: Intel i5 @ 2.6GHz / MacOS Mojave v10.14.6
- Windows: Intel i7-6600U @ 2.60GHz 2.81GHz 16GB RAM / Windows 10 x64 v1803(Build 17134.1304)
테스트 응용 프로그램 유형
성능 테스트는 github의 Java 콘솔 벤치마크 데모 코드에 있습니다.
테스트 데이터
처음 3개 테스트에서는 이중, 문자열, 날짜 유형의 값을 100,000개의 행 x 30개의 열에 채워 값 설정, 값 가져오기, XLSX로 저장, 사용된 메모리 합계(언제든지 가비지 수집이 발생할 수 있으므로 정확하게 측정하기 어려움) 등의 성능을 측정합니다.
이러한 테스트는 다음과 같은 모습으로 이루어집니다(문자열 테스트에서는 하드코딩된 문자열 값 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"를 사용하고 날짜 테스트에서는 new Date() 개체를 생성하며, 그 외에는 동일).
GcExcel 이중 성능 테스트
public static void TestSetRangeValues_Double(int rowCount, int columnCount, RefObject<Double> setTime, RefObject<Double> getTime, RefObject<Double> saveTime, RefObject<Double> usedMem) { System.out.println(); System.out.println(String.format("GcExcel benchmark for double values with %,d rows and %d columns", rowCount, columnCount)); double startMem = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory(); IWorkbook workbook = new Workbook(); IWorksheet worksheet = workbook.getWorksheets().get(0); long start = System.currentTimeMillis(); double[][] values = new double[rowCount][columnCount]; for (int i = 0; i < rowCount; i++) { for (int j = 0; j < columnCount; j++) { values[i][j] = i + j; } } worksheet.getRange(0, 0, rowCount, columnCount).setValue(values); long end = System.currentTimeMillis(); setTime.value = (end - start) * 0.001; System.out.println(String.format("GcExcel set double values: %.1f s", setTime.value)); start = System.currentTimeMillis(); Object tmpValues = worksheet.getRange(0, 0, rowCount, columnCount).getValue(); end = System.currentTimeMillis(); getTime.value = (end - start) * 0.001; System.out.println(String.format("GcExcel get double values: %.1f s", getTime.value)); start = System.currentTimeMillis(); workbook.save("output/gcexcel-saved-doubles.xlsx"); end = System.currentTimeMillis(); saveTime.value = (end - start) * 0.001; System.out.println(String.format("GcExcel save doubles to Excel: %.1f s", saveTime.value)); double endMem = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory(); usedMem.value = (endMem - startMem) / 1024 / 1024; System.out.println(String.format("GcExcel used memory: %.1f MB", usedMem.value)); }
마지막 2가지 테스트에서는 계산 성능에 더 집중합니다. 테스트 4에서는 100,000개의 행 x 2개의 열에 이중 값을 채운 다음 처음 2개의 열에 인접해 있고 해당 열의 이중 값을 참조하는 100,000개의 행 x 30개의 열 범위에 수식을 설정하여 수식 설정, 계산, XLSX로 저장, 사용된 메모리 합계 등의 성능을 측정합니다.
이 테스트의 모습은 다음과 같습니다.
GcExcel 개방형 대규모 XLSX 성능 테스트
public static void TestBigExcelFile(int rowCount, int columnCount, RefObject<Double> openTime, RefObject<Double> calcTime, RefObject<Double> saveTime, RefObject<Double> usedMem) { System.out.println(); System.out.println(String.format("GcExcel benchmark for test-performance.xlsx which is 20.5MB with a lot of values, formulas and styles")); double startMem = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory(); IWorkbook workbook = new Workbook(); long start = System.currentTimeMillis(); workbook.open("files/test-performance.xlsx"); long end = System.currentTimeMillis(); openTime.value = (end - start) * 0.001; System.out.println(String.format("GcExcel open big Excel: %.1f s", openTime.value)); start = System.currentTimeMillis(); workbook.dirty(); workbook.calculate(); end = System.currentTimeMillis(); calcTime.value = (end - start) * 0.001; System.out.println(String.format("GcExcel calculate formulas for big Excel: %.1f s", calcTime.value)); start = System.currentTimeMillis(); workbook.save("output/gcexcel-saved-test-performance.xlsx"); end = System.currentTimeMillis(); saveTime.value = (end - start) * 0.001; System.out.println(String.format("GcExcel save back to big Excel: %.1f s", saveTime.value)); double endMem = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory(); usedMem.value = (endMem - startMem) / 1024 / 1024; System.out.println(String.format("GcExcel used memory: %.1f MB", usedMem.value)); }
테스트 5에서는 워크시트가 계산될 때마다 재계산해야 하는 다기능 함수를 사용하는 여러 수식이 포함된 대규모 XLSX를 로드하고 파일 열기, 계산, XLSX로 저장, 사용된 메모리 합계 등의 성능을 측정합니다.
이 테스트의 모습은 다음과 같습니다.
GcExcel 수식 성능 테스트
public static void TestSetRangeFormulas(int rowCount, int columnCount, RefObject<Double> setTime, RefObject<Double> calcTime, RefObject<Double> saveTime, RefObject<Double> usedMem) { System.out.println(); System.out.println(String.format("GcExcel benchmark for double values with %,d rows and %d columns", rowCount, columnCount)); double startMem = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory(); IWorkbook workbook = new Workbook(); workbook.setReferenceStyle(ReferenceStyle.R1C1); IWorksheet worksheet = workbook.getWorksheets().get(0); double[][] values = new double[rowCount][2]; for (int i = 0; i < rowCount; i++) { for (int j = 0; j < 2; j++) { values[i][j] = i + j; } } worksheet.getRange(0, 0, rowCount, 2).setValue(values); long start = System.currentTimeMillis(); worksheet.getRange(0, 2, rowCount, columnCount).setFormula("=SUM(RC[-2],RC[-1])"); long end = System.currentTimeMillis(); setTime.value = (end - start) * 0.001; System.out.println(String.format("GcExcel set formulas: %.1f s", setTime.value)); start = System.currentTimeMillis(); workbook.calculate(); end = System.currentTimeMillis(); calcTime.value = (end - start) * 0.001; System.out.println(String.format("GcExcel calculates formula: %.1f s", calcTime.value)); workbook.setReferenceStyle(ReferenceStyle.A1); start = System.currentTimeMillis(); workbook.save("output/gcexcel-saved-formulas.xlsx"); end = System.currentTimeMillis(); saveTime.value = (end - start) * 0.001; System.out.println(String.format("GcExcel save formulas to Excel: %.1f s", saveTime.value)); double endMem = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory(); usedMem.value = (endMem - startMem) / 1024 / 1024; System.out.println(String.format("GcExcel used memory: %.1f MB", usedMem.value)); }
테스트 결과
차트:
Linux: 성능: 평균 23.6배 더 빠름, 메모리: 평균 5.7배 더 효율적임
Windows: 성능: 평균 24.7배 더 빠름, 메모리: 평균 6.3배 더 효율적임
MacOS: 성능: 평균 15.3배 더 빠름, 메모리: 평균 6.0배 더 효율적임
성능 스프레드시트 데이터
계산에 이용한 전체 성능 세부 사항은 다음 스프레드시트에 나와 있습니다.
성능 샘플
전반적으로 GcExcel이 더 빠르고 메모리 사용량이 더 적습니다.
GcExcel을 이용하면 Excel에 의존하지 않고 스프레드시트를 완전히 제어할 수 있습니다.
이 글에 대한 의견이나 질문이 있으시면 아래의 댓글에 남겨 주시기 바랍니다.
댓글목록
하늘을날자님의 댓글


GrapeCity님의 댓글의 댓글


안녕하세요. "하늘을날자"님 문의 주신 것과 같이, 안드로이드 개발 시에도 사용이 가능합니다. 특히 GCExcel의 경우, 안드로이드 공식 개발언어인 Kotlin를 공식지원하고 있습니다. IDE는 JAVA 또는 Kotlin 개발이 가능한 어던 IDE든 상관 없습니다. (IDE에 의존되지 않습니다.) 또한, GCExcel API는 DB에도 종속되지 않습니다. 필요한신 DB로 부터 데이터를 가져오는 서비스만 만들으셔서, 저희 API를 통해 Excel 파일 형식으로 해당 데이터를 쉽게 가공하실 수 있습니다. 추가적으로 궁금하신 내용이 있으시면 언제든지 덧글 또는 그레이프시로 연락주세요 ^^
하늘을날자님의 댓글의 댓글

