CSV와 JSON은 개발자로서 만나게 될 두 가지 가장 일반적인 데이터 형식입니다. CSV 파일은 스프레드시트 내보내기, 데이터베이스 덤프, 데이터 과학 파이프라인에서 나타납니다. JSON은 웹 어디서나 — REST API, 설정 파일, NoSQL 데이터베이스. 둘 다 일반 텍스트이고, 둘 다 사람이 읽을 수 있으며, 둘 다 작업을 완수합니다. 하지만 서로 다른 형태의 데이터를 위해 만들어졌으며, 잘못된 것을 선택하면 실제로 골치가 아파집니다. 이 글에서는 핵심 차이점을 살펴보고, 각 형식이 빛나는(그리고 무너지는) 구체적인 예시를 보여주며, 선택을 위한 실용적인 결정 가이드를 제공합니다.

핵심 차이점: 표 vs 트리

CSV — RFC 4180에 정의됨 — 는 평탄한 표형식입니다. 모든 행은 같은 열을 가지고, 모든 값은 문자열입니다. 그게 전부입니다. 스프레드시트나 데이터베이스 테이블에 완벽하게 매핑됩니다: 행은 아래로, 열은 옆으로.

JSON — RFC 8259에 명세되고 json.org에 설명됨 — 는 계층적 형식입니다. 값은 객체, 배열, 문자열, 숫자, 불리언, 또는 null이 될 수 있습니다. 객체가 객체 안에 중첩되고, 배열이 다양한 형태를 담습니다. 코드에서 데이터가 실제로 존재하는 방식에 매핑됩니다 — 관계가 있는 레코드, 다양한 것들의 목록, 유형이 있는 값.

한 줄 요약: CSV는 표입니다. JSON은 트리입니다. 데이터가 표라면 CSV가 더 간단하고 작습니다. 데이터에 중첩이 있다면, CSV는 정보를 잃거나 고통스러운 해결 방법을 강요할 것입니다.

두 형식에서의 동일한 데이터

여기서 차이가 구체적으로 드러납니다. 전자 상거래 스토어의 제품 카탈로그를 상상해 보세요. 제품에는 이름, 가격, 재고 여부 — 간단합니다. 하지만 변형(사이즈, 색상)과 속성(재질, 무게)도 있습니다. 두 형식에서 이 데이터가 어떻게 보이는지 살펴봅시다.

JSON에서 이것은 자연스럽습니다:

json
[
  {
    "id": "SHOE-001",
    "name": "Trail Runner Pro",
    "price": 129.99,
    "inStock": true,
    "attributes": {
      "material": "mesh",
      "weightGrams": 280
    },
    "variants": [
      { "size": 9,  "color": "black", "sku": "TR-9-BLK",  "qty": 12 },
      { "size": 9,  "color": "white", "sku": "TR-9-WHT",  "qty": 4  },
      { "size": 10, "color": "black", "sku": "TR-10-BLK", "qty": 7  }
    ]
  },
  {
    "id": "SHOE-002",
    "name": "City Walker",
    "price": 89.99,
    "inStock": true,
    "attributes": {
      "material": "leather",
      "weightGrams": 340
    },
    "variants": [
      { "size": 8,  "color": "brown", "sku": "CW-8-BRN",  "qty": 6  },
      { "size": 9,  "color": "brown", "sku": "CW-9-BRN",  "qty": 15 }
    ]
  }
]

이것을 CSV에 넣어보세요. 두 가지 선택이 있으며, 둘 다 어색합니다. 옵션 1: 모든 것을 평탄화하고 각 변형 행에 부모 데이터를 반복합니다:

csv
product_id,product_name,price,inStock,material,weightGrams,variant_size,variant_color,sku,qty
SHOE-001,Trail Runner Pro,129.99,true,mesh,280,9,black,TR-9-BLK,12
SHOE-001,Trail Runner Pro,129.99,true,mesh,280,9,white,TR-9-WHT,4
SHOE-001,Trail Runner Pro,129.99,true,mesh,280,10,black,TR-10-BLK,7
SHOE-002,City Walker,89.99,true,leather,340,8,brown,CW-8-BRN,6
SHOE-002,City Walker,89.99,true,leather,340,9,brown,CW-9-BRN,15

