Data to CSV

JSON 데이터를 CSV 형태로 바꾸고 이를 다운로드 가능하게 해야했다. 우선 사용자 관리 테이블이나, 주문 현황, 사용현황테이블을 CSV 형태로 파싱했다.

function convertToCSV(objArray) {
  const header = Object.keys(objArray[0]).join(',');
  const rows = objArray.map(obj => Object.values(obj).join(','));
  return `${header}\\n${rows.join('\\n')}`;
}

헤더와 row를 구분해주고 데이터를 ,로 구분시켜서 붙인 문자열을 만들었다. 이후에 다음과 같이 호출해서 csv 문자열을 얻을 수 있었다.

const csv = converToCSV(data)

리액트 컴포넌트에서는 다음과 같이 다운로드 버튼을 만들고 이를 클릭하면 downloadCSV()라는 함수를 호출하여 다운로드를 구현할 수 있다.

import { useRef } from 'react';

function MyComponent() {
  const csvData = convertToCSV(data);

  function downloadCSV(filename = "data.csv") {
    const blob = new Blob([csvData], { type: 'text/csv;charset=utf-8;' });
    const url = URL.createObjectURL(blob);
    linkRef.current.href = url;
    linkRef.current.download = filename;
    linkRef.current.click();
    URL.revokeObjectURL(url);
  }

  return (
    <>
      <button onClick={downloadCSV}>Download CSV</button>
      <a href="#" ref={linkRef} style={{display: 'none'}}>Download</a>
    </>
  );
}

JavaScript에서는 URL.createObjectURL을 통해 Blob 객체(Blob.Binary Large Object 객체는 자바스크립트에서 이미지, 영상등의 멀티미디어 데이터를 다룰 때 사용한다. createObjectUrl에 입력 가능한 File, Blob, MediaSource 중 File은 Blob에 기반한 인터페이스이다.)를 나타낼 수 있다. 이 메서드를 호출하면 window의 document에서만 접근 가능한 url이 생성된다.(이 URL은 다른 window에서는 접근할 수 없다.) 이를 통해 image를 받았을 때 화면에 보여줄 수 있는 임시 url을 생성할 수 있다. URL.revokeObjectURL을 통해 createObjectURL을 통해 생성된 URL을 폐기 시킬 수 있다. 폐기하지 않으면 자바스크립트 엔진에서는 생성된 URL을 계속 사용하는 것으로 판단하여 GC가 동작하지 않게 된다.

CSV 포맷으로 변환한 후 다운로드 기능을 만드는 작업을 하면서 사용해보지 않은 브라우저 API를 사용해서 흥미로웠다.