[spring] Apache POI 추상화 모듈 구현하기 1

KIM Jongwan·2024년 1월 9일
0

SPRING

목록 보기
4/7
post-thumbnail
post-custom-banner

이 글은 우아한형제들 기술블로그의 아 엑셀다운로드 개발,,, 쉽고 빠르게 하고 싶다 (feat. 엑셀 다운로드 모듈 개발기) 를 참고하여 작성되었습니다.

목 차
1. Apache POI 추상화 모듈 구현하기 1 - 엑셀 다운로드 구현
2. Apache POI 추상화 모듈 구현하기 2 - 추상화 모듈 만들기
3. Apache POI 추상화 모듈 구현하기 3 - 추가 기능

서론


java(spring)를 이용하여 엑셀 파일을 생성하기 위한 여러 라이브러리들이 있다.
그중 Apache사의 POI 라이브러리가 많이 사용된다.

Apache POI(POI-ooxml)란 Java에서 Microsoft Office 문서를 다루기 위한 API입니다. 두 API는 모두 Excel, Word, PowerPoint, Outlook 등의 문서를 읽고 쓸 수 있습니다. - google bard

의존 추가

//build.gradle에 아래 의존을 추가한다.
implementation 'org.apache.poi:poi:5.2.3'
implementation 'org.apache.poi:poi-ooxml:5.2.3'
  • org.apache.poi:poi
    • Excel 97~2003의 .xls 파일, Word 97~2003의 .doc 파일, PowerPoint 97~2003의 .ppt 파일 등을 지원
    • OLE(Object Linking and Embedding) 형식의 파일을 처리하므로 메모리 사용량이 상대적으로 많다 (OOM 발생 가능)
  • org.apache.poi:poi-ooxml
    • Excel 2007 이후의 .xlsx 파일, Word 2007 이후의 .docx 파일, PowerPoint 2007 이후의 .pptx 파일 등을 지원
    • XML 형식의 파일을 처리하므로 메모리 사용량이 상대적으로 적다.

엑셀 파일 다운로드 구현


본격적으로 Apache POI를 활용하여 엑셀 파일 다운로드를 구현해보겠습니다.
Spring(Spring Boot) + Apache POI를 활용할 경우 대부분 WEB에서 다운로드 기능을 사용하겠지만, 이번 튜토리얼에서는 새로운 엑셀 파일을 생성하는 방식으로 진행해보겠습니다.

만들어 보게 될 엑셀 데이터 형식입니다.

BookDto.class

public class BookDto {
	
    //constructor()
    public BookDto(){}
    
    //constructor(all args[])
    public BookDto(String title, String publisher, int price, String author, int stock) {
        this.title = title;
        this.publisher = publisher;
        this.price = price;
        this.author = author;
        this.stock = stock;
    }

    private String title;		// 제목
    private String publisher;	// 출판사
    private int price;			// 가격
    private String author;		// 저자
    private int stock;			// 재고
    
    
    //getter, setter
    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    // ... 이하 생략
}

도서 정보를 담을 BookDto.class입니다.
lombok을 사용하지 않기에 생성자와 getter, setter까지 작성해주었습니다.

BookService.class

BookService.Class는 도서 정보를 관리하는 역할을 합니다.

@Component
public class BookService {

	private static List<BookDto> bookList = new ArrayList();
    
    public BookService(){
        BookDto book1 = new BookDto("소설1", "A", 1000, "김아무개", 10);
        BookDto book2 = new BookDto("소설2", "A", 1000, "김아무개", 10);
        BookDto book3 = new BookDto("시집1", "B", 1000, "박소설", 20);
        BookDto book4 = new BookDto("시집2", "C", 2000, "이시집", 20);

        bookList.add(book1);
        bookList.add(book2);
        bookList.add(book3);
        bookList.add(book4);
    }

    public List<BookDto> getBookList(){
        return bookList;
    }

}

BookService에는 List 형태로 엑셀에 입력 될 도서 데이터들이 저장되어있습니다.
(이 부분은 사용 목적에 따라서 수정해서 사용하시면 됩니다.)

