GN⁺: CSV 포맷에 대한 러브레터
(github.com/medialab)- CSV를 대체할 "우월한" 형식들이 자주 소개되지만, 대부분은 편향된 비교를 기반으로 CSV의 진정한 강점을 간과함
- 이 글은 CSV가 완벽하다는 것이 아니라, 과소평가된 장점을 조명하고자 함
- CSV를 미워하는 것이 멋져 보이는 분위기에 반해 CSV의 진가를 되새김
1. CSV는 극도로 단순함
- CSV의 정의는 제목 그대로: "쉼표로 구분된 값"
- 행은 줄바꿈으로, 열은 쉼표로 구분됨
- 값에 쉼표나 줄바꿈이 있을 경우에는 따옴표로 감싸고, 따옴표 자체는 이중 따옴표로 표현
- 복잡한 명세 없이 누구나 직관적으로 이해하고 사용할 수 있음
- 다만, 정확한 파싱을 위해 전용 CSV 파서 사용은 여전히 필요함
2. CSV는 집단적인 아이디어임
- 소유자가 없음, 사유화되지 않음
- RFC 4180이 존재하지만, 대부분은 이를 참고용으로만 여김
- 전 세계 개발자들이 암묵적으로 공유하는 공통 규칙 기반의 자유로운 형식임
3. CSV는 텍스트임
- JSON, YAML, XML처럼 사람이 읽을 수 있는 순수 텍스트 포맷
- 어떤 텍스트 에디터로도 열 수 있으며, 별도 도구 없이도 내용을 확인 가능
- 인코딩 방식도 자유롭게 선택 가능
4. CSV는 스트리밍에 최적화됨
- 한 줄씩 읽는 구조이기 때문에 메모리 소모가 매우 적음
- 간단한 코드만으로도 수 기가바이트의 데이터를 몇 KB의 메모리만으로 처리 가능
- Parquet 같은 열 지향 포맷은 스트리밍 처리가 어렵고, 복잡한 버퍼링이 필요함
- 단점은 특정 열만 보고 싶을 때에도 전체 행을 읽어야 한다는 점
5. CSV는 쉽게 덧붙일 수 있음
- 파일을 append 모드(
a+
)로 열어 새로운 행을 끝에 추가하는 것이 매우 쉬움 - 반면 Parquet 등의 열 지향 포맷은 행 추가가 비효율적이고 복잡함
6. CSV는 동적 타입을 지원함
- 고정 타입이 없어서 유연하게 데이터를 해석 가능
- 예: JavaScript는 64비트 정수를 제대로 표현하지 못하지만 CSV는 이런 제약 없이 사용 가능
- 언어 간 호환성과 유연성에서 이점이 있음
- 하지만 잘못 해석하면 오류 발생 가능 → 사용 시 주의 필요
- 고성능이 요구될 경우 텍스트를 디코딩하지 않고 바이너리 수준에서 직접 처리하는 것도 가능
7. CSV는 간결함
- 헤더가 파일 맨 앞에만 존재하기 때문에 형식 반복이 거의 없음
- JSON, XML은 키 반복으로 오버헤드가 큼
- 문자열 표현도 이미 간결하며, 포맷 자체의 오버헤드(쉼표, 따옴표 등)가 매우 적음
8. 뒤집힌 CSV도 여전히 유효함
- CSV는 바이트 단위로 뒤집어도 여전히 유효한 CSV임
- 이는 이중 따옴표 이스케이프 방식 덕분으로, 팔린드롬 형태의 이스케이프 방식이기 때문
- 이 특성 덕분에 CSV 파일의 끝부분을 매우 효율적으로 읽을 수 있음
- 예: 중단된 프로세스를 재개할 때 파일의 마지막 몇 줄만 읽어 재시작 가능
9. Excel은 CSV를 싫어함
- Excel이 불편하게 여기는 형식이라면, 오히려 올바른 길을 가고 있다는 신호일 수도 있음
Hacker News 의견
-
CSV와 INI 파일을 좋아하는 이유는 단순하고 텍스트 기반이며, 형식에 인코딩된 타입이 없고 문자열로만 구성되어 있기 때문임
- 공식 표준이 없다는 단점이 있지만, 제 역할을 잘 수행함
- TOML에 대한 INI 비판을 북마크해 두었음
- TOML 비판의 첫 번째 줄이 CSV에도 적용된다고 생각함: 여러 방언의 연합체임
-
CSV는 우아하지만 치명적인 결점이 있음 - 인용부호가 "비지역적" 효과를 가짐
- 예를 들어, 바이트 1에 있는 인용부호 하나가 바이트 1000000에 있는 쉼표의 의미를 바꿀 수 있음
- 이로 인해 두 가지 불편한 결과가 발생함
- CSV 처리의 병렬화가 어려움
- 데이터 손상이 파일의 가독성에 큰 영향을 미침 (인용부호 하나의 누락이나 추가가 전체를 망칠 수 있음)
- 그래서 요즘은 간단한 테이블 데이터 직렬화에 대해 CSV 대신 단순한 이스케이핑을 선호함
-
CSV의 가장 좋은 점은 누구나 30분 만에 파서를 작성할 수 있다는 것임
- 90년대 초의 데이터를 현대 웹 서비스로 쉽게 가져올 수 있음
- 가장 나쁜 점은 누구나 30분 만에 파서를 작성할 수 있다는 것임
- 잘못된 구현, 잘못된 데이터, 이상한 정의되지 않은 동작이 발생하기 쉬움
- JSON과 YAML도 비슷한 문제를 가지고 있음
- XML은 다소 보기 흉하지만 가장 견고한 것 같음
-
CSV를 좋아하는 사람은 기업 환경에서 CSV 주입 방지를 처리하라는 요청을 받은 적이 없을 것임
- 웹에 좋은 자원이 부족함
- 가장 좋은 자원은 <a href="https://georgemauer.net/2017/10/07/csv-injection.html" rel="nofollow">여기</a>임
-
CSV를 좋아하는 이유는 여러 가지가 있음
- C로 프로그램을 작성하여 다양한 것을 CSV로 직접 출력할 수 있음
- 거의 모든 데이터베이스나 일반적인 "것"에서 CSV로 쉽게 변환할 수 있는 간단한 미들웨어를 작성할 수 있음
- CSV를 엑셀에 넣고 원하는 모든 것을 할 수 있음
- ini 파일도 좋아함. 메모장에서 직접 수정할 수 있음
- 그러나 일반적인 개요/구조가 있었으면 좋겠음
-
최근 Raspberry Pi 기반 솔루션을 개발하고 있음
- 첫 번째 구현은 SQLite 데이터베이스를 사용했으나, 전원 주기 후 몇 일 만에 손상됨
- Parquet 파일을 살펴보았으나 append-only 작업에 친화적이지 않음
- IPC 파일에 이벤트를 기록하고 주기적으로 Parquet 파일로 "플러시"하는 방법을 구현함
- 작동하고 효율적이지만 제대로 구현하기가 쉽지 않음
- 일반 개발자에게는 CSV (또는 JSONL)가 여전히 최고임
-
CSV의 재미없는 점은 빠르게 작성된 파서와 직렬화기가 인용부호를 잘못 처리하는 일반적인 실수를 반복하는 것임
- 오랫동안 CSV를 경계했으나 Python을 배우고 훌륭한 csv 표준 라이브러리 모듈을 사용하면서 달라짐
-
만약 이것이 정말로 러브레터였다면, CSV 형식으로 작성되었을 것임
-
JSON에 대한 반론은 그다지 설득력이 없음
- 모든 필드에 이름을 추가하는 것은 필요하지 않음
- CSV와 JSON을 비교하면 JSON은 약간 더 크지만, 괄호가 단순하거나 복잡할 수 있는 능력을 나타냄
- CSV는 단순하기 때문에 파싱/인코딩 라이브러리를 사용하지 않는 경우가 많음
- JSON 파서는 항상 예상 값을 출력하며, 언어는 아마도 매우 효율적인 SIMD 기반 파서를 사용함
- 표준화 문제도 있음. CSV 파일이 쉼표, 공백, 세미콜론, 파이프 등을 사용하는지, CR, LF, CRLF를 사용하는지, 인용부호를 이스케이프할 수 있는지 등의 문제가 있음
- JSON은 이러한 문제가 없음
- JSON은 타입이 있음. 6가지 타입이 없는 것보다 나음
- JSON은 완벽하지 않지만, 일반적으로 CSV보다 나음
-
현대적인 형식을 좋아하는 사람으로서, 의심스러울 때는 CSV나 JSONL을 사용함
- 주로 평문 텍스트이기 때문에
grep
으로 쉽게 찾을 수 있고 스트리밍 가능함 - 문서에 나열된 대부분의 기능은 JSONL에도 공유됨
- gzip이나 zstd로 잘 압축됨
- 압축은 평문 텍스트의 장점을 일부 제거하지만, ripgrep은 압축된 파일도 검색할 수 있음
- JSONL의 또 다른 장점은 더 작은 파일로 쉽게 나눌 수 있다는 것임
- 주로 평문 텍스트이기 때문에