[JAVA POI] HSSFWorkbook vs XSSFWorkbook vs SXSSFWorkbook 비교

Apache POI Workbook 종류

Apache POI는 Microsoft Office 파일을 처리하기 위한 Java 라이브러리입니다. Excel 파일을 다루기 위해 세 가지 주요 Workbook 구현체를 제공합니다.

📌 HSSFWorkbook

HSSF (Horrible SpreadSheet Format) 는 Excel 97-2003 파일 형식(.xls)을 처리하는 구현체입니다.

특징

  • 파일 형식: .xls (Excel 97-2003)
  • 최대 행 수: 65,536행 (2^16)
  • 최대 열 수: 256열 (2^8)
  • 최대 Cell Style: 4,000개
  • 메모리 사용: 중간 수준 (전체 파일을 메모리에 로드)
  • 처리 속도: XSSF보다 빠름

사용 예시

import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.*;

import java.io.FileOutputStream;
import java.io.IOException;

public class HSSFExample {
public static void main(String[] args) throws IOException {
// HSSFWorkbook 생성
Workbook workbook = new HSSFWorkbook();
Sheet sheet = workbook.createSheet("Sample");

// 데이터 작성
Row row = sheet.createRow(0);
Cell cell = row.createCell(0);
cell.setCellValue("Hello, HSSF!");

// .xls 파일로 저장
try (FileOutputStream fileOut = new FileOutputStream("sample.xls")) {
workbook.write(fileOut);
}

workbook.close();
}
}

장점

  • 오래된 Excel 버전과의 호환성
  • XSSF보다 빠른 처리 속도
  • 작은 파일 크기

단점

  • 행/열 제한이 작음 (65,536행, 256열)
  • Cell Style 제한 (4,000개)
  • 구형 파일 포맷 (현대적인 Excel 기능 제한)

📌 XSSFWorkbook

XSSF (XML SpreadSheet Format) 는 Excel 2007 이후 파일 형식(.xlsx)을 처리하는 구현체입니다.

.xlsx 파일을 전체 DOM 구조로 메모리에 로드해 모든 시트 / 행 / 셀 객체가 메모리에 상주하기 때문에 랜덤 접근(임의 셀 수정, 이동) 에 매우 편리하는 이점이 있습니다.

하지만 파일내 모든 데이터를 메모리에 로드하기 때문에 대용량 파일에는 메모리 부담이 크다는 단점이 있습니다.

특징

  • 파일 형식: .xlsx (Excel 2007+)
  • 최대 행 수: 1,048,576행 (2^20)
  • 최대 열 수: 16,384열 (2^14)
  • 최대 Cell Style: 64,000개
  • 메모리 사용: 높음 (전체 파일을 메모리에 로드)
  • 처리 속도: HSSF보다 느림 (XML 파싱 오버헤드)

사용 예시

import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.poi.ss.usermodel.*;

import java.io.FileOutputStream;
import java.io.IOException;

public class XSSFExample {
public static void main(String[] args) throws IOException {
// XSSFWorkbook 생성
Workbook workbook = new XSSFWorkbook();
Sheet sheet = workbook.createSheet("Sample");

// 데이터 작성
Row row = sheet.createRow(0);
Cell cell = row.createCell(0);
cell.setCellValue("Hello, XSSF!");

// 스타일 적용
CellStyle style = workbook.createCellStyle();
Font font = workbook.createFont();
font.setBold(true);
font.setFontHeightInPoints((short) 14);
style.setFont(font);
cell.setCellStyle(style);

// .xlsx 파일로 저장
try (FileOutputStream fileOut = new FileOutputStream("sample.xlsx")) {
workbook.write(fileOut);
}

workbook.close();
}
}

장점

  • 대용량 데이터 지원 (100만 행 이상)
  • 많은 Cell Style 지원 (64,000개)
  • 현대적인 Excel 기능 지원
  • 압축된 XML 형식으로 파일 크기 감소

단점

  • 높은 메모리 사용량
  • HSSF보다 느린 처리 속도
  • 대용량 파일 처리 시 OutOfMemoryError 발생 가능

📌 SXSSFWorkbook

SXSSF (Streaming XML SpreadSheet Format) 는 XSSFWorkbook의 메모리 최적화 버전으로, 대용량 Excel 파일을 생성할 때 사용합니다.

특징

  • 파일 형식: .xlsx (Excel 2007+)
  • 최대 행 수: 1,048,576행 (2^20)
  • 최대 열 수: 16,384열 (2^14)
  • 최대 Cell Style: 64,000개
  • 메모리 사용: 낮음 (윈도우 방식으로 일부만 메모리에 유지)
  • 처리 속도: 쓰기는 빠르지만 읽기 불가
  • 기본 윈도우 크기: 100행 (변경 가능)

