토이 프로젝트 진행 중에 csv 파일로 대량의 데이터를 한 번에 업로드할 수 있는 기능을 구현하려고 하기 위해
자바스크립트로 어떻게 csv 파일을 읽어들이고 데이터를 다룰 수 있는지 여기저기 공부하다가 좋은 글이 있어 번역해 옮겨본다.
JavaScript - Parse CSV data into an array
이번 튜토리얼에서는 HTML <input> 엘리먼트로 CSV 파일을 어떻게 전달받고 자바스크립트 배열로 어떻게 내용을 파싱 할지에 대해 알아보겠다.
CSV 데이터를 배열로 변환하기 위해선, readAsText() 메소드를 가지고 있는 자바스크립트의 FileReader 클래스를 사용해야 한다. readAsText() 메서드는 CSV 파일을 읽고 결과를 스트링 텍스트로 파싱 한다.
예를 들어 아래와 같은 CSV 파일이 있다고 가정해보자.
name,role,country
Sarene,Help Desk Operator,Thailand
Olvan,Nurse Practicioner,China
Janos,Cost Accountant,China
Dolph,Assistant Manager,China
Ariela,Database Administrator I,Azerbaijan
Lane,Environmental Tech,Indonesia
Griselda,Senior Quality Engineer,Portugal
Manda,Physical Therapy Assistant,Brazil
Leslie,Information Systems Manager,Japan
Aleen,Cost Accountant,Canada
위 파일은 아래와 같은 자바스크립트 배열로 변환시킬 수 있다.
const arr = [
{ name: "Sarene", role: "Help Desk Operator", country: "Thailand" },
{ name: "Olvan", role: "Nurse Practicioner", country: "China" },
{ name: "Janos", role: "Cost Accountant", country: "China" },
{ name: "Dolph", role: "Assistant Manager", country: "China" },
{ name: "Ariela", role: "Database Administrator I", country: "Azerbaijan" },
{ name: "Lane", role: "Environmental Tech", country: "Indonesia" },
{ name: "Griselda", role: "Senior Quality Engineer", country: "Portugal" },
{ name: "Manda", role: "Physical Therapy Assistant", country: "Brazil" },
{ name: "Leslie", role: "Information Systems Manager", country: "Japan" },
{ name: "Aleen", role: "Cost Accountant", country: "Canada" },
];
튜토리얼 코드는 여기서 확인할 수 있다.
우선은 HTML 엘리먼트를 이용해 CSV 파일을 어떻게 받아들이는지 살펴보자.
<input> 엘리먼트를 이용해 CSV 파일을 받을 HTML form이 필요하다. 아래는 예문이다.
<body>
<form id="myForm">
<input type="file" id="csvFile" accept=".csv" />
<br />
<input type="submit" value="Submit" />
</form>
</body>
이제 HTML 엘리먼트는 준비되었으니 submit 이벤트를 감지할 스크립트가 필요하다.
<form> 태그 아래에 아래 코드를 넣어주자.
<script>
const myForm = document.getElementById("myForm");
const csvFile = document.getElementById("csvFile");
myForm.addEventListener("submit", function (e) {
e.preventDefault();
console.log("Form submitted");
});
</script>
우선은 브라우저의 기본값으로 설정된 submit 설정(페이지를 새로고침한다)을 방지하기 위해 e.preventDefault() 코드가 필요하다. 그러고 나서, 유저에 의해 이벤트가 발생했을 때 실행할 코드를 작성하면 된다.
업로드된 CSV 파일을 아래와 같이 받을 수 있다.
const myForm = document.getElementById("myForm");
const csvFile = document.getElementById("csvFile");
myForm.addEventListener("submit", function (e) {
e.preventDefault();
const input = csvFile.files[0];
});
그리고 아래와 같이 FileReader 클래스의 새 인스턴스를 생성해야 한다.
const reader = new FileReader();
우선, 리딩 오퍼레이션이 onload 이벤트 헨들러를 통해 완료될 때 어떤 일이 발생해야 할지 정의해야 한다. 리딩 오퍼레이션의 결과는 event.target.result 프로퍼티로 아래와 같이 확인할 수 있다.
const reader = new FileReader();
reader.onload = function (event) {
console.log(event.target.result); // the CSV content as string
};
그러면 아래와 같이 reader에게 특정 파일을 읽도록 명령할 수 있다.
reader.readAsText(file);
이제 자바스크립트의 FileReader가 어떻게 작동하는지 알게 되었으니, 업로드된 CSV 파일을 읽는 코드를 모두 작성해보자. 전체 코드는 아래와 같다.
<head> </head>
<body>
<form id="myForm">
<input type="file" id="csvFile" accept=".csv" />
<br />
<input type="submit" value="Submit" />
</form>
<script>
const myForm = document.getElementById("myForm");
const csvFile = document.getElementById("csvFile");
myForm.addEventListener("submit", function (e) {
e.preventDefault();
const input = csvFile.files[0];
const reader = new FileReader();
reader.onload = function (e) {
const text = e.target.result;
document.write(text);
};
reader.readAsText(input);
});
</script>
</body>
CSV 콘텐츠가 브라우저에 렌더링 되는 것을 확인 할 수 있다. 이는 <script>가 문제없이 CSV 파일의 내용을 스트링으로 읽어 들일 수 있었음을 의미한다. 다음으로 이 스트링을 객체의 배열로 파싱만 하면 된다.
Parsing CSV string into an array
CSV 스트링을 배열로 파싱하기 위해선, CSV 헤더와 열을 구분하는 코드가 필요하다. 그리고 각 열을 객체 엘리먼트에 넣고 헤더는 프로퍼티의 이름으로 그리고 열은 값으로 사용한다.
우선, 두개의 파라미터를 가지는 csvToArray() 함수를 만들자.
- CSV 스트링 데이터
- CSV 스트링 데이터의 구분자(보통은 콤마,)
아래는 함수의 문법이다.
function csvToArray(str, delimiter = ",") {}
이 함수에서는 두 개의 배열이 필요하다. headers와 rows. headers는 CSV 파일의 첫 번째 줄을 의미하고, rows는 두 번째 줄부터 마지막까지의 모든 값을 의미한다.
이는 split() 메소드를 이용해 스트링을 잘라 배열로 변환하면 된다.
아래는 예제 코드다.
function csvToArray(str, delimiter = ",") {
// slice from start of text to the first \n index
// use split to create an array from string by delimiter
const headers = str.slice(0, str.indexOf("\n")).split(delimiter);
// slice from \n index + 1 to the end of the text
// use split to create an array of each csv value row
const rows = str.slice(str.indexOf("\n") + 1).split("\n");
}
headers와 rows 배열을 만들었으면, 이제는 배열을 객체로 변환할 차례다. 일단은, rows 배열을 매핑하면서 각 배열을 배열로 값들을 split() 하자.
그리고, reduce() 메서드를 이용해 각 headers를 프로퍼티의 이름으로 그리고 프로퍼티의 값으로 같은 인덱스의 values 데이터를 넣는다.
마지막으로 매핑된 열을 배열로 리턴한다. 코드는 아래와 같다.
function csvToArray(str, delimiter = ",") {
// slice from start of text to the first \n index
// use split to create an array from string by delimiter
const headers = str.slice(0, str.indexOf("\n")).split(delimiter);
// slice from \n index + 1 to the end of the text
// use split to create an array of each csv value row
const rows = str.slice(str.indexOf("\n") + 1).split("\n");
// Map the rows
// split values from each row into an array
// use headers.reduce to create an object
// object properties derived from headers:values
// the object passed as an element of the array
const arr = rows.map(function (row) {
const values = row.split(delimiter);
const el = headers.reduce(function (object, header, index) {
object[header] = values[index];
return object;
}, {});
return el;
});
// return the array
return arr;
}
이렇게 csvToArray() 함수 생성이 끝났으면, onload 이벤트에 해당 함수를 호출하기만 하면 된다.
reader.onload = function (e) {
const text = e.target.result;
const data = csvToArray(text);
document.write(JSON.stringify(data));
};
JavaScript - Parse CSV data into an array
Learn how to use JavaScript to convert CSV data into an array
sebhastian.com
'Javascript' 카테고리의 다른 글
[JS] 자바스크립트에서 불변성을 이용하는 경우 (0) | 2022.05.31 |
---|---|
[JS] 구루처럼 자바스크립트 작성하기 (0) | 2022.05.30 |
[JS] 자바스크립트로 유니크한 ID 생성하기 (0) | 2022.04.17 |
[Node.js] Node.js와 브라우저의 차이 (0) | 2022.03.23 |
[JS] String에서 Date 전환할 때 시간 변경 문제 (0) | 2022.03.22 |