워크노트 예제: JSON 목록을 CSV로 변환하고 누락 필드 확인하기
버전: 1.0.0 / 언어: ko / 작성 기준일: 2026-09-19

[실행 환경]
대상: Python 3.12, 표준 라이브러리만 사용. pip 설치 불필요.
실제 검증: Linux x86_64 / CPython 3.13.5 / unittest 22개 통과.
Python 3.12 실제 실행 및 Windows/macOS 실행은 미검증.
3.12 문법 모드 AST 검사 통과는 3.12 실행 검증을 대신하지 않는다.
네트워크, 외부 서비스/API 호출, 결제, 광고 연결, 개인정보는 사용하지 않는다.

[준비]
ZIP을 새 폴더에 풀고 example.py와 sample.json이 있는 폴더에서 터미널을 연다.
처음에는 제공한 합성 sample.json만 사용한다. sample.json을 덮어 고치지 않는다.
파이썬 파일 이름이 example.py.txt로 저장되지 않았는지 확인한다.

[실행 순서]
1. 아래 명령으로 선택된 인터프리터 버전을 확인한다.
   python --version

2. Python 3.12가 선택된 상태에서 실행한다.
   python -X utf8 example.py sample.json --output-dir result_001

   Windows에서 py 런처와 Python 3.12가 이미 설치되어 있다면:
   py -3.12 -X utf8 example.py sample.json --output-dir result_001

   macOS/Linux에서 python3.12 명령이 이미 있다면:
   python3.12 -X utf8 example.py sample.json --output-dir result_001

   위 명령은 대안이다. 모두 차례대로 실행하지 않는다.
   result_001 폴더는 미리 만들지 않는다. 출력 부모 폴더는 이미 있어야 한다.
   경로에 공백이 있으면 경로를 큰따옴표로 감싼다.

3. 정상 출력:
   OK: rows=4; missing_key_cells=2; null_cells=1; empty_string_cells=1; issue_cells=4

4. result_001의 converted.csv, field_issues.csv, summary.json을 확인한다.
   expected 폴더는 손으로 정한 기대값이다. verified_output은 실제 검증 시 생성한 결과다.
   CSV는 UTF-8, BOM 없음, 쉼표 구분, CRLF 줄바꿈이다.
   텍스트 편집기 또는 UTF-8로 지정한 CSV 가져오기로 확인한다.

5. 같은 명령을 다시 실행하면 종료 코드 3과 E_OUTPUT_EXISTS가 나와야 한다.
   기존 결과를 지우지 말고 새 실행은 --output-dir result_002로 수행한다.

[정확한 기대값]
입력 레코드 4 / CSV 데이터 행 4 / CSV 열 3 / 전체 데이터 셀 12.
누락 키 2셀(2번 레코드 unit, 3번 레코드 quantity), 누락 키가 있는 레코드 2개.
null 1셀(4번 quantity), 빈 문자열 1셀(4번 unit).
field_issues.csv: 헤더 제외 4행 = missing_key 2 + null 1 + empty_string 1.
converted.csv: 이 4셀은 빈 칸으로 기록하되 원인 차이는 점검 CSV에 남긴다.
row_number는 JSON 배열 원소의 1부터 시작하는 순번이다. 원문 텍스트의 줄 번호가 아니다.
종료 코드 0은 변환 완료라는 뜻이지, 누락이나 업무상 오류가 없다는 뜻이 아니다.

[입력 규칙]
기본 필드: item quantity unit. 필드 이름은 대소문자를 구분한다.
최상위 값은 배열이어야 하고 각 원소는 객체여야 한다. 빈 배열은 허용한다.
기대 필드에 키가 없으면 missing_key, 값이 null이면 null, 값이 ""이면 empty_string.
0, false, 공백만 있는 문자열은 누락으로 분류하지 않고 그대로 보존한다.
새 키가 있으면 자동으로 버리지 않고 오류로 중단한다. 필요한 필드를 직접 추가한다.
   python -X utf8 example.py other.json --output-dir result_custom --fields item quantity unit note
