← 전체 글

CSV와 XML을 JSON으로 변환하는 방법

JavaScript, Python, 브라우저에서 CSV와 XML을 JSON으로 변환. array-of-objects 매핑, XML 속성 처리, 타입 강제 변환 함정을 다룬다.

CSV와 XML은 어디에나 있습니다 —— 스프레드시트 내보내기, 레거시 API, 엔터프라이즈 피드 —— 그러나 대부분의 현대 코드는 JSON을 원합니다. 매핑 규칙과 함정(CSV에서는 모든 것이 문자열; XML 속성과 반복 요소는 특별한 처리가 필요)을 이해하면 변환은 단순합니다. 이 가이드는 JavaScript, Python, 브라우저에서의 양방향 변환을 다룹니다.

범위: 이 글은 CSV → JSON과 XML → JSON을 한곳에 모은 포괄적인 how-to입니다. XML 전용 —— 속성, 텍스트 노드, 반복 요소, 네임스페이스 심화 —— 가 필요하면 XML에서 JSON으로의 변환: 속성, 텍스트 노드, 배열, 네임스페이스 를 읽으세요. 역방향은 JSON에서 XML로.

CSV를 JSON으로 변환

CSV 파일은 쉼표로 구분된 값의 행 모음이며, 보통 헤더 행이 있습니다. 자연스러운 JSON 표현은 행마다 하나의 객체를 가지고 헤더를 키로 쓰는 객체 배열입니다:

# CSV
id,name,active
1,Ada,true
2,Bob,false
// JSON
[
  { "id": "1", "name": "Ada", "active": "true" },
  { "id": "2", "name": "Bob", "active": "false" }
]

모든 값이 문자열 임에 주의 —— CSV에는 타입이 없습니다. "1" 을 숫자로, "true" 를 불리언으로 변환하는 것은 의도적으로 해야 하는 별도의 강제 변환 단계입니다.

JavaScript에서 CSV → JSON

신뢰할 수 있고 단순한 CSV는 수동으로 split 해도 됩니다 —— 하지만 실제 CSV는 인용된 필드에 쉼표나 개행을 포함하므로, 프로덕션에서는 papaparse 같은 제대로 된 parser를 사용하세요:

// 최소 parser —— 단순, 인용 없는 CSV에만 안전
function csvToJson(csv) {
  const [header, ...rows] = csv.trim().split('\n');
  const keys = header.split(',');
  return rows.map((row) => {
    const values = row.split(',');
    return Object.fromEntries(keys.map((k, i) => [k, values[i]]));
  });
}

// 프로덕션 —— 인용, 내부 쉼표, 개행 처리
import Papa from 'papaparse';
const result = Papa.parse(csvText, { header: true, dynamicTyping: true });
// dynamicTyping 이 "1" → 1, "true" → true 로 자동 변환

Python에서 CSV → JSON

import csv, json

with open('data.csv', newline='') as f:
    rows = list(csv.DictReader(f))   # 헤더를 키로 쓰는 dict 리스트

print(json.dumps(rows, indent=2))

XML을 JSON으로 변환

XML은 까다롭습니다. JSON에 없는 개념인 속성, 텍스트 노드, 단일 vs 반복 요소가 있기 때문입니다. 단 하나의 '올바른' 매핑은 없으니, 규약을 하나 골라 일관되게 적용하세요.

<!-- XML -->
<user id="1">
  <name>Ada</name>
  <role>admin</role>
  <role>editor</role>
</user>
// 흔한 JSON 매핑
{
  "user": {
    "@id": "1",                    // 속성, @ 접두사
    "name": "Ada",                 // 단일 자식 → 값
    "role": ["admin", "editor"]    // 반복 자식 → 배열
  }
}

JavaScript에서 XML → JSON

import { XMLParser } from 'fast-xml-parser';

const parser = new XMLParser({ ignoreAttributes: false, attributeNamePrefix: '@' });
const obj = parser.parse(xmlString);
// 브라우저에서는 DOMParser를 쓰고 노드 트리를 수동으로 걸어도 됩니다.

