← 블로그 목록

CSV 완벽 가이드: 데이터 교환의 표준 형식

CSV의 기초부터 파싱, 인코딩 처리까지. 엑셀과 데이터베이스 간 데이터 교환을 완벽히 이해하세요.

CSV, 가장 간단하면서도 복잡한 데이터 형식

CSV(Comma Separated Values)는 쉼표로 구분된 값들의 형식입니다. 엑셀, Google Sheets, 데이터베이스 등 거의 모든 곳에서 데이터를 주고받을 때 사용됩니다.

하지만 표준이 명확하지 않아서 여러 변종이 있고, 인코딩, 줄바꿈, 따옴표 처리 등으로 인한 문제가 자주 발생합니다.

1부: CSV 기초

CSV의 기본 형식

이름,나이,직업
John,30,개발자
Jane,28,디자이너
Bob,35,매니저

CSV 특징

  • 텍스트 기반 (모든 프로그램에서 열 수 있음)
  • 행(Row) 기반 구조
  • 각 행은 새로운 레코드
  • 각 값은 쉼표로 구분

2부: CSV 문법 규칙

1. 기본 규칙

필드1,필드2,필드3
값1,값2,값3
값4,값5,값6

2. 따옴표 처리

// 필드에 쉼표가 포함되면 따옴표로 감싸기
이름,주소,직업
John,"Seoul, South Korea",개발자
Jane,"New York, USA",디자이너

3. 따옴표 내 따옴표

// 따옴표 안에 따옴표가 있으면 따옴표 2개로 표현
이름,설명
John,"그는 "좋은" 개발자다"
Jane,"그녀의 별명은 "JD""

4. 줄바꿈

// 필드 내 줄바꿈 (따옴표로 감싸야 함)
이름,소개
John,"안녕하세요.
저는 개발자입니다."
Jane,"디자인을 합니다.
창의적인 작업을 좋아합니다."

5. 빈 필드

이름,나이,직업
John,30,
Jane,,디자이너
,35,

3부: CSV 파싱

JavaScript에서 CSV 파싱

간단한 방법 (정규표현식)

const csv = "이름,나이,직업
John,30,개발자
Jane,28,디자이너";

const rows = csv.trim().split('
');
const headers = rows[0].split(',');

const data = rows.slice(1).map(row => {
  const values = row.split(',');
  const obj = {};
  headers.forEach((header, i) => {
    obj[header] = values[i];
  });
  return obj;
});

console.log(data);
// [
//   { 이름: 'John', 나이: '30', 직업: '개발자' },
//   { 이름: 'Jane', 나이: '28', 직업: '디자이너' }
// ]

올바른 방법 (라이브러리)

// npm install papaparse
import Papa from 'papaparse';

const csv = "이름,나이,직업
John,30,개발자
Jane,28,디자이너";

Papa.parse(csv, {
  header: true,
  complete: (results) => {
    console.log(results.data);
  }
});

Python에서 CSV 파싱

CSV 모듈

import csv

with open('data.csv', 'r', encoding='utf-8') as f:
    reader = csv.DictReader(f)
    for row in reader:
        print(row)
        # {'이름': 'John', '나이': '30', '직업': '개발자'}

Pandas

import pandas as pd

df = pd.read_csv('data.csv', encoding='utf-8')
print(df)
#   이름  나이   직업
# 0 John  30  개발자
# 1 Jane  28  디자이너

4부: CSV 생성

JavaScript

const data = [
  { 이름: 'John', 나이: 30, 직업: '개발자' },
  { 이름: 'Jane', 나이: 28, 직업: '디자이너' }
];

// CSV 문자열 생성
const headers = Object.keys(data[0]);
const csv = [
  headers.join(','),
  ...data.map(row =>
    headers.map(header => {
      const value = row[header];
      // 쉼표나 따옴표가 있으면 따옴표로 감싸기
      if (value.toString().includes(',') || value.toString().includes('"')) {
        return '"' + value.toString().replace(/"/g, '""') + '"';
      }
      return value;
    }).join(',')
  )
].join('
');

console.log(csv);

Python

import csv

data = [
  {'이름': 'John', '나이': 30, '직업': '개발자'},
  {'이름': 'Jane', '나이': 28, '직업': '디자이너'}
]

with open('output.csv', 'w', encoding='utf-8', newline='') as f:
    writer = csv.DictWriter(f, fieldnames=['이름', '나이', '직업'])
    writer.writeheader()
    writer.writerows(data)

5부: 인코딩 처리

일반적인 인코딩

UTF-8
- 표준 (권장)
- 한글, 특수문자 완벽 지원

EUC-KR
- 구형 시스템
- 한글 전용

CP949
- Windows 한글 인코딩

잘못된 인코딩 감지

❌ 이상한 글자: "???엗엗" (인코딩 오류)

원인: UTF-8 파일을 EUC-KR로 읽음

해결:
1. 원본 인코딩 확인
2. 올바른 인코딩으로 변환

Python에서 인코딩 처리

import chardet

# 파일의 인코딩 자동 감지
with open('file.csv', 'rb') as f:
    raw_data = f.read()
    result = chardet.detect(raw_data)
    encoding = result['encoding']  # 'UTF-8', 'EUC-KR' 등

# 올바른 인코딩으로 읽기
df = pd.read_csv('file.csv', encoding=encoding)

6부: CSV의 문제점과 해결

문제 1: 따옴표 처리

❌ 잘못된 방법:
"John "Developer" Lee" (내부 따옴표 처리 안 함)

✅ 올바른 방법:
"John ""Developer"" Lee" (따옴표를 2개로)

문제 2: 줄바꿈

❌ 잘못된 파싱:
각 줄바꿈을 새로운 레코드로 인식

✅ 올바른 처리:
따옴표로 감싼 필드 내의 줄바꿈 보존

문제 3: BOM(Byte Order Mark)

일부 Windows 프로그램이 UTF-8 BOM으로 저장
→ 첫 글자가 이상해짐 (예: 이름 → "이름)

해결: BOM 제거하기 (라이브러리 사용)

문제 4: 행 끝 문자 (CRLF vs LF)

Windows: CRLF (
)
Mac/Linux: LF (
)

CSV 읽을 때 이를 정규화해야 함

7부: CSV vs JSON

CSV:
장점: 간단, 작음, 엑셀 호환
단점: 계층 구조 불가, 타입 정보 없음

JSON:
장점: 계층 구조, 타입 정보
단점: 파일 크기 크다, 엑셀 읽기 어려움

선택:
- 엑셀 사용자와 협업: CSV
- API 응답: JSON
- 정형 데이터: CSV
- 복잡한 구조: JSON

자주 하는 실수

1. 간단한 split() 사용

❌ row.split(',') (따옴표 처리 안 됨)

✅ CSV 파싱 라이브러리 사용

2. 인코딩 무시

❌ 인코딩 지정 안 함

✅ UTF-8로 통일하거나 명시적 지정

3. 따옴표 이스케이핑 무시

❌ 특수문자 포함할 때 따옴표 안 함

✅ 항상 따옴표로 감싸기

마무리

CSV는 간단해 보이지만, 제대로 처리하려면 신경 써야 할 부분이 많습니다. CSV 라이브러리를 사용하고, 인코딩을 명시적으로 지정하면 대부분의 문제를 해결할 수 있습니다.