other.json은 제공 파일이 아니라 독자가 새로 만든 비개인 합성 입력의 예시 이름이다.
원본 sample.json 대신 새 입력 파일을 사용한다.
중첩 객체/배열, 중복 키, NaN/Infinity/-Infinity는 거부한다.
UTF-8 입력만 받되 UTF-8 BOM은 허용한다. 입력 크기 제한은 5 MiB(5,242,880바이트)다.
숫자는 CSV 문자열로 기록한다. 소수는 Decimal로 읽지만 숫자 표기의 완전한 복원은 보장하지 않는다.

[재검증]
example.py와 같은 폴더에서:
   python -B -X utf8 -m unittest -v test_example
Python 3.12 런처가 있다면 python 대신 py -3.12 또는 python3.12를 사용한다.
테스트는 임시 폴더에 합성 입력을 새로 만들고 정리한다. 배포된 sample.json은 수정하지 않는다.
검사 내용: 정상 기대값, 재실행 거부, 잘못된 JSON, 비배열, 일부 키 누락,
null/빈 문자열 구분, 추가 키, 중첩값, 중복 키, 인코딩, 원본 바이트/SHA-256 보존 등.
실제 실행 로그: validation_run.txt / 구조화 기록: validation_results.json.

[오류와 조치]
E_INPUT, 종료 코드 2: JSON 문법·배열 구조·키·인코딩을 확인한다.
E_OUTPUT_EXISTS, 종료 코드 3: 비어 있는 폴더라도 기존 경로는 거부된다. 새 이름을 쓴다.
E_READ/E_WRITE, 종료 코드 4: 입력 경로·읽기 권한·출력 부모·쓰기 권한·디스크 상태를 확인한다.
쓰기 도중 실패하면 이번에 만든 새 출력 폴더에 일부 파일이 남을 수 있다.
이때 결과를 사용하지 않는다. 자동 삭제나 덮어쓰기는 하지 않으며 새 경로로 재시도한다.

[한계]
소규모 로컬 파일용이다. 스트리밍, JSON Lines, 중첩 평탄화, 업무 규칙 검사는 제공하지 않는다.
quantity의 양수 여부·단위의 타당성·자료의 진위는 판정하지 않는다.
원본 JSON의 공백·키 순서·숫자 표기 등 전체 형식을 되돌리는 도구가 아니다.
CSV 문자열의 수식 여부를 검사하거나 정화하지 않는다. 외부 파일의 스프레드시트 실행은 검증 범위 밖이다.
원본을 다른 프로그램이 동시에 바꾸거나 디렉터리를 공격적으로 교체하는 환경은 대상이 아니다.
강제 종료·디스크 장애 시 다중 파일의 완전한 일괄 저장을 보장하지 않는다.

[파일]
article.ko.md: 전체 한국어 원문 및 전체 코드
example.py / sample.json: 실행 코드와 최소 합성 입력
README.txt: 이 실행 안내
expected/: 독립 기대값 3개
verified_output/: 실제 정상 실행 결과 3개
test_example.py: 임시 폴더 회귀 테스트 22개
VALIDATION.md / validation_run.txt / validation_results.json: 검증 기록
상위 폴더 PLAN_5_TOPICS.md: 신규 5개 기획표
상위 폴더 SHA256SUMS.txt: 배포 파일 체크섬

[출처와 게시 범위]
본문·코드·합성 데이터는 이번 작업에서 새로 작성했다.
기술 근거는 article.ko.md의 Python 3.12 공식 문서 링크를 따른다.
기존 16편의 원문 ZIP은 열람하지 않았고 기존 본문과의 중복 대조는 미완료다.
이번 작업에는 사이트 게시, 광고 설정, 번역 본문 생성이 포함되지 않는다.
특정 서비스의 광고 심사 통과, 법적 적합성, 수익을 보장하지 않는다.