제품 이름, 가격, 속성이 모든 변형에 반복됩니다. 데이터 중복입니다 — 5개 행에는 큰 문제가 아니지만, 변형이 8개인 제품 50,000개 카탈로그에서는 쌓입니다. 옵션 2: CSV 열 안에 변형을 JSON 문자열로 직렬화합니다 — 하지만 이제 CSV의 한계를 해결하기 위해 CSV 안에 JSON을 삽입하고 있는데, 이것은 코드 냄새 그 자체입니다.

CSV가 이기는 곳

그 한계에도 불구하고, CSV는 여러 일반적인 시나리오에서 진정한 더 나은 선택입니다.

  • 스프레드시트와 BI 도구. Excel, Google Sheets, Tableau, Looker, Power BI — 모두 클릭 한 번으로 CSV를 네이티브로 엽니다. 가져오기 마법사도, 정의할 스키마도, 변환 단계도 없습니다. 관계자들이 스프레드시트에서 생활한다면, CSV가 최소 저항의 길입니다.
  • 순수한 평탄 데이터. 데이터가 진정으로 표형식이라면 — 분석 이벤트, 거래 로그, 센서 읽기, 사용자 내보내기 — CSV는 더 작고 단순합니다. 반복 키 없음, 괄호 없음, 노이즈 없음.
  • 데이터베이스 가져오기/내보내기. 모든 SQL 데이터베이스에는 COPY FROM CSV 또는 동등한 명령어가 있습니다. 대량 데이터 로딩을 위한 표준 교환 형식이며 INSERT 문보다 수십 배 빠릅니다.
  • pandas와 데이터 과학. pandas.read_csv()는 Python 데이터 작업에서 가장 많이 사용되는 함수 중 하나입니다. 전체 생태계 — NumPy, scikit-learn, Polars — 가 CSV를 1등급 입력 형식으로 취급합니다.
  • 대형 평탄 표의 파일 크기. 모든 행에 키 이름 없이, CSV는 많은 행이 있는 넓은 표에 대해 더 작습니다. 분석 이벤트 100만 행 CSV는 동등한 JSON 배열보다 편안하게 이길 것입니다.

JSON이 이기는 곳

  • 중첩 및 계층적 데이터. 데이터에 평탄한 표 이상의 구조가 있자마자 — 중첩 객체, 다양한 형태의 배열, 관련 레코드 — JSON이 자연스럽게 처리합니다. CSV는 정보 손실이나 중복 없이 이것을 표현할 수 없습니다.
  • 유형 보존. CSV에서 모든 것은 문자열입니다. true, 42, null, "true"가 모두 같아 보입니다. 수신 측에서 유형을 추론해야 하며, 이는 버그로 이어집니다. JSON에는 네이티브 불리언, 숫자, null이 있습니다. inStock: true는 명확하게 불리언입니다 — 추측 없이.
  • REST API와 웹. JSON은 웹의 네이티브 데이터 형식입니다. 모든 HTTP 클라이언트 라이브러리, 모든 브라우저의 Fetch API, 모든 REST 및 GraphQL API가 JSON을 사용합니다. HTTP를 통해 CSV를 보내는 것은 가능하지만 특이합니다 — 양 끝에서 커스텀 파싱이 필요합니다.
  • NoSQL 데이터베이스. MongoDB, DynamoDB, Firestore, Elasticsearch, CouchDB — 모두 JSON(또는 BSON 같은 이진 수퍼셋)을 네이티브 문서 형식으로 사용합니다. JSON을 넣고 JSON을 받습니다.
  • 설정 파일. package.json, tsconfig.json, manifest.json — 도구 설정은 JSON에 표준화되었습니다. 중첩 구조를 지원하고 프로그래밍 방식으로 생성하고 검증하기 쉽기 때문입니다.
  • 스키마 검증. JSON Schema를 사용하면 문서의 정확한 형태를 정의하고 데이터를 검증할 수 있습니다 — 유형 검사, 필수 필드, 패턴 매칭, 배열 제약. CSV에는 동등한 표준이 없습니다.

