매주 자료를 다시 검색하는데 보고서가 거의 바뀌지 않는다면, 새 자료를 찾는 일과 내 문서를 고치는 일이 연결되지 않았을 수 있어요. “페이지가 갱신됐다”만 기록해서는 무엇을 다시 검토할지 알기 어려워요. 이번에는 보존한 두 판본을 비교해 변경을 찾고, 그 변경이 보고서의 어느 주장에 영향을 주는지까지 연결해요.
첨부 링크는 이 글의 예제 ZIP으로 연결돼요. 압축을 푼 뒤 링크에 표시된 파일을 열면 입력·코드·완성 자료를 함께 사용할 수 있어요.
예제의 자료는 직접 만든 CSV 변환 사양 v1.0·v1.1과 이를 인용한 가상 보고서예요. 특정 제품의 실제 변경 공지가 아니에요. 파일 안에도 synthetic: true를 넣었어요. 결과물은 변경 영향 기록 (ZIP: change-impact.csv), 수정 보고서 (ZIP: report-v2.md), 실제로 분할한 CSV와 검증 결과 (ZIP: verification.json), 남은 조치의 담당·상태 기록 (ZIP: follow-up-actions.csv)이에요.

출처 목록보다 추적할 질문을 먼저 정해요
가상 보고서의 질문은 “현재 800행 입력을 사양에 맞게 처리할 수 있는가?”예요. 그래서 추적할 항목은 요청당 최대 행수, 허용 인코딩, 타임아웃이에요. 소개문이 바뀌어도 기능 판단과 연결되지 않으면 같은 긴급도로 처리할 필요는 없어요.
기준본은 10월 6일자 v1.0, 현재본은 10월 13일자 v1.1로 정했어요. 실제 자료를 다룰 때는 출처 URL, 제공자가 붙인 판본·발효일, 내가 확인한 날짜를 나눠 적어야 해요. 확인일이 오늘이라고 변경이 오늘 발생한 것은 아니기 때문이에요. 이번 합성 자료는 변경 과정을 분명히 보기 위해 날짜와 판본을 직접 지정했어요.
파일을 보존하고 변경 이력을 관리하는 원칙은 Good enough practices in scientific computing의 변경 관리 부분을 참고했어요. 아래의 필드별 영향 판정은 예제의 문서 목적에 맞춰 만든 방식이에요. 웹페이지 전체를 매번 복사하기보다 이용 조건과 저장 범위를 확인하고, 중요한 값과 원문 위치를 추적하는 방법도 가능해요.
변경을 찾는 단계에서는 의미를 미리 붙이지 않아요
v1.0은 요청당 최대 1,000행, UTF-8 입력, 30초 타임아웃이에요. v1.1은 최대 행수가 500으로 줄고 UTF-8 BOM이 추가되었으며 소개문의 형용사가 바뀌었어요. 타임아웃은 그대로예요.
먼저 source-v1.json과 source-v2.json의 같은 키를 비교해요. 순서나 공백이 달라졌다고 기능 변경으로 세지 않고, 실제 값이 달라진 필드를 분리해요. 제공한 compare-and-split.py는 최대 행수·인코딩·타임아웃·소개문 네 필드 중 달라진 세 개를 field-diff.json에 남겨요. 판본과 날짜는 내용 차이와 별도로 추적표 D04에 기록했어요.

