낯선 시스템 앞에서 · 받은 답과 실제가 다르다 · 실습
받은 답과 실제가 다르다 — 칸마다 대조한다
목표
현장에 들어가기 전 받은 인테이크 답변 9칸을 그 고객사의 실제 시스템에서 잰 값과 대조한다. 판정 규칙을 파일로 굳히고, 정확히 일치·범위 안·불일치·답이 없음·확인 불가 다섯 가지로 판정하는 대조기를 만들고, 어긋난 칸마다 다시 물어볼 질문을 기계가 만들어 내게 한다.
왜 중요한가
인테이크 답변은 고객의 기억이고 시스템은 사실이다. 답을 적은 사람은 대개 3년 전에 그 시스템을 설치한 사람이고, 그 뒤로 보존 기간이 줄었고 연동이 하나 더 붙었고 백업 주기가 바뀌었다. 답변을 그대로 전제로 삼은 계획은 착수하자마자 무너진다.
그래서 대조는 눈이 아니라 규칙으로 한다. 칸마다 어떻게 비교할지를 먼저 정해 파일에 적어 두면, 2주 뒤에 같은 명령을 다시 돌려 그 사이 무엇이 바뀌었는지 볼 수 있다. 눈으로 한 대조는 다시 돌릴 수 없다.
가장 중요한 것은 모르는 칸을 모른다고 적는 것이다. 확인하지 못한 칸을 일치로 적으면 아무도 그 칸을 다시 보지 않고, 불일치로 적으면 고객과 쓸데없이 다툰다. 답이 없는 칸과 확인할 수 없는 칸은 따로 세어 목록으로 남긴다.
채점기는 여러분이 적어 낸 문구를 믿지 않는다. 임시 디렉터리에 채점기가 만든 답변과 사실을 차려 놓고, 매번 다른 값으로 여러분의 대조기를 실제로 실행해 판정과 요약을 직접 계산한 값과 대조한다.
단계
1. /root/intake/gen_site.py 를 만들어 실행해 /root/intake/answers.json(9칸)과 /root/intake/site/(버전 파일·설정·로그 14일치·운영 DB)를 만드세요.
2. 시스템을 직접 재어 /root/intake/facts.json 에 app_version·timezone·retention_days·log_days·daily_orders_max·integrations·backup_interval_hours 일곱 칸을 적으세요.
3. 칸마다 비교 방법을 정해 /root/intake/rules.json 에 fields 목록으로 적으세요. 범위로 답한 칸은 range, 목록으로 답한 칸은 set, 어림수로 답한 칸은 tolerance(tolerance_pct 20), 나머지는 exact 입니다. 잴 자리가 없는 칸은 source 를 null 로 둡니다.
4. /root/intake/reconcile.py 를 만들어 exact 와 set 두 규칙으로 match_exact·mismatch 를 판정하고 요약과 함께 JSON 으로 내게 하세요.
5. range 와 tolerance 를 더해 범위 안에 들어온 칸을 match_in_range 로 판정하게 하세요. 경계값은 범위 안입니다.
6. 답이 비어 있는 칸은 unanswered, 답은 있는데 잰 값이 없는 칸은 unverifiable 로 판정하게 하세요. 둘 다인 칸은 unanswered 입니다.
7. --questions <경로> 를 더해, 일치하지 않은 칸마다 다시 물어볼 질문 한 문장을 담은 JSON 배열을 쓰게 하세요.
8. 진짜 답변과 진짜 사실로 /root/intake/report.json 과 /root/intake/questions.json 을 만들고, /root/intake/intake_report.md 에 네 절로 보고하세요.
참고
- 실행 계약:
python3 /root/intake/reconcile.py --answers <A> --facts <F> --rules <R> --out <보고 JSON> [--questions <질문 JSON>]은 요약 JSON 한 줄을 표준출력에 내고 종료 코드 0 으로 끝납니다. 입력을 읽을 수 없으면 3 입니다. - 보고 JSON:
{"summary": {"fields": 정수, "match_exact": 정수, "match_in_range": 정수, "mismatch": 정수, "unanswered": 정수, "unverifiable": 정수}, "findings": [...]}. findings 는 field 이름 오름차순이고, 항목마다 field·rule·answer·fact·verdict 다섯 키가 있습니다. - 판정 이름은 정확히 match_exact · match_in_range · mismatch · unanswered · unverifiable 다섯입니다.
- 규칙 파일:
{"fields": [{"name": …, "kind": "exact|range|tolerance|set", "source": 문자열 또는 null, "tolerance_pct": 정수}]}. tolerance 가 아닌 칸에는 tolerance_pct 를 두지 않아도 됩니다. - range 는 답변이
{"min": …, "max": …}인 칸이고 경계값을 포함합니다. tolerance 는잰 값과 답변의 차이 <= 답변 × tolerance_pct / 100일 때 범위 안입니다. 잰 값이 답변과 정확히 같으면 tolerance 칸이라도 match_exact 입니다. - 사실 파일의 값은 직접 재세요. 버전은
site/app/VERSION, 설정은site/app/app.ini(configparser), 보존 기간과 시간대는site/data/app.db의 settings 표, 로그 보존 일수는site/logs의 파일 이름, 하루 최대 주문은 orders 표, 백업 주기는 backup_log 표의 시각 간격입니다. - 흔한 실수: 목록을 순서까지 비교하기, 허용 오차를 코드에 숨겨 두기, 확인하지 못한 칸을 일치로 적기, 질문 문장 대신 지적 문장을 내기.
- tolerance_pct 20 과 "답이 없는 칸이 확인 불가보다 먼저" 라는 우선순위는 이 실습의 가정입니다. 표준이 정해 주는 값이 아니라 팀이 합의하고 규칙 파일에 적어 두는 값입니다.
- 참고 문서: [RFC 2119](https://www.rfc-editor.org/rfc/rfc2119.html) 와 [RFC 8174](https://www.rfc-editor.org/rfc/rfc8174.html) 는 규칙 문장의 강도를 낱말로 못박는 방법을, [RFC 3339](https://www.rfc-editor.org/rfc/rfc3339.html) 는 날짜와 시각 표기를, [파이썬 json 문서](https://docs.python.org/3/library/json.html)와 [SQLite 날짜 함수](https://www.sqlite.org/lang_datefunc.html)는 이 실습에서 쓰는 도구를 설명합니다.
단계 8개
- 답변과 시스템을 손에 쥐기
- 시스템에서 직접 재기
- 판정 규칙을 파일로 굳히기
- 정확히 일치와 불일치 가르기
- 범위 안을 따로 세기
- 답이 없는 칸과 확인 불가
- 지적 대신 질문 만들기
- 진짜 답변으로 돌리고 보고하기