파일 크기: 실제 이야기

"CSV가 더 작다"는 주장은 하나의 특정 경우에 맞습니다: 많은 행이 있는 대형 평탄 표. 각각 8개의 고정 필드가 있는 분석 이벤트 100,000개를 생각해 보세요. CSV에서 필드 이름은 헤더에 한 번 나타납니다. JSON에서는 모든 객체에 나타납니다. 그 반복이 쌓입니다 — JSON 배열은 동등한 CSV보다 30–50% 더 클 수 있습니다.

하지만 중첩 데이터로 시나리오를 뒤집으면 수학이 달라집니다. 신발 카탈로그의 평탄화된 CSV는 모든 변형 행에 제품 이름, 가격, 속성을 반복합니다. JSON 버전은 각 제품을 한 번 저장합니다. 많은 반복 부모 필드가 있는 깊이 중첩된 데이터의 경우, JSON이 실제로 더 작을 수 있습니다.

실제로 파일 크기가 진짜 문제라면, 두 형식 모두 gzip으로 매우 잘 압축됩니다 — JSON의 반복 키 이름과 CSV의 반복 행 값 모두 크게 압축됩니다. HTTP를 통해 gzip 압축된 JSON을 제공하는 것은 표준 관행이며, 크기 차이는 보통 압축 후 무시할 수 있는 수준이 됩니다.

도구 비교

각 형식의 도구 이야기는 가장 많이 사용되는 곳을 반영합니다.

CSV 도구: Excel, Google Sheets, LibreOffice Calc가 네이티브로 엽니다. pandas 라이브러리는 Python에서 데이터 분석의 기본으로 CSV를 만듭니다. 모든 관계형 데이터베이스에는 CSV 가져오기/내보내기 명령어가 있습니다. csvkitxsv 같은 명령행 도구를 사용하면 코드 없이 CSV 파일을 필터링, 조인, 집계할 수 있습니다. MIME 유형은 text/csv로 IANA에 등록되어 있습니다.

JSON 도구: 모든 프로그래밍 언어에는 내장 또는 표준 라이브러리 JSON 파서가 있습니다. JavaScript의 JSON.parse(), Python의 json.loads(), Go의 encoding/json, Rust의 serde_json. MDN JSON 레퍼런스는 MDN에서 가장 많이 방문하는 페이지 중 하나입니다. 명령행: jq는 JSON 쿼리 및 변환에 필수적입니다. IDE는 자동으로 pretty-print하고 검증합니다.

두 세계에 걸친 데이터 파이프라인으로 작업 중이라면 — JSON API 응답을 데이터 웨어하우스에 로드하거나, 데이터베이스 레코드를 스프레드시트로 내보내는 — 정기적으로 두 형식 간에 변환해야 할 것입니다. CSV를 JSON으로 변환기JSON을 CSV로 변환기가 빠르게 처리합니다. 처리 전에 원시 파일을 정리하려면 CSV 포매터JSON 포매터를 북마크해 두세요.

하이브리드: JSON Lines (NDJSON)

알아둘 가치가 있는 세 번째 옵션이 있습니다: JSON Lines, NDJSON (줄바꿈으로 구분된 JSON)이라고도 합니다. 아이디어는 간단합니다 — 줄당 하나의 완전한 JSON 객체, 감싸는 배열 없음.

json
{"id":"SHOE-001","name":"Trail Runner Pro","price":129.99,"inStock":true,"variantCount":3}
{"id":"SHOE-002","name":"City Walker","price":89.99,"inStock":true,"variantCount":2}
{"id":"SHOE-003","name":"Summit Hiker","price":159.99,"inStock":false,"variantCount":5}

