DevToolBox무료
블로그

CSV to JSON 변환기 완전 가이드: 코드 예제 포함

11분 읽기by DevToolBox

CSV에서 JSON으로의 변환은 개발자가 매일 직면하는 가장 일반적인 데이터 변환 작업 중 하나입니다. 시스템 간 데이터 마이그레이션, API 구축, 스프레드시트 처리 등 CSV를 JSON으로 변환하는 방법을 효율적으로 아는 것은 필수적입니다. 이 종합 가이드에서는 변환 도구, 파싱 알고리즘, JavaScript, Python, Bash 코드 예제 및 엣지 케이스 처리 모범 사례를 다룹니다.

무료 온라인 CSV to JSON 변환 도구를 사용해 보세요.

CSV란 무엇인가?

CSV는 Comma-Separated Values(쉼표로 구분된 값)의 약자로, RFC 4180에서 정의한 테이블 형식 데이터를 저장하는 일반 텍스트 파일 형식입니다. 각 행은 레코드를 나타내며, 값은 쉼표나 다른 구분자로 구분됩니다. 첫 번째 행은 일반적으로 헤더 역할을 합니다.

CSV 형식은 컴퓨팅 초기부터 사용되어 왔으며 단순함 때문에 여전히 인기가 있습니다. 모든 텍스트 편집기, 스프레드시트, 프로그래밍 언어에서 CSV를 읽고 쓸 수 있습니다. 단순하지만 CSV 파서는 인용 필드, 이스케이프된 따옴표, 여러 줄 값 등 까다로운 경우를 처리해야 합니다.

CSV와 JSON 사용 시기: CSV는 스프레드시트 내보내기, 데이터베이스 덤프 등 플랫 테이블 데이터에 적합합니다. JSON은 계층적 데이터 구조, API 응답, 설정 파일에 더 좋습니다.

CSV vs JSON: 상세 비교

CSV와 JSON의 차이를 이해하면 올바른 형식 선택과 변환 프로세스 이해에 도움이 됩니다:

특징CSVJSON
구조플랫, 테이블 형식계층적 (중첩 객체)
가독성간단한 데이터는 쉬움포맷팅하면 읽기 쉬움
중첩네이티브 미지원완전 지원
데이터 타입모두 문자열문자열, 숫자, 불리언, null, 배열, 객체
파일 크기일반적으로 작음더 큼 (키 반복)
사용 사례스프레드시트, DB 내보내기API, 설정, NoSQL, 웹앱

CSV에서 JSON 변환 작동 원리

CSV to JSON 변환기 프로세스는 여러 단계를 포함합니다:

  1. 헤더 행 읽기: 열 이름을 추출하여 JSON 키로 사용.
  2. 각 데이터 행 파싱: 구분자로 분할하고 값을 헤더에 매핑.
  3. 인용 필드 처리: 큰따옴표로 둘러싼 값은 쉼표나 줄바꿈이 있어도 하나의 필드.
  4. 데이터 타입 감지: 숫자, 불리언, null 값 자동 변환.
  5. JSON 배열 구축: 각 행이 객체가 되고 모두 배열에 수집.

예시: CSV name,age,active\nAlice,30,true[{"name":"Alice","age":30,"active":true}]가 됩니다.

CSV to JSON 코드 예제

JavaScript: CSV to JSON 변환

CSV to JSON JavaScript 변환의 여러 접근법: 네이티브, Papa Parse, Node.js csv-parser:

// ===== Native JavaScript: CSV to JSON =====

function csvToJson(csv) {
  const lines = csv.trim().split('\n');
  const headers = lines[0].split(',').map(h => h.trim());
  const result = [];

  for (let i = 1; i < lines.length; i++) {
    const values = lines[i].split(',');
    const obj = {};
    headers.forEach((header, index) => {
      let val = values[index]?.trim() || '';
      // Auto-detect types
      if (val === 'true') val = true;
      else if (val === 'false') val = false;
      else if (val === 'null' || val === '') val = null;
      else if (!isNaN(val) && val !== '') val = Number(val);
      obj[header] = val;
    });
    result.push(obj);
  }
  return result;
}

const csv = `name,age,city,active
Alice,30,New York,true
Bob,25,London,false
Charlie,35,Tokyo,true`;

console.log(JSON.stringify(csvToJson(csv), null, 2));
// [
//   { "name": "Alice", "age": 30, "city": "New York", "active": true },
//   { "name": "Bob", "age": 25, "city": "London", "active": false },
//   { "name": "Charlie", "age": 35, "city": "Tokyo", "active": true }
// ]

// ===== Papa Parse (Browser & Node.js) =====
// npm install papaparse

import Papa from 'papaparse';

