개발 가이드 백엔드 엑셀 다운로드 가이드
최종 수정:

엑셀 다운로드 가이드

Apache POI 기반 엑셀 파일 생성 및 다운로드 규칙

엑셀 다운로드 가이드

현재 상태

이 프로젝트는 현재 엑셀 다운로드 기능이 구현되어 있지 않다.
향후 관리자 페이지에서 데이터 내보내기가 필요할 경우 이 가이드를 참고한다.


의존성 추가

// build.gradle
implementation 'org.apache.poi:poi-ooxml:5.2.5'   // .xlsx 형식

Controller 반환 형식

@GetMapping("/download")
public ResponseEntity<byte[]> downloadExcel() throws IOException {
    byte[] excelBytes = postService.generateExcel();

    String fileName = URLEncoder.encode("노트목록.xlsx", StandardCharsets.UTF_8);

    HttpHeaders headers = new HttpHeaders();
    headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
    headers.setContentDispositionFormData("attachment", fileName);
    headers.setContentLength(excelBytes.length);

    return ResponseEntity.ok()
            .headers(headers)
            .body(excelBytes);
}

Service 엑셀 생성

@Service
@Transactional(readOnly = true)
@RequiredArgsConstructor
public class PostService {

    private final PostRepository postRepository;

    public byte[] generateExcel() throws IOException {
        List<Post> posts = postRepository.findAll();

        try (Workbook workbook = new XSSFWorkbook();
             ByteArrayOutputStream out = new ByteArrayOutputStream()) {

            Sheet sheet = workbook.createSheet("노트 목록");

            // 헤더 행
            Row header = sheet.createRow(0);
            header.createCell(0).setCellValue("ID");
            header.createCell(1).setCellValue("제목");
            header.createCell(2).setCellValue("카테고리");
            header.createCell(3).setCellValue("등록일시");

            // 데이터 행
            int rowIdx = 1;
            for (Post post : posts) {
                Row row = sheet.createRow(rowIdx++);
                row.createCell(0).setCellValue(post.getId());
                row.createCell(1).setCellValue(post.getTitle());
                row.createCell(2).setCellValue(post.getCategory());
                row.createCell(3).setCellValue(
                        post.getFrstRegistDt().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm")));
            }

            // 열 너비 자동 조정
            for (int i = 0; i < 4; i++) {
                sheet.autoSizeColumn(i);
            }

            workbook.write(out);
            return out.toByteArray();
        }
    }
}

Content-Disposition 파일명 인코딩

한글 파일명은 반드시 URL 인코딩 처리한다.

// 한글 파일명 처리 (RFC 5987)
String fileName = URLEncoder.encode("데이터_" + LocalDate.now() + ".xlsx",
        StandardCharsets.UTF_8).replace("+", "%20");

headers.set(HttpHeaders.CONTENT_DISPOSITION,
        "attachment; filename*=UTF-8''" + fileName);

대용량 데이터 처리 주의사항

  • 10만 건 이상: SXSSFWorkbook (스트리밍 방식) 사용
  • 메모리 부족 방지를 위해 스트리밍 처리 필수
// SXSSFWorkbook — 대용량 데이터
try (Workbook workbook = new SXSSFWorkbook(1000)) {  // 1000행씩 메모리에 유지
    // 동일한 방식으로 데이터 작성
}

보안 체크리스트

  • [ ] 파일명에 사용자 입력값 사용 금지 (Path Traversal 방지)
  • [ ] 파일 크기 제한 설정
  • [ ] 개인정보 포함 시 다운로드 권한 검증
  • [ ] 운영 환경에서 엑셀 다운로드 API 인증 적용
AI 문서 검색

현재 페이지 내용을 기반으로 질문하세요.