Python에서 XML → JSON

import xmltodict, json

doc = xmltodict.parse(xml_string)   # 속성은 "@name" 키가 됨
print(json.dumps(doc, indent=2))

조심해야 할 매핑 함정

  • 타입이 사라진다. CSV와 XML 값은 문자열로 도착합니다. 숫자와 불리언은 명시적으로 변환하세요 —— parser가 알아서 했다고 가정하지 마세요.
  • 단일 vs 반복 요소. <role> 하나는 값이 되고, 둘은 배열이 됩니다. 소비자가 놀라지 않도록 어떤 필드를 항상 배열로 처리할지 결정하세요.
  • 속성 vs 자식 요소.접두사 규약을 선택하고(일반적으로 @) 문서화하세요.
  • 빈 값과 공백. 빈 XML 요소와 후행 CSV 쉼표는 parser에 따라 null, "", 또는 키 누락을 만들 수 있습니다.

BOM과 인코딩의 변덕

Excel과 일부 Windows 도구에서 내보낸 파일은 UTF-8 BOM(0xEF 0xBB 0xBF)으로 시작합니다. 파싱 전에 제거하지 않으면 첫 번째 헤더/요소 이름에 조용히 포함됩니다. RFC 8259는 JSON 시작 부분의 BOM을 금지하므로, 직접 만든 변환기는 입력에서 제거할 뿐 출력에 복사해선 안 됩니다.

TSV vs CSV(및 기타 구분자)

'CSV'가 항상 쉼표 구분은 아닙니다. 탭으로 구분된 값(TSV)은 엔지니어링 파이프라인에서 흔합니다. 탭은 값 안에 거의 나타나지 않아 인용 처리를 생략할 수 있기 때문입니다. 유럽판 Excel 내보내기는 종종 ; 을 씁니다. 출력이 이상한 한 칸에 뭉쳐 보인다면, 파일이 parser가 기대하는 것과 다른 구분자를 쓰는 겁니다 —— 구분자를 바꾸거나 자동 감지 라이브러리를 쓰세요.

XML 네임스페이스

XML 요소는 네임스페이스 접두사로 한정될 수 있고(예: <soap:Envelope>), 이는 xmlns 선언으로 묶입니다. JSON에는 네임스페이스 개념이 없으므로 대부분의 변환기는 세 가지 중 하나를 택합니다: 접두사를 키에 유지("soap:Envelope"), 제거, 혹은 xmlns 선언을 @xmlns:* 속성으로 저장. 접두사 유지가 무손실의 유일한 옵션입니다. 자세한 내용은 XML에서 JSON으로의 변환.

결과를 검증하고 포맷팅

변환 후, 출력이 잘 형성되고 읽기 쉬운지 확인합니다:

자주 묻는 질문

CSV를 JSON으로 어떻게 변환하나요?

CSV를 행으로 파싱하고 각 행을 헤더를 키로 한 객체로 매핑하세요 —— Python에서는 csv.DictReader, JavaScript에서는 papaparse 같은 라이브러리. 모든 값은 처음엔 문자열입니다; 타입 변환은 직접 하세요.

왜 CSV에서 JSON으로 변환된 값이 모두 문자열인가요?

CSV는 타입이 없습니다 —— 모든 필드가 텍스트입니다. 타입 자동 변환을 켜거나(예: papaparse의 dynamicTyping), 파싱 후 숫자와 불리언을 명시적으로 변환하세요.

XML을 JSON으로 변환할 때 XML 속성은 어떻게 다루나요?

대부분의 변환기는 속성을 @ 같은 접두사를 가진 키로 매핑합니다(예: @id). 규약을 정하고 일관되게 적용하면, 하류 코드가 어디를 봐야 할지 압니다.

왜 XML→JSON 출력이 때로는 객체, 때로는 배열인가요?

단일 자식 요소는 값으로, 반복 요소는 배열로 매핑됩니다. 소비자가 일관된 형상을 기대한다면 특정 요소를 항상 배열로 처리하도록 parser를 설정하세요.

브라우저에서 변환·검증·포맷팅