ExcelDownloaderV1.Class

이제 본격적으로 조회된 도서 목록을 엑셀 파일로 다운로드 해보겠습니다.

ExcelDownloaderV1.Class의 downloadExcel()메소드를 호출하면
BookService에서 데이터를 조회하여 반복문을 돌며 엑셀 데이터를 입력하는 방식입니다.
(튜토리얼이기 때문에 예외처리는 하지 않겠습니다.)

@Component
public class ExcelDownloaderV1 {

	//도서 정보 조회를 위한 bookService
	private final BookService bookService; 
    
    public ExcelDownloaderV1(BookService bookService){
    	this.bookService = bookService;
    }

	//엑셀 다운로드 로직
    //public void downloadExcel(HttpServletResponse response){  -- Web요청을 받아 처리할 경우
	public void downloadExcel(){
    
    	//데이터 조회
		List<BookDto> bookList = bookService.getBookList();
        
        //Excel Workbook 생성
        Workbook workbook = new SXSSFWorkbook();
        
        //생성된 Workbook에 새 sheet 생성
        Sheet sheet = workbook.createSheet();
        
        //Header 값 입력
        int rowIndex = 0;
        Row headerRow = sheet.createRow(rowIndex++);
        Cell headerCell1 = headerRow.createCell(0);
        headerCell1.setCellValue("제목");

        Cell headerCell2 = headerRow.createCell(1);
        headerCell2.setCellValue("출판사");

        Cell headerCell3 = headerRow.createCell(2);
        headerCell3.setCellValue("가격");

        Cell headerCell4 = headerRow.createCell(3);
        headerCell4.setCellValue("저자");
        
        Cell headerCell5 = headerRow.createCell(4);
        headerCell4.setCellValue("재고");
        
        //bookList 데이터 입력
        for (BookDto book : bookList) {
        	Row bodyRow = sheet.createRow(rowIndex++);
            
            Cell bodyCell1 = bodyRow.createCell(0);
            bodyCell1.setCellValue(book.getTitle());

            Cell bodyCell2 = bodyRow.createCell(1);
            bodyCell2.setCellValue(book.getPublisher());

            Cell bodyCell3 = bodyRow.createCell(2);
            bodyCell3.setCellValue(book.getPrice());

            Cell bodyCell4 = bodyRow.createCell(3);
            bodyCell4.setCellValue(book.getAuthor());
            
            Cell bodyCell5 = bodyRow.createCell(4);
            bodyCell5.setCellValue(book.getStock());
        }
        
        //File 생성 및 데이터 저장
        File outputFile = new File(`파일경로`);
        workbook.wirte(new FileOutputStream(outputFile));
        workbook.close();
    }
}

작성이 완료되었습니다. 이제 downloadExcel() 메소드를 호출하여 엑셀 파일이 정상적으로 생성되는지 확인해보도록 하겠습니다.

public void main(String[] args){

	ExcelDownloaderV1 downloader = new ExcelDownloaderV1();
    
    downloader.downloadExcel();

}

문제점


위와 같이 엑셀 다운로드 기능을 구현한다면 기능 구현과 사용에 큰 어려움은 없을것이다. 하지만 만약 필요한 엑셀 형태가 다양해 진다면?

요구되는 엑셀 형식에 맞춰 커스텀 된 여러개의 downloadExcel1(), downloadExcel2(), downloadExcel3() .... 등등을 새로 생성해야 할 것이다.

또한 직접 헤더값과 위치를 지정해주는 위 방식에서는 오탈자로 인해 기능이 정상적으로 작동하지 않을 위험이 크다!

추상화

이런 문제를 해결하기 위해서 POI 추상화 객체를 만들어 사용하는 방법을 생각해 볼 수 있다.
이후 포스트에서는 Apache POI를 사용하여 엑셀 다운로드 추상화 모듈을 만들어보도록 하겠다.

profile
2년차 백앤드 개발자입니다.
post-custom-banner

0개의 댓글