Java로 Excel을 JSON으로 변환하기: 다중 시트 및 중첩 구조

Pilalo Jovanitho·2026년 8월 18일

JSON은 웹 API와 데이터 교환에서 사실상의 표준이 된 경량 데이터 형식입니다. 반면 Excel은 풍부한 데이터 모델과 계산 기능을 가진 스프레드시트 도구입니다. 이 글에서는 Java용 Spire.XLS for Java 라이브러리를 사용하여 Excel 파일을 JSON으로 변환하는 방법을 다룹니다. 특히 여러 시트를 가진 워크북을 처리하고, 데이터 간의 계층적 관계를 반영한 중첩(nested) JSON을 생성하는 방법에 초점을 맞춥니다.

1. 라이브러리 설치 및 설정

프로젝트에서 Spire.XLS for Java를 사용하려면 Maven pom.xml 파일에 다음 리포지토리와 의존성을 추가합니다.

<repositories>
    <repository>
        <id>com.e-iceblue</id>
        <name>e-iceblue</name>
        <url>https://repo.e-iceblue.com/nexus/content/groups/public/</url>
    </repository>
</repositories>
<dependencies>
    <dependency>
        <groupId>e-iceblue</groupId>
        <artifactId>spire.xls</artifactId>
        <version>16.6.5</version>
    </dependency>
</dependencies>

Maven을 사용하지 않는다면, JAR 파일을 직접 다운로드하여 프로젝트의 클래스패스에 추가할 수 있습니다. JSON 처리를 위해 Jackson 라이브러리(com.fasterxml.jackson.core:jackson-databind)도 함께 사용합니다.

2. 단일 시트 Excel을 JSON 배열로 변환

가장 기본적인 사용 사례는 하나의 워크시트를 JSON 객체 배열로 변환하는 것입니다. 첫 번째 행을 헤더로 사용하여 각 데이터 행을 하나의 JSON 객체로 매핑합니다.

예제 코드:

import com.spire.xls.*;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.fasterxml.jackson.databind.node.ArrayNode;
import java.io.File;
import java.io.IOException;

public class ExcelToJsonConverter {

    public static void main(String[] args) {

        // Excel 워크북 로드
        Workbook workbook = new Workbook();
        workbook.loadFromFile("EmployeeData.xlsx");

        // 첫 번째 워크시트 접근
        Worksheet worksheet = workbook.getWorksheets().get(0);

        // 첫 번째 행에서 열 헤더 읽기
        int columnCount = worksheet.getLastColumn();
        String[] headers = new String[columnCount];
        for (int col = 1; col <= columnCount; col++) {
            headers[col - 1] = worksheet.get(1, col).getValue();
        }

        // Jackson ObjectMapper 및 ArrayNode 생성
        ObjectMapper mapper = new ObjectMapper();
        ArrayNode arrayNode = mapper.createArrayNode();

        // 각 데이터 행을 JSON 객체로 변환
        for (int row = 2; row <= worksheet.getLastRow(); row++) {
            ObjectNode record = mapper.createObjectNode();
            for (int col = 1; col <= columnCount; col++) {
                record.put(headers[col - 1], worksheet.get(row, col).getValue());
            }
            arrayNode.add(record);
        }

        // 예쁘게 포맷팅하여 JSON 파일로 출력
        try {
            mapper.writerWithDefaultPrettyPrinter().writeValue(new File("EmployeeData.json"), arrayNode);
            System.out.println("Excel 데이터가 JSON으로 변환되었습니다.");
        } catch (IOException e) {
            System.err.println("JSON 파일 쓰기 오류: " + e.getMessage());
        }

        // 워크북 리소스 해제
        workbook.dispose();
    }
}

3. 다중 시트 Excel을 JSON 객체로 변환

실제 업무용 Excel 파일은 여러 시트를 포함하는 경우가 많습니다. 이때는 각 시트를 별도의 JSON 배열로 구성하여 하나의 JSON 객체에 담을 수 있습니다. 객체의 키는 시트 이름, 값은 해당 시트의 데이터 배열이 됩니다.

예제 코드:

import com.spire.xls.*;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.fasterxml.jackson.databind.node.ArrayNode;
import java.io.File;
import java.io.IOException;

public class MultiSheetExcelToJson {

    public static void main(String[] args) {

        Workbook workbook = new Workbook();
        workbook.loadFromFile("SalesReport.xlsx");

        ObjectMapper mapper = new ObjectMapper();
        ObjectNode fullReport = mapper.createObjectNode();

        // 워크북의 모든 워크시트 순회
        for (int s = 0; s < workbook.getWorksheets().getCount(); s++) {
            Worksheet worksheet = workbook.getWorksheets().get(s);
            String sheetName = worksheet.getName();

            // 첫 번째 행에서 헤더 읽기
            int columnCount = worksheet.getLastColumn();
            String[] headers = new String[columnCount];
            for (int col = 1; col <= columnCount; col++) {
                headers[col - 1] = worksheet.get(1, col).getValue();
            }

            // 데이터 행을 JSON 객체로 변환
            ArrayNode sheetData = mapper.createArrayNode();
            for (int row = 2; row <= worksheet.getLastRow(); row++) {
                ObjectNode record = mapper.createObjectNode();
                for (int col = 1; col <= columnCount; col++) {
                    record.put(headers[col - 1], worksheet.get(row, col).getValue());
                }
                sheetData.add(record);
            }

            // 이 시트의 데이터를 최종 출력에 추가
            fullReport.set(sheetName, sheetData);
        }

        // 결합된 JSON을 예쁘게 포맷팅하여 파일로 출력
        try {
            mapper.writerWithDefaultPrettyPrinter().writeValue(new File("SalesReport.json"), fullReport);
            System.out.println("다중 시트 워크북이 JSON으로 변환되었습니다.");
        } catch (IOException e) {
            System.err.println("JSON 쓰기 오류: " + e.getMessage());
        }

        workbook.dispose();
    }
}