사용 예시

import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.apache.poi.ss.usermodel.*;

import java.io.FileOutputStream;
import java.io.IOException;

public class SXSSFExample {
public static void main(String[] args) throws IOException {
// SXSSFWorkbook 생성 (메모리에 100행만 유지)
SXSSFWorkbook workbook = new SXSSFWorkbook(100);
Sheet sheet = workbook.createSheet("Large Data");

// 대용량 데이터 작성
for (int rowNum = 0; rowNum < 100000; rowNum++) {
Row row = sheet.createRow(rowNum);
for (int colNum = 0; colNum < 10; colNum++) {
Cell cell = row.createCell(colNum);
cell.setCellValue("Row " + rowNum + ", Col " + colNum);
}
}

// .xlsx 파일로 저장
try (FileOutputStream fileOut = new FileOutputStream("large_sample.xlsx")) {
workbook.write(fileOut);
}

// 임시 파일 정리 (중요!)
workbook.dispose();
workbook.close();
}
}

고급 설정

import org.apache.poi.xssf.streaming.SXSSFWorkbook;

public class SXSSFAdvanced {
public static void main(String[] args) {
// 윈도우 크기 설정 (메모리에 유지할 행 수)
SXSSFWorkbook workbook = new SXSSFWorkbook(1000);

// 임시 파일 압축 사용 (메모리 절약)
workbook.setCompressTempFiles(true);

// 자동 플러시 설정
Sheet sheet = workbook.createSheet("Data");

// ... 데이터 작성 ...

// 반드시 dispose() 호출하여 임시 파일 정리
workbook.dispose();
}
}

장점

  • 매우 낮은 메모리 사용량
  • 대용량 데이터 처리 가능 (수백만 행)
  • OutOfMemoryError 방지
  • 스트리밍 방식으로 빠른 쓰기 성능

단점

  • 읽기 불가능 (쓰기 전용)
  • 이전 행으로 돌아가서 수정 불가 (윈도우 밖의 행)
  • 임시 파일 생성 (반드시 dispose() 호출 필요)
  • 랜덤 액세스 불가

주의사항

// 잘못된 예시 - 메모리 누수 발생
SXSSFWorkbook workbook = new SXSSFWorkbook();
workbook.write(outputStream);
workbook.close(); // dispose() 호출 안 함 - 임시 파일이 삭제되지 않음!

// 올바른 예시
SXSSFWorkbook workbook = new SXSSFWorkbook();
try {
workbook.write(outputStream);
} finally {
workbook.dispose(); // 임시 파일 정리
workbook.close();
}

비교표

구분 HSSFWorkbook XSSFWorkbook SXSSFWorkbook
파일 형식 .xls .xlsx .xlsx
Excel 버전 97-2003 2007+ 2007+
최대 행 65,536 1,048,576 1,048,576
최대 열 256 16,384 16,384
Cell Style 제한 4,000 64,000 64,000
메모리 사용 중간 높음 낮음
처리 속도 빠름 보통 빠름 (쓰기)
읽기 지원
쓰기 지원
랜덤 액세스 ⚠️ 제한적
대용량 처리 ⚠️ 제한적
임시 파일

사용 시나리오별 추천

HSSFWorkbook 사용 권장

  • 오래된 Excel 파일(.xls) 호환성이 필요한 경우
  • 데이터가 65,536행 이하인 경우
  • 빠른 처리 속도가 중요한 경우
  • 레거시 시스템과의 통합
// 레거시 시스템용
if (legacySystem) {
Workbook workbook = new HSSFWorkbook();
// ...
}

XSSFWorkbook 사용 권장

  • 현대적인 Excel 기능이 필요한 경우
  • 읽기와 쓰기를 모두 수행해야 하는 경우
  • 데이터 수정이 필요한 경우
  • 중간 규모의 데이터 (수만 행)
// 읽기 및 수정 작업
try (FileInputStream fis = new FileInputStream("input.xlsx")) {
XSSFWorkbook workbook = new XSSFWorkbook(fis);
Sheet sheet = workbook.getSheetAt(0);

// 데이터 읽기 및 수정
Row row = sheet.getRow(0);
Cell cell = row.getCell(0);
cell.setCellValue("Updated Value");

// 저장
try (FileOutputStream fos = new FileOutputStream("output.xlsx")) {
workbook.write(fos);
}
}

