CSV 빈 칸·빈 줄·누락된 열: JSON 변환 전에 구분하세요
CSV의 빈 값은 모두 같은 상태가 아닙니다. 빈 칸, 빈 레코드, 필드가 모자란 행을 구별하지 않고 JSON으로 바꾸면 원래 없던 값과 명시적으로 비어 있던 값이 같아질 수 있습니다.
원인
CSV 파서는 구분자와 인용 문법에 따라 필드를 나눕니다. 빈 문자열이 들어 있는 필드와 필드 자체가 없는 경우는 다릅니다. 이 글에서는 Python CSV 파서가 읽은 필드 수로 구분합니다. JSON 변환기가 누락을 어떻게 처리하는지는 별도 규칙입니다. Python csv 공식 문서
재현
07-empty-missing.csv는 아래 합성 예제입니다. A1 다음의 빈 줄도 파일 내용입니다.
id,memo,qty
A1,,2
A2,note
A3,"",3
파일과 같은 폴더에서 실행합니다.
import csv
with open('07-empty-missing.csv', encoding='utf-8', newline='') as f:
rows = list(csv.reader(f, strict=True))
print([len(row) for row in rows])
print(repr(rows[1][1]), repr(rows[4][1]))
print(rows[3])
결과는 [3, 3, 0, 2, 3], '' '', ['A2', 'note']입니다.
- A1의 메모는 빈 문자열이지만 필드는 3개입니다.
- 빈 줄은 이 파서에서 필드가 없는 레코드
[]로 읽힙니다. - A2는 수량 필드 자체가 없어 필드 수가 2개입니다.
- A3의
""도 빈 문자열로 읽힙니다. 인용 여부는 파싱한 문자열 값만으로 구별되지 않습니다.
따옴표를 엄격하게 읽는 설정만으로 열 수 일치까지 검증되지는 않습니다. 위 파일은 파싱되지만 열 수 검사가 추가로 필요합니다.
해결
먼저 헤더가 3열이라는 규격과 각 레코드를 대조합니다. A2의 수량을 알 수 없다면 0이나 빈 문자열로 자동 보충하지 않습니다. 자료를 보낸 쪽에 확인하거나 보류 목록으로 분리합니다. 빈 줄을 건너뛰는 규칙도 원본과 함께 기록합니다.
07-complete-subset.csv는 비교를 위해 A1·A3만 남긴 별도 예제입니다. A2를 복구한 완성본이 아니며 실제 업무에서 임의 제외를 권하는 파일도 아닙니다. 이 예제는 각 행이 헤더와 같은 3열인지 확인한 뒤 객체로 바꿀 수 있습니다.
import json
with open('07-complete-subset.csv', encoding='utf-8', newline='') as f:
complete = list(csv.reader(f, strict=True))
assert all(len(row) == len(complete[0]) for row in complete[1:])
objects = [dict(zip(complete[0], row)) for row in complete[1:]]
print(json.dumps(objects, ensure_ascii=False))
출력 객체는 A1·A3 두 개이며 memo는 "", qty는 문자열 "2"·"3"입니다. 숫자2·3이나 null로 자동 바뀐다고 가정하지 않습니다. 헤더 이름은 비어 있지 않고 서로 달라야 한다는 전제도 확인합니다.
연결 도구: CSV 검사기 → CSV ↔ JSON 변환
먼저 **CSV 검사기(/csv-check/)**에서 원본 예제의 열 수 불일치와 빈 레코드 정보를 확인합니다. 도구는 빈 줄을 별도 집계하므로 Python의 rows 목록 길이와 화면 레코드 수가 그대로 같다고 가정하지 말고 항목 이름을 함께 봅니다.
그다음 열 수가 맞는 별도 예제를 **CSV ↔ JSON 변환(/csv-json/)**의 CSV→JSON 방향·쉼표·머리글 있음으로 읽습니다. A1·A3의 메모가 빈 문자열로 출력되는지 확인합니다.
CSV ↔ JSON 변환은 열 수가 머리글과 다른 줄이 있으면 결과 위에 줄 번호와 함께 경고를 띄웁니다. 원본 예제를 넣으면 4번째 줄: 2열 (머리글 3열)이 표시됩니다. 변환을 막지는 않으며, 모자란 필드는 빈 문자열로 채우고 머리글보다 많은 값은 결과에서 뺍니다. 그래서 경고가 뜬 상태로 A2를 변환해 qty: ""가 나와도 원본에 명시된 빈 수량이라는 뜻은 아닙니다. 변환 결과만으로 누락 여부를 판정할 수 없습니다. 구조 오류·열 수 불일치가 남아 있으면 해결·보류 규칙을 정한 뒤 진행합니다.
한계
변환 도구의 경고는 열 수만 봅니다. 경고가 없어도 빈 문자열·누락·null의 의미까지 확인한 것은 아닙니다. 빈 문자열·누락·null을 같은 것으로 볼지는 업무 규격이 결정합니다. 공백 한 칸도 자동으로 빈 값 취급하지 않습니다. JSON을 다시 CSV로 써도 원래의 인용 방식·빈 줄 배치까지 되살아난다는 보장은 없습니다. 이 글은 UTF-8·쉼표·고유한 헤더를 사용하는 작은 합성 예제를 검증한 것이며 Excel 화면이나 실제 고객 파일의 상태를 대신 판단하지 않습니다.
검토일: 2026-10-18. Python 3.9.6으로 필드 수·빈 문자열·누락 필드·검증 후 JSON 객체화를 실행했습니다. 사이트 연결은 현재 라이브러리의 동작을 대조하며 브라우저 UI 검증은 별도입니다.
AI 보조 작성: AI로 초안과 합성 예제를 작성하고 로컬 실행으로 확인했습니다. 실제 거래 자료·개인정보는 사용하지 않았습니다. 참고용이며 원본·업무 규격과 함께 대조하세요.