4. Excel 데이터에서 중첩 JSON 구조 만들기

때로는 평면적인 배열보다 데이터의 계층적 관계를 표현하는 중첩 JSON이 필요합니다. 예를 들어, 프로젝트와 그에 속한 작업(task)이 Excel 행에 나열되어 있다면, 프로젝트별로 작업을 그룹화할 수 있습니다.

예제 코드:

import com.spire.xls.*;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.fasterxml.jackson.databind.node.ArrayNode;
import java.util.LinkedHashMap;
import java.util.Map;
import java.io.File;
import java.io.IOException;

public class NestedExcelToJson {

    public static void main(String[] args) {

        Workbook workbook = new Workbook();
        workbook.loadFromFile("ProjectTasks.xlsx");
        Worksheet worksheet = workbook.getWorksheets().get(0);

        ObjectMapper mapper = new ObjectMapper();

        // 프로젝트 삽입 순서를 유지하기 위해 LinkedHashMap 사용
        Map<String, ObjectNode> projectMap = new LinkedHashMap<>();

        for (int row = 2; row <= worksheet.getLastRow(); row++) {
            String projectName = worksheet.get(row, 1).getValue();
            String taskName = worksheet.get(row, 2).getValue();
            String assignee = worksheet.get(row, 3).getValue();
            String status = worksheet.get(row, 4).getValue();

            // 프로젝트가 처음 등장하면 새 객체 생성
            if (!projectMap.containsKey(projectName)) {
                ObjectNode project = mapper.createObjectNode();
                project.put("name", projectName);
                project.set("tasks", mapper.createArrayNode());
                projectMap.put(projectName, project);
            }

            // 작업(task) 객체를 생성하여 해당 프로젝트의 tasks 배열에 추가
            ObjectNode task = mapper.createObjectNode();
            task.put("task", taskName);
            task.put("assignee", assignee);
            task.put("status", status);
            ((ArrayNode) projectMap.get(projectName).get("tasks")).add(task);
        }

        // 최종 JSON 배열 구성
        ArrayNode projectsJson = mapper.createArrayNode();
        for (ObjectNode project : projectMap.values()) {
            projectsJson.add(project);
        }

        try {
            mapper.writerWithDefaultPrettyPrinter()
                    .writeValue(new File("ProjectTasks.json"), projectsJson);

            System.out.println("중첩 JSON 파일이 성공적으로 생성되었습니다.");
        } catch (IOException e) {
            System.err.println("JSON 파일 쓰기 오류: " + e.getMessage());
        }

        workbook.dispose();
    }
}

5. 데이터 타입 및 빈 셀 처리

실제 Excel 파일은 빈 셀이나 다양한 데이터 타입을 포함할 수 있습니다. 견고한 변환을 위해 다음 사항을 고려해야 합니다.

  • 빈 셀 처리: CellRange.getType()으로 셀 타입이 CellValueType.Empty인지 확인하고, 기본값(예: 빈 문자열 "")을 제공하여 JSON에 null이 포함되지 않도록 합니다.
  • 숫자 타입 보존: getValue()는 문자열을 반환하므로, 숫자 타입은 getNumberValue().doubleValue()를 사용하여 JSON에서 숫자 타입으로 유지합니다.
  • 날짜 형식 변환: Excel은 날짜를 내부적으로 숫자로 저장합니다. getDateTimeValue()로 java.util.Date를 얻은 후 SimpleDateFormat을 사용하여 ISO 8601과 같은 표준 문자열 형식으로 변환합니다.

6. 주의사항 및 대안

  • 헤더 행 건너뛰기: 가장 흔한 실수는 데이터 루프를 1행(헤더)부터 시작하는 것입니다. 항상 헤더는 1행에서 읽고, 데이터 루프는 2행부터 시작해야 합니다.
  • 대안 라이브러리: 이 글에서 사용한 라이브러리 외에도 Aspose.Cells, Apache POI 등이 있습니다. Aspose.Cells는 상용 제품으로 workbook.save("output.json")과 같은 간결한 API를 제공합니다. Apache POI는 오픈소스이지만 더 많은 수동 코딩이 필요합니다.

결론

이 글에서는 Spire.XLS for Java를 사용하여 Excel 파일을 JSON으로 변환하는 방법을 살펴보았습니다. 단일 시트 변환을 시작으로, 다중 시트 처리 및 중첩 JSON 생성까지 다루었습니다. 또한 데이터 타입과 빈 셀 처리 등 실무에서 중요한 고려사항도 확인했습니다. 이 접근 방식은 Excel 데이터를 웹 API나 데이터 파이프라인에 통합해야 할 때 유용하게 사용될 수 있습니다. 프로젝트의 라이선스 요구사항과 필요 기능에 따라 오픈소스 대안과의 비교를 통해 가장 적합한 도구를 선택할 것을 권장합니다.

0개의 댓글