바뀐 값마다 보고서의 문장 ID를 붙여요
보고서 C01은 “800행을 한 번에 처리한다”였어요. 최대 500행이라는 현재 값과 충돌하므로 D01의 판정은 수정이에요. 단순히 보고서의 1,000을 500으로 바꾸면 실제 계획은 여전히 800행 단일 요청으로 남아요. 숫자와 함께 그 숫자에 의존한 행동까지 고쳐야 해요.
예제에서는 원본 800행을 400행씩 두 파일로 나눴어요. 한도 이내인 500·300도 가능하지만, 두 파일의 크기를 같게 하면 이번 검증에서 처리 건수를 비교하기 쉬워 400·400을 선택했어요. 어느 분할 방식이 더 빠르다는 실험 결과는 없어요. 원본 ID는 X0001~X0800이고 value는 모두 1인 합성 데이터예요.
python3 compare-and-split.py를 실행해 파일을 만든 뒤, 두 파일의 행수 합이 800인지, ID가 겹치거나 빠지지 않았는지, value 합계가 원본과 같은지 확인했어요. 결과는 각각 400행, 전체 800행, 중복 0, 합계 800으로 일치했어요. 이것은 로컬 파일 분할의 검증이에요. 외부 서비스에 보내거나 응답을 다시 합치는 단계는 실행하지 않았으므로 보고서에 그대로 구분했어요.
관찰과 영향 없음도 근거가 있는 결정이에요
D02의 인코딩 추가는 관찰로 두었어요. 기존 입력이 UTF-8이라 현재 계획에는 문제가 없고, 앞으로 BOM이 있는 파일을 받을 때 사용할 수 있는 선택지가 생겼기 때문이에요. 곧바로 입력 형식을 바꾸거나 새 기능을 적용했다고 기록하지 않았어요. 해당 입력이 실제로 생기면 별도 검사한다는 조건을 적었어요.
D03의 소개문 변경은 영향 없음이에요. 보고서 어디에서도 그 형용사를 기능 보장의 근거로 쓰지 않았으므로 고칠 문장이 없어요. 그래도 변경을 무시한 것과 검토한 뒤 영향이 없다고 판단한 것을 구분하려고 기록을 남겼어요. D04는 판본·확인일을 갱신했어요. 타임아웃은 변화가 없으므로 변경 목록에 넣지 않았고, 보고서 C03도 유지했어요.