이 형식은 특정 사용 사례에서 두 세계의 장점을 얻을 수 있습니다. CSV처럼, 전체 파일을 메모리에 로드하지 않고 줄 단위로 스트리밍하고 처리할 수 있습니다 — 대형 로그 파일이나 데이터 파이프라인 출력에 중요합니다. JSON처럼, 각 줄은 다른 스키마를 가질 수 있고 유형을 보존합니다. 표준 Unix 도구(grep, wc -l, head)로 작업할 수 있지만, 구조적 쿼리를 위해 각 줄을 jq를 통해 파이프할 수도 있습니다.

NDJSON은 로그 집계(많은 구조화된 로거의 기본 출력 형식), 데이터 파이프라인 단계, ML 훈련 데이터 내보내기에 널리 사용됩니다. 각 레코드가 JSON 객체인 수백만 레코드를 처리하는 스크립트를 작성한다면, NDJSON이 보통 거대한 JSON 배열보다 올바른 선택입니다 — 전체를 메모리에 로드하지 않아도 되고 체크포인트에서 재개할 수 있습니다.

python
import json

# Process a large NDJSON file without loading it all into memory
with open('products.ndjson', 'r') as f:
    for line in f:
        product = json.loads(line.strip())
        if product['inStock'] and product['price'] < 100:
            print(f"{product['name']} — ${product['price']}")

결정 가이드: CSV vs JSON

실용적인 버전이 있습니다. 둘 중 하나를 선택할 때 스스로에게 이 질문들을 하세요:

  • 데이터가 진정으로 평탄한가(중첩 없음, 배열 없음)? 그렇다면 CSV가 더 간단합니다. 아니라면 JSON.
  • 비개발자가 이 파일을 소비할 것인가? Excel의 분석가? Google Sheets의 비즈니스 사용자? CSV를 사용하세요.
  • HTTP API를 제공하거나 소비하는가? JSON을 사용하세요. 단호하게.
  • 대량 데이터베이스 가져오기 또는 내보내기를 하는가? CSV를 사용하세요 — 모든 데이터베이스가 네이티브로 지원합니다.
  • 데이터에 혼합 유형(불리언, 숫자, null)이 있는가? 수신 측에서 유형 추론 버그를 피하기 위해 JSON을 사용하세요.
  • 파일을 스트리밍 파이프라인에서 행 단위로 처리할 것인가? 중간 지점으로 NDJSON을 고려하세요.
  • 설정을 저장하는가? JSON을 사용하세요(또는 주석이 중요하다면 YAML).
  • 레코드마다 스키마가 달라질 필요가 있는가? JSON. CSV는 모든 행에 같은 열을 강제합니다.
솔직한 기본값: 다른 개발자나 기계가 소비할 무언가를 만들고 있다면 JSON을 사용하세요. 스프레드시트에서 열 사람에게 데이터를 전달한다면 CSV를 사용하세요. 각 레코드가 JSON 객체인 수백만 구조화된 레코드를 처리하는 데이터 파이프라인을 만든다면 NDJSON을 고려하세요.

마무리

CSV와 JSON은 실제로 경쟁하지 않습니다 — 서로 다른 문제를 해결합니다. CSV는 데이터가 표형식이고 스프레드시트 및 데이터베이스 도구와의 최대 호환성을 원할 때 적합한 도구입니다. JSON은 데이터에 구조, 유형, 또는 중첩이 있고 API나 애플리케이션과 통신할 때 적합한 도구입니다.

데이터의 실제 형태를 보면 결정이 보통 어렵지 않습니다. 센서 읽기의 평탄한 행? CSV. 중첩된 사용자 프로필과 내장된 주문 이력이 있는 API 응답? JSON. 구조화된 이벤트의 스트리밍 로그? NDJSON. 데이터의 형태와 양 끝의 도구에 형식을 맞추면 거의 틀리지 않을 것입니다.