백엔드는 Java를 사용하고, 프론트는 Vue를 사용하는 환경에서 엑셀 입출력은 어떻게 처리하는게 효율적일까? 고민이되어 스스로 비교하고 정리하여 작성하는 글.
웹개발을 해본 개발자로써 기본적인 상식은, 비즈니스 로직은 백엔드에서 최대한 처리를 한다라고 인식을 갖고 있었다. 그런데 이번에 새롭게 Vue.js를 적용하여 프로젝트를 진행하던 중에 Vue의 편리함을 알게되었고, Vue를 마구 파보기 시작했다.
편리하다고해서 비즈니스 로직을 Vue로 개발하지는 말자
각 사용자, 브라우저 별로 성능차이가 크기 때문에 프론트에서는 비즈니스 로직 구현은 올바르지 못하다.
그렇다면, 엑셀 입출력은 어떨까.
Java에서 이미 검증되었고, 많은 개발자가 사용한 Java의 POI방식으로 백엔드 처리가 가능하다.
그러나 백엔드까지 연산처리를 할 필요없이 프론트에서 간단하게 출력할 수 있다면 어느 방식이 더 효율적일까?
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>3.7</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.7</version>
</dependency>
import java.awt.Color;
import java.io.File;
import java.io.FileOutputStream;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFFont;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFColor;
import org.apache.poi.xssf.usermodel.XSSFFont;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
public class ExcelDownTest {
public static void main(String[] args) throws Exception{
// .xls 확장자 지원
// HSSFWorkbook hssWb = null;
// HSSFSheet hssSheet = null;
// Row hssRow = null;
// Cell hssCell = null;
//.xlsx 확장자 지원
XSSFWorkbook xssfWb = null;
XSSFSheet xssfSheet = null;
XSSFRow xssfRow = null;
XSSFCell xssfCell = null;
try {
int rowNo = 0; // 행의 갯수
xssfWb = new XSSFWorkbook(); //XSSFWorkbook 객체 생성
xssfSheet = xssfWb.createSheet("워크 시트1"); // 워크시트 이름 설정
// 폰트 스타일
XSSFFont font = xssfWb.createFont();
font.setFontName(HSSFFont.FONT_ARIAL); // 폰트 스타일
font.setFontHeightInPoints((short)20); // 폰트 크기
font.setBold(true); // Bold 설정
font.setColor(new XSSFColor(Color.decode("#457ba2"))); // 폰트 색 지정
//테이블 셀 스타일
CellStyle cellStyle = xssfWb.createCellStyle();
xssfSheet.setColumnWidth(0, (xssfSheet.getColumnWidth(0))+(short)2048); // 0번째 컬럼 넓이 조절
cellStyle.setFont(font); // cellStyle에 font를 적용
cellStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER); // 정렬
//셀병합
xssfSheet.addMergedRegion(new CellRangeAddress(0, 1, 0, 4)); //첫행, 마지막행, 첫열, 마지막열 병합
// 타이틀 생성
xssfRow = xssfSheet.createRow(rowNo++); // 행 객체 추가
xssfCell = xssfRow.createCell((short) 0); // 추가한 행에 셀 객체 추가
xssfCell.setCellStyle(cellStyle); // 셀에 스타일 지정
xssfCell.setCellValue("타이틀 입니다"); // 데이터 입력
xssfSheet.createRow(rowNo++);
xssfRow = xssfSheet.createRow(rowNo++); // 빈행 추가
//테이블 스타일 설정
CellStyle tableCellStyle = xssfWb.createCellStyle();
tableCellStyle.setBorderTop((short) 5); // 테두리 위쪽
tableCellStyle.setBorderBottom((short) 5); // 테두리 아래쪽
tableCellStyle.setBorderLeft((short) 5); // 테두리 왼쪽
tableCellStyle.setBorderRight((short) 5); // 테두리 오른쪽
xssfRow = xssfSheet.createRow(rowNo++);
xssfCell = xssfRow.createCell((short) 0);
xssfCell.setCellStyle(tableCellStyle);
xssfCell.setCellValue("과일");
xssfCell = xssfRow.createCell((short) 1);
xssfCell.setCellStyle(tableCellStyle);
xssfCell.setCellValue("육류");
xssfCell = xssfRow.createCell((short) 2);
xssfCell.setCellStyle(tableCellStyle);
xssfCell.setCellValue("과자");
xssfCell = xssfRow.createCell((short) 3);
xssfCell.setCellStyle(tableCellStyle);
xssfCell.setCellValue("채소");
xssfCell = xssfRow.createCell((short) 4);
xssfCell.setCellStyle(tableCellStyle);
String localFile = "/Users/downlode/" + "excelDownTest" + ".xlsx";
File file = new File(localFile);
FileOutputStream fos = null;
fos = new FileOutputStream(file);
xssfWb.write(fos);
if (fos != null) fos.close();
}catch(Exception e){
}
}
}
npm install vue-excel-xlsx --save
or
yarn add vue-excel-xlsx
<template>
<section>
<xlsx-workbook>
<xlsx-sheet
:collection="sheet.data"
v-for="sheet in sheets"
:key="sheet.name"
:sheet-name="sheet.name"
/>
<xlsx-download>
<button>다운로드</button>
</xlsx-download>
</xlsx-workbook>
</section>
</template>
<script>
import XlsxWorkbook from "./components/XlsxWorkbook";
import XlsxSheet from "./components/XlsxSheet";
import XlsxDownload from "./components/XlsxDownload";
export default {
components: {
XlsxWorkbook,
XlsxSheet,
XlsxDownload
},
data() {
return {
sheets: [{ name: "첫번째 시트", data: [{ 과일: 사과, 육류: 소고기 }] }],
};
}
};
</script>