SXSSFWorkbook 사용 권장

  • 대용량 데이터 생성 (10만 행 이상)
  • 메모리가 제한적인 환경
  • 쓰기 전용 작업
  • 리포트 생성, 데이터 내보내기
// 대용량 리포트 생성
public void generateLargeReport(List<Data> dataList) throws IOException {
SXSSFWorkbook workbook = new SXSSFWorkbook(100);

try {
Sheet sheet = workbook.createSheet("Report");

int rowNum = 0;
for (Data data : dataList) { // 수백만 건
Row row = sheet.createRow(rowNum++);
row.createCell(0).setCellValue(data.getId());
row.createCell(1).setCellValue(data.getName());
// ...
}

try (FileOutputStream fos = new FileOutputStream("report.xlsx")) {
workbook.write(fos);
}
} finally {
workbook.dispose(); // 임시 파일 정리
workbook.close();
}
}

성능 비교

메모리 사용량 (100,000행 기준)

HSSFWorkbook:  지원 불가 (행 수 제한 초과)
XSSFWorkbook: 약 500MB - 1GB
SXSSFWorkbook: 약 50MB - 100MB (윈도우 크기에 따라)

처리 시간 (100,000행 쓰기)

HSSFWorkbook:  N/A
XSSFWorkbook: 약 15-20초
SXSSFWorkbook: 약 8-12초

실무 예제: 조건부 Workbook 선택

import org.apache.poi.ss.usermodel.*;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;

public class WorkbookFactory {

public static Workbook createWorkbook(String fileType, int estimatedRows) {
if ("xls".equalsIgnoreCase(fileType)) {
if (estimatedRows > 65000) {
throw new IllegalArgumentException(
"XLS format does not support more than 65,536 rows"
);
}
return new HSSFWorkbook();
}

// xlsx 형식
if (estimatedRows > 50000) {
// 대용량: SXSSFWorkbook 사용
return new SXSSFWorkbook(100);
} else {
// 중소량: XSSFWorkbook 사용
return new XSSFWorkbook();
}
}

public static void main(String[] args) throws Exception {
// 사용 예시
Workbook workbook = createWorkbook("xlsx", 200000);

try {
Sheet sheet = workbook.createSheet("Data");

// 데이터 작성...

try (FileOutputStream fos = new FileOutputStream("output.xlsx")) {
workbook.write(fos);
}
} finally {
// SXSSFWorkbook인 경우 dispose() 호출
if (workbook instanceof SXSSFWorkbook) {
((SXSSFWorkbook) workbook).dispose();
}
workbook.close();
}
}
}

Best Practices

1. 적절한 Workbook 선택

// 파일 크기와 용도에 따라 선택
public Workbook chooseWorkbook(int rowCount, boolean needsRead) {
if (needsRead) {
return new XSSFWorkbook(); // 읽기 필요 시 XSSF
}

if (rowCount > 100000) {
return new SXSSFWorkbook(1000); // 대용량은 SXSSF
}

return new XSSFWorkbook(); // 기본은 XSSF
}

2. 리소스 관리

// try-with-resources 사용
public void processExcel() throws IOException {
try (SXSSFWorkbook workbook = new SXSSFWorkbook();
FileOutputStream fos = new FileOutputStream("output.xlsx")) {

// 작업 수행
Sheet sheet = workbook.createSheet();
// ...

workbook.write(fos);
workbook.dispose(); // SXSSF는 반드시 dispose() 호출
}
}

3. 메모리 최적화

// SXSSFWorkbook 사용 시 윈도우 크기 조정
public void optimizeMemory() {
// 메모리가 충분한 경우
SXSSFWorkbook workbook1 = new SXSSFWorkbook(1000);

// 메모리가 제한적인 경우
SXSSFWorkbook workbook2 = new SXSSFWorkbook(100);

// 임시 파일 압축 활성화
workbook2.setCompressTempFiles(true);
}

4. 에러 처리

public void safeExcelGeneration() {
SXSSFWorkbook workbook = null;
try {
workbook = new SXSSFWorkbook();
Sheet sheet = workbook.createSheet();

// 작업 수행...

} catch (Exception e) {
// 에러 처리
e.printStackTrace();
} finally {
if (workbook != null) {
try {
workbook.dispose(); // 임시 파일 정리
workbook.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}

참고사항

  • Apache POI 5.x 버전 기준입니다.
  • 실제 성능은 시스템 사양과 데이터 특성에 따라 다를 수 있습니다.
  • 프로덕션 환경에서는 충분한 테스트를 거친 후 사용하시기 바랍니다.
Share