// Parse CSV string
const result = Papa.parse(csvString, {
  header: true,         // Use first row as keys
  dynamicTyping: true,  // Auto-detect numbers and booleans
  skipEmptyLines: true, // Ignore blank lines
});

console.log(result.data);   // Array of JSON objects
console.log(result.errors); // Any parsing errors
console.log(result.meta);   // Metadata (delimiter, fields, etc.)

// Parse CSV file (browser)
const fileInput = document.querySelector('input[type="file"]');
fileInput.addEventListener('change', (e) => {
  Papa.parse(e.target.files[0], {
    header: true,
    dynamicTyping: true,
    complete: (results) => {
      console.log(results.data); // JSON array
    },
  });
});

// ===== Node.js: csv-parser (streaming) =====
// npm install csv-parser

const csvParser = require('csv-parser');
const fs = require('fs');

const results = [];
fs.createReadStream('data.csv')
  .pipe(csvParser())
  .on('data', (row) => results.push(row))
  .on('end', () => {
    console.log(JSON.stringify(results, null, 2));
  });

Python: CSV to JSON 변환

CSV to JSON Python 변환: csv 모듈, pandas, json.dumps:

# ===== Python csv module =====
import csv
import json

# CSV string to JSON
csv_string = """name,age,city,active
Alice,30,New York,true
Bob,25,London,false"""

reader = csv.DictReader(csv_string.strip().splitlines())
data = list(reader)
json_output = json.dumps(data, indent=2)
print(json_output)

# CSV file to JSON file
with open('input.csv', 'r', encoding='utf-8') as csv_file:
    reader = csv.DictReader(csv_file)
    data = list(reader)

with open('output.json', 'w', encoding='utf-8') as json_file:
    json.dump(data, json_file, indent=2, ensure_ascii=False)

# ===== pandas (recommended for large datasets) =====
import pandas as pd

# CSV to JSON with pandas
df = pd.read_csv('data.csv')

# Different JSON orientations
print(df.to_json(orient='records', indent=2))  # Array of objects
print(df.to_json(orient='columns', indent=2))  # Object of arrays
print(df.to_json(orient='index', indent=2))     # Object keyed by index

# With type conversion
df['age'] = pd.to_numeric(df['age'], errors='coerce')
df['active'] = df['active'].map({'true': True, 'false': False})

# Save to file
df.to_json('output.json', orient='records', indent=2, force_ascii=False)

# ===== Streaming large CSV files =====
import csv
import json

def csv_to_json_stream(csv_path, json_path, chunk_size=1000):
    """Convert large CSV to JSON using streaming."""
    with open(json_path, 'w') as out:
        out.write('[\n')
        with open(csv_path, 'r', encoding='utf-8') as f:
            reader = csv.DictReader(f)
            first = True
            for row in reader:
                if not first:
                    out.write(',\n')
                json.dump(row, out, ensure_ascii=False)
                first = False
        out.write('\n]')

csv_to_json_stream('large_file.csv', 'output.json')

Bash / 커맨드 라인: CSV to JSON

커맨드 라인에서 csvkit, miller, jq, awk로 변환:

# ===== csvkit: csvjson command =====
# pip install csvkit

# Basic CSV to JSON conversion
csvjson data.csv > output.json

# Indent output for readability
csvjson --indent 2 data.csv > output.json

# Specify a key column (creates object instead of array)
csvjson --key id data.csv > output.json

# ===== miller (mlr): powerful data processing =====
# brew install miller (macOS) or apt install miller (Linux)

# CSV to JSON
mlr --icsv --ojson cat data.csv > output.json

# CSV to JSON with filtering
mlr --icsv --ojson filter '$age > 25' data.csv

# CSV to JSON with field selection
mlr --icsv --ojson cut -f name,city data.csv

# ===== jq + awk: lightweight approach =====
# Convert simple CSV to JSON with awk
awk -F',' 'NR==1{split($0,h);next}
{printf "{";for(i=1;i<=NF;i++)
printf "%s\"%s\":\"%s\"",
(i>1?",":""),h[i],$i;print "}"}' data.csv | jq -s '.'

# ===== Using sed + jq for quick conversion =====
# Convert CSV to JSON (simple, no quoted fields)
head -1 data.csv | tr ',' '\n' > /tmp/headers.txt
tail -n +2 data.csv | while IFS=',' read -r col1 col2 col3; do
  jq -n --arg a "$col1" --arg b "$col2" --arg c "$col3" \
    '{name:$a, age:($b|tonumber), city:$c}'
done | jq -s '.'

전용 CLI 도구: csvjson과 miller

csvjson(csvkit)과 miller(mlr)는 데이터 형식 변환 전용 커맨드 라인 도구입니다:

# ===== csvkit: full suite of CSV tools =====
# pip install csvkit

# View CSV statistics
csvstat data.csv

# Convert CSV to JSON
csvjson data.csv

# Convert Excel to CSV first, then to JSON
in2csv data.xlsx | csvjson > output.json

# Query CSV with SQL syntax, output as JSON
csvsql --query "SELECT name, age FROM data WHERE age > 25" data.csv | csvjson

# ===== miller (mlr): Swiss Army knife for data =====

# CSV to JSON (pretty-printed)
mlr --icsv --ojson --jflatsep '.' cat data.csv

# CSV to JSON with data transformation
mlr --icsv --ojson put '$full_name = $first . " " . $last' data.csv

# CSV to NDJSON (newline-delimited JSON, one object per line)
mlr --icsv --ojsonl cat data.csv

# Convert between any formats
mlr --icsv --ojson cat data.csv       # CSV -> JSON
mlr --ijson --ocsv cat data.json      # JSON -> CSV
mlr --icsv --otsv cat data.csv        # CSV -> TSV
mlr --itsv --ojson cat data.tsv       # TSV -> JSON

JSON to CSV 변환 (역방향 프로세스)

역방향 프로세스인 JSON to CSV는 계층적 JSON 데이터를 플랫 테이블 구조로 변환합니다.

중첩 객체 플랫화: 점 표기법이나 밑줄로 펼침: user.name, user.address.city.

JavaScript와 Python에서의 JSON to CSV 변환 예제:

// ===== JavaScript: JSON to CSV =====

