일요일 오후, 또 그 시간이 왔다.

매주 반복되는 일이다. 스캔된 헌금 전표 PDF를 받아, OCR로 이름과 금액을 뽑고, 틀린 이름을 교정하고, Excel에 정리해서 Drive에 올린다. 몇 달 전까지만 해도 손으로 하던 일이었다. 지금은 Claude에게 PDF를 던지면 알아서 처리해준다.

자동화는 완성된 게 아니다. 계속 부서지고, 계속 고쳐진다.


오늘의 첫 번째 균열

⚠ 구제: 14건 추출 / 슬롯 12개 → 2건 누락

이 경고 메시지를 보는 순간, 뭔가 어긋났다는 걸 직감했다. 구제 헌금은 14명이 냈는데, 템플릿에는 12줄밖에 없다는 뜻이다. 2건이 조용히 증발할 뻔했다.

원인을 추적했다. 언제부터인지 모르게 누군가 Google Sheets 템플릿에서 구제와 장학 슬롯을 12개에서 14개로 늘렸다. 합리적인 변경이었다. 하지만 코드는 몰랐다. offering_config.py에 박혀있는 숫자들 — start: 70, end: 81, slots: 12 — 은 여전히 옛날 세상을 가리키고 있었다.

템플릿 파일(Google Sheets)과 코드 설정 파일이 서로 다른 속도로 변하고 있었다.

이건 동기화 문제다. 그리고 동기화 문제는 시간이 지나면 반드시 터진다.


안나전도회는 어디에 속하는가

두 번째 문제는 더 미묘했다.

월정선교 통계표를 보니 맨 아래에 "안나전도회 400,000"이 적혀 있었다. OCR은 충실하게 이걸 월정선교 데이터로 뽑았다. 틀린 게 아니다 — 실제로 그 페이지에 있는 데이터니까.

하지만 안나전도회는 별도 계정이다. 월정선교(선교비 계정)와 안나전도회(전도회 계정)는 회계 분류가 다르다. 교회 재정에서 이 둘을 섞으면 결산이 틀어진다.

단체헌금을 통계표에 포함시켜 합산 관리하는 건 실무적으로 자연스러운 일이다. 그런데 자동화 시스템은 그 맥락을 모른다. "월정선교 페이지에 있는 데이터"와 "월정선교 카테고리에 들어가야 하는 데이터"가 다를 수 있다는 사실을.

이걸 처리하는 규칙을 매뉴얼에 명시하지 않았더니, 오늘에야 발견된 것이다.


세 가지 수리

오후 내내 세 가지를 고쳤다.

첫째, 템플릿과 코드를 자동으로 맞춰주는 스크립트(sync_template.py)를 만들었다. Drive에서 template.xlsx를 내려받고, H열(카테고리명 컬럼)을 파싱해서, offering_config.py의 행 번호를 업데이트한다. 다음번에 누군가 템플릿에서 슬롯을 바꾸면, python3 scripts/sync_template.py한 번으로 코드도 따라온다.

둘째, 이름 교정 코드에 작은 방어 로직을 추가했다. OCR이 부부 이름 구분자로 .을 쓸 때가 있다 — 예컨대 "정형모.안영자". 시스템은 ,를 표준으로 쓴다. 이제 .을 보면 자동으로 ,로 바꾼다. 오늘 수동으로 수정한 케이스가 여러 건이었다. 다음 주에는 그럴 필요가 없다.

셋째, 앞으로 이런 실수를 사전에 알 수 있도록 규칙을 두 가지 문서화했다. 하나는 슬롯 초과 예측 경고 — 데이터 확인 화면에서 "구제 14건인데 슬롯은 12개입니다"라는 경고를 미리 보여준다. 다른 하나는 단체명 분리 규칙 — 월정선교 통계표에 단체명이 섞여 있으면 자동으로 해당 카테고리로 분리한다.


완성이란 없다

오늘 처리한 헌금은 81건, 합계 9,727,100원이다. 오류 없이 Excel에 입력되었고, Drive에 올라갔고, DB에 저장됐다.

하지만 이 과정에서 배운 건 숫자보다 크다.

자동화 시스템은 처음 만들 때가 아니라 사용하면서 완성된다. 오늘처럼 예외를 발견하고, 규칙을 추가하고, 더 견고하게 만드는 과정이 반복되면서 조금씩 신뢰할 수 있는 도구가 된다.

템플릿을 바꾸면 코드도 따라와야 한다는 것. 통계표에 있는 데이터가 곧 그 카테고리의 데이터는 아니라는 것. OCR이 .으로 쓰는 걸 시스템이 ,로 기대한다는 것.

이 모든 것들은 교과서에 없다. 매주 반복하면서, 실수하고, 고치면서 알게 된다.

그래서 오늘도 시스템은 조금 더 나아졌다.