행수와 합계만 통과한 가짜 완료를 걸러 봐요
F01의 종료 증거에 ID를 넣은 이유를 직접 확인했어요. 실제 외부 응답은 없으므로, 이미 만든 두 분할 파일을 로컬에서 합친 뒤 마지막 X0800 한 행을 빼고 X0001을 한 번 더 넣은 오류 입력 (ZIP: local-duplicate-replaces-last.csv)을 만들었어요. 모든 value가 1이라 아래처럼 행수·합계 검사를 통과하지만 원본 보존에는 실패해요.
| 로컬 모의 입력 | 행수 | value 합계 | ID·행별 값 대조 | F01 종료 가능 여부 |
|---|---|---|---|---|
| 두 파일을 그대로 합침 | 800 | 800 | 중복·누락 0 | 외부 실행 증거가 없어 종료 불가 |
| X0800 대신 X0001 중복 | 800 | 800 | 중복 1·누락 1 | 내용 검사 실패 |
| 첫 번째 파일만 합침 | 400 | 400 | 누락 400 | 내용 검사 실패 |
| X0001의 value=2, X0002의 value=0 | 800 | 800 | ID는 같고 값 2건 불일치 | 내용 검사 실패 |
한 단계 더 확인하려고 원본 ID는 모두 유지한 채 X0001의 값을 1에서 2로, X0002의 값을 1에서 0으로 바꾼 상쇄 오류 입력 (ZIP: local-values-offset.csv)도 만들었어요. 합계는 여전히 800이고 중복·누락도 없지만, ID별 원래 값과 대조하면 두 행의 내용이 달라요. 따라서 이번의 보존 조건은 행수·ID집합·합계에 ID별 value 일치까지 포함해요.
검사 코드 (ZIP: check-followup.py)는 위 네 입력을 실제로 생성하고 결과 JSON (ZIP: followup-verification.json)에 빠진 ID와 값이 달라진 ID까지 남겨요. 이것은 잘못된 응답을 받았다는 경험담이 아니라 검증 규칙의 빈틈을 확인하는 합성 오류 주입이에요. 표 첫 행의 내용 검사가 맞아도 외부 실행으로 바꾸어 부르지 않으므로 F01은 여전히 미실행이에요.
종료할 때는 수치 외에도 증거의 적용 범위를 맞춰야 해요. 사양 판본, 원본 파일 식별값, 요청별 행수, 응답 파일, 실행일과 확인 담당을 함께 연결해요. 이 예제는 값을 그대로 보존하는 변환을 가정하므로 value 합계 800과 ID별 값의 원본 일치를 요구해요. 실제 서비스가 중복을 제거하거나 값을 집계하는 계약이라면 출력 800행을 강제하지 말고 그 계약에 맞는 정답을 먼저 정해야 해요.
다음 개정이 오면 완료 기록을 지우지 않고 새 확인을 열어요
현재 한도 500에서는 400+400과 500+300이 모두 두 요청으로 가능해요. 원고는 같은 크기의 비교가 편한 400+400을 택했고, 요청 수를 줄인다는 이유로 고른 것은 아니에요. 요청 수는 같고 속도·과금은 측정하지 않았어요. 단일 800행은 현재 한도를 넘으므로 제외해요.
다음 판본에서 한도가 300이 되었다는 별도 합성 조건을 넣으면 두 분할안 모두 무효예요. 현재 v1.1이 실제로 바뀌었다고 보고하지 않고, 조건 검사에서만 300+300+200을 새로 만들었어요. 각 파일이 300행 이하이고 전체 800행·ID·합계·ID별 값이 유지되는 것을 확인했어요. 이 결과는 이전 완료 기록을 삭제할 이유가 아니라 C01 처리 계획, D01 영향 판정, F01 외부 검증을 새 판본 기준으로 다시 열 이유예요. 이전 판본에서 완료한 증거가 있다면 그 판본의 이력으로 보존하고 새 확인 행에서 연결하면 돼요.
반대로 한도가 500에서 1,000으로 완화돼도 두 파일 처리가 계속 유효하다면 기존 계획을 유지할 수 있어요. 단일 요청으로 바꾸는 편익과 다시 검증할 비용을 보고 결정해요. 허용 선택지가 늘었다는 사실만으로 입력 형식을 즉시 바꾸지 않은 D02와 같은 판단이에요. 새 요청 한도만 바뀌었다는 가정이며 다른 계약 조건도 바뀌면 별도로 확인해야 해요.
남은 조치마다 확인 담당과 종료 증거를 연결해요
문서를 고친 사람과 남은 작업의 결과를 확인할 사람은 다를 수 있어요. 따라서 변경 행의 ‘기록 담당’만으로 끝내지 말고, 남은 조치마다 조치 ID, 확인 담당, 상태, 다음 확인 시점·조건, 완료를 판단할 증거를 붙여요. 조치가 두 개라면 행도 둘로 나누고 둘 다 담당을 적어요. “팀에서 확인”이나 빈칸은 누가 다음에 확인할지 알려주지 못해요.
이 예제에서 D01의 로컬 분할은 끝났지만 외부 응답 재결합은 미실행이에요. 이를 F01로 나누고 확인 담당을 ‘담당 미지정, 지정 필요’, 상태를 ‘담당 지정 대기·외부 검증 미실행’으로 기록했어요. 예제의 문서 책임자가 외부 적용 전에 담당을 정해야 한다는 지정 요청 대상도 남겼어요. 실제 요청을 보낸 기록이나 담당자의 승인이 있다는 뜻은 아니에요. 담당을 모르면 임의의 사람을 배정하거나 ‘확인 중’으로 바꾸지 않아요. 지정 요청 대상도 모른다면 그 역시 미확인으로 표시하고 문서 책임자부터 확인할 일로 남기세요.
F01의 담당이 정해지면 이름이나 명확한 역할을 넣고, 응답 합계800행·원본ID집합 일치·중복0·value합계800·ID별value 일치를 확인한 실행 기록을 붙인 뒤 완료 여부를 결정해요. 이미 끝난 로컬 검사 결과만으로 F01을 종료하면 안 돼요. F02의 BOM 검증은 가정한 분석 담당이 확인하도록 정했고, 상태는 ‘조건부 대기·미실행’, 재확인 조건은 ‘BOM 입력을 처음 사용하기 전’이에요. 이때 문자 해석·행수·ID가 입력과 일치하는 기록이 종료 증거예요. 담당 역할은 합성 예제의 배정안이며 실제 조직의 업무 지시가 아니에요.
원고 폴더에서 python3 assets/compare-and-split.py와 python3 assets/check-followup.py를 차례로 실행하면 현재 분할과 추가 조건 검사를 재현할 수 있어요. 상세 보류 해제 규칙 (ZIP: followup-policy.md)도 첨부했어요.
다음 주에는 변경 목록의 F01·F02를 열어 담당이 지정됐는지, 확인 조건이 도래했는지, 증거가 생겼는지 보면 돼요. D03·D04처럼 남은 조치가 없는 행은 그 사실을 명시하고 종료해요. NASA 의사결정 분석 안내의 가정·불확실성·결정 이유 보존 원칙을 참고했고, 위 담당·상태 열은 이 예제에서 후속 확인이 빠지지 않도록 만든 작업 방식이에요.
과거 판본이 없다면 기억으로 이전 값을 채우지 마세요. 현재 값을 기준본으로 저장하고 ‘이전 상태 미확인’이라고 남기면 돼요. URL이 같은데 내용이 바뀐 경우에는 확인일만으로 이전 내용을 복원할 수 없어요. 중요한 주장은 판본이나 제공자가 남긴 변경 기록과 연결하고, 자료 접근이 끊기면 마지막 확인값과 현재 미확인을 구분해요.
2026년 10월 13일에 공개 방법론 자료를 확인하고 합성 판본 비교·파일 분할을 로컬 Python으로 실행했어요. 실제 제품이나 정책의 변경 조사, 외부 API 실행, 자동 감시 서비스 설치는 이 예제에 포함되지 않아요. 출처가 달라질 때 고쳐야 할 것은 링크 날짜뿐 아니라 그 출처에 기대어 만든 문장과 행동이라는 점을 결과 파일에서 확인할 수 있어요.
재확인할 입력·코드·예상 결과를 다른 담당자에게 넘길 때는 분석 인수인계 자료를 함께 묶으세요. 출처 변경으로 지표의 분모나 집계 기준까지 달라졌다면 KPI 정의서도 갱신해야 예전 보고서와의 비교 범위가 남아요.
예제 파일을 한 번에 받아 다시 확인해요
이 글의 입력·코드·완성 자료 ZIP을 새 폴더에 풀면 R30/README.txt, replay.py, assets 폴더가 함께 생겨요. 개별 코드 파일만 저장하면 보조 모듈이나 입력이 빠질 수 있으므로 처음에는 이 묶음을 사용하세요. R30 폴더에서 다음 명령을 실행하면 본문에 사용한 검사를 순서대로 수행해요.
python3 replay.py
확인할 결과는 500행 한도에서400+400과800개 ID 보존, 누락·중복·상쇄값 오류 검출예요. 명령이 성공해도 이 값과 본문의 적용 범위를 함께 대조하세요. 실행 안내 (ZIP: README.txt)에 필요한 파일과 개별 명령을 적었어요. 실행 코드는 compare-and-split.py (ZIP: compare-and-split.py) · check-followup.py (ZIP: check-followup.py)에서 직접 볼 수 있어요. Python3.12의 표준 라이브러리를 사용하며, 명령이 실패하면 ZIP의 폴더 구조와 오류에 나온 파일부터 확인해요. 실제 앱 실행에 필요한 프로그램은 원래 설명을 따르세요.
작성·확인: Codex가 공개 원문 또는 공식 문서를 확인하고 예제와 초안을 작성했어요. 사람을 대상으로 한 사용성 검증은 수행하지 않았어요.
설명 삽화 2장은 GPT로 생성한 개념 설명이에요. 실제 예제의 작업 화면과 실행 결과는 기존 그림·첨부 자료에서 따로 확인할 수 있어요.