DevToolBoxFREE
BlogAdvertise

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을 즉시 변환하세요.

도움이 되었나요?

Stay Updated

Get weekly dev tips and new tool announcements.

No spam. Unsubscribe anytime.

Partner Picks

Sponsor this article

Place your product next to this developer topic with tracked clicks.

Ask about article sponsorship

This site uses cookies for analytics and to display ads. By continuing to browse, you agree. Privacy Policy