function jsonToCsv(jsonArray) {
  if (!jsonArray.length) return '';

  // Flatten nested objects
  function flatten(obj, prefix = '') {
    return Object.keys(obj).reduce((acc, key) => {
      const fullKey = prefix ? prefix + '.' + key : key;
      if (typeof obj[key] === 'object' && obj[key] !== null && !Array.isArray(obj[key])) {
        Object.assign(acc, flatten(obj[key], fullKey));
      } else if (Array.isArray(obj[key])) {
        acc[fullKey] = obj[key].join('|'); // Join arrays with pipe
      } else {
        acc[fullKey] = obj[key];
      }
      return acc;
    }, {});
  }

  const flatData = jsonArray.map(item => flatten(item));
  const headers = [...new Set(flatData.flatMap(Object.keys))];

  const csvRows = [headers.join(',')];
  for (const row of flatData) {
    const values = headers.map(h => {
      const val = row[h] ?? '';
      // Quote values containing commas, quotes, or newlines
      const str = String(val);
      return str.includes(',') || str.includes('"') || str.includes('\n')
        ? '"' + str.replace(/"/g, '""') + '"'
        : str;
    });
    csvRows.push(values.join(','));
  }
  return csvRows.join('\n');
}

// Example with nested JSON
const data = [
  { name: "Alice", address: { city: "NYC", zip: "10001" }, tags: ["dev", "admin"] },
  { name: "Bob", address: { city: "London", zip: "EC1A" }, tags: ["user"] },
];
console.log(jsonToCsv(data));
// name,address.city,address.zip,tags
// Alice,NYC,10001,dev|admin
// Bob,London,EC1A,user
# ===== Python: JSON to CSV =====
import json
import csv
import pandas as pd

# Method 1: pandas (easiest)
with open('data.json') as f:
    data = json.load(f)

df = pd.json_normalize(data, sep='.')  # Flatten nested objects
df.to_csv('output.csv', index=False)

# Method 2: csv module (manual control)
def json_to_csv(json_data, csv_path):
    """Convert JSON array to CSV, handling nested objects."""
    flat_data = [flatten_dict(item) for item in json_data]
    fieldnames = list(dict.fromkeys(
        key for item in flat_data for key in item.keys()
    ))

    with open(csv_path, 'w', newline='', encoding='utf-8') as f:
        writer = csv.DictWriter(f, fieldnames=fieldnames)
        writer.writeheader()
        writer.writerows(flat_data)

def flatten_dict(d, parent_key='', sep='.'):
    items = []
    for k, v in d.items():
        new_key = f"{parent_key}{sep}{k}" if parent_key else k
        if isinstance(v, dict):
            items.extend(flatten_dict(v, new_key, sep).items())
        elif isinstance(v, list):
            items.append((new_key, '|'.join(str(i) for i in v)))
        else:
            items.append((new_key, v))
    return dict(items)

CSV 파싱 엣지 케이스 처리

견고한 CSV 파서는 수많은 엣지 케이스를 처리해야 합니다:

UTF-8 BOM: 일부 애플리케이션이 파일 시작에 보이지 않는 BOM을 추가합니다. 파서가 이를 제거해야 합니다.

구분자 변형: 유럽에서는 세미콜론, TSV에서는 탭. 좋은 파서는 자동 감지합니다.

누락된 값과 빈 필드: 후행 쉼표나 중간의 빈 필드. 빈 문자열이나 null로 유지해야 합니다.

여러 줄 필드: RFC 4180은 큰따옴표 안의 여러 줄 값을 허용합니다.

특수 문자와 이스케이프: 인용 필드 내 큰따옴표는 두 번 써서 이스케이프합니다.

불일치하는 행 길이: 견고한 파서는 짧은 행을 빈 값으로 채우거나 긴 행을 자릅니다.

// Robust CSV parser handling all edge cases
function parseCSV(text, delimiter = ',') {
  // Strip UTF-8 BOM if present
  if (text.charCodeAt(0) === 0xFEFF) {
    text = text.slice(1);
  }

  const rows = [];
  let row = [];
  let field = '';
  let inQuotes = false;

  for (let i = 0; i < text.length; i++) {
    const char = text[i];
    const next = text[i + 1];

    if (inQuotes) {
      if (char === '"' && next === '"') {
        field += '"'; // Escaped quote
        i++;          // Skip next quote
      } else if (char === '"') {
        inQuotes = false; // End of quoted field
      } else {
        field += char; // Regular char inside quotes
      }
    } else {
      if (char === '"') {
        inQuotes = true; // Start quoted field
      } else if (char === delimiter) {
        row.push(field);
        field = '';
      } else if (char === '\n' || (char === '\r' && next === '\n')) {
        row.push(field);
        rows.push(row);
        row = [];
        field = '';
        if (char === '\r') i++; // Skip \n in \r\n
      } else {
        field += char;
      }
    }
  }

  // Push last field and row
  if (field || row.length) {
    row.push(field);
    rows.push(row);
  }

  return rows;
}

CSV 모범 사례

최대 호환성과 데이터 무결성을 위해 다음 모범 사례를 따르세요:

항상 UTF-8 인코딩 사용: 텍스트 인코딩의 유니버설 표준.

필드를 일관되게 인용: 가장 안전한 것은 모든 필드를 인용하는 것.

헤더 행 포함: 설명적인 이름과 일관된 명명 규칙으로.

일관된 구분자 사용: 파일 전체에 하나의 구분자.

큰 파일은 스트림 처리: 메모리를 초과하는 파일에 스트리밍 파서 사용.

변환 후 데이터 검증: 레코드 수, 데이터 타입, 무결성 확인.

자주 묻는 질문

CSV를 JSON으로 변환하려면?

헤더 행을 파싱하여 열 이름을 얻고, 각 행을 해당 키에 매핑합니다. Papa Parse(JavaScript)나 pandas(Python) 등의 라이브러리 또는 무료 온라인 도구를 사용할 수 있습니다.

CSV와 JSON의 차이점은?

CSV는 모든 값이 문자열인 플랫 테이블 형식입니다. JSON은 중첩 객체, 배열, 다양한 데이터 타입을 지원하는 계층적 형식입니다. CSV는 더 컴팩트하고, JSON은 더 표현력이 풍부합니다.

CSV는 중첩된 데이터를 처리할 수 있나요?

아닙니다. CSV는 네이티브로 중첩 구조를 지원하지 않습니다. 점 표기법, CSV 필드 내 JSON 인코딩, 별도의 CSV 파일 등으로 데이터를 플랫화해야 합니다.

CSV to JSON 변환은 개발자와 데이터 분석가의 기본 기술입니다. 무료 도구로 즉시 변환하세요.

무료 온라인 도구로 CSV와 JSON을 즉시 변환하세요.

𝕏 Twitterin LinkedIn
도움이 되었나요?

최신 소식 받기

주간 개발 팁과 새 도구 알림을 받으세요.

스팸 없음. 언제든 구독 해지 가능.

Try These Related Tools

📊CSV ↔ JSON Converter{ }JSON FormatterY{}JSON ↔ YAML Converter<>XML Formatter

Related Articles

JSON vs YAML vs TOML: 어떤 설정 포맷을 사용해야 할까?

JSON, YAML, TOML 설정 포맷을 비교합니다.

JSON 포매터 & 검증기: 온라인 포맷, 검증 완전 가이드

무료 온라인 JSON 포매터와 검증기. JSON 정리, 구문 오류 찾기, JavaScript와 Python 코드 예제.

JSON에서 TypeScript로: 예제와 함께하는 완벽 가이드

JSON 데이터를 TypeScript 인터페이스로 자동 변환하는 방법을 배웁니다. 중첩 객체, 배열, 선택적 필드, 모범 사례를 다룹니다.