운영 매뉴얼 18편을 코드와 대조했더니 넷이 반대로 적혀 있었습니다
B2B 채권 분석 시스템의 월별 원장 업무를 정리한 매뉴얼 사이트가 있습니다. 과업 범위·회차별 계획·검수 절차·용어를 열여덟 편으로 나눠 둔 것입니다. 장식용 문서가 아니라 다음 회차에 무엇을 먼저 할지 정할 때 실제로 열어 보는 문서입니다.
이 매뉴얼의 상당수가 한 달 전 상태를 기준으로 쓰여 있었습니다. 그 사이 코드는 계속 나갔습니다. 문서가 낡았다는 것은 알고 있었지만 얼마나 낡았는지는 재본 적이 없었습니다. 그래서 한 회차를 통째로 써서 열여덟 편 전부를 개발 브랜치 코드·운영 DB·작업 기록 셋과 맞춰 봤습니다.
반대로 적혀 있던 것이 넷 나왔습니다
틀린 문장이 나온 것이 아닙니다. 방향이 뒤집힌 문장이 나왔습니다.
'그 판정이 꺼져 있다, 켜는 게 먼저다' — 열흘 전에 이미 켜져 있었습니다. 수익률 지표의 상한·하한 판정이 사유 컬럼까지 붙어 돌고 있었습니다.
'그 월간 생성을 부르는 배치 자리가 없다' — 자리는 아흐레 전에 생겼습니다. 실행기가 39개에서 40개가 됐습니다. 그런데 운영 DB 의 배치 등록 테이블에 그 행이 없어서 한 번도 안 돌았습니다.
'그쪽 기관 유형은 아직 검증도 안 됐다' — 통합 1차는 끝났고 검증이 진행 중이었습니다.
'그 상태조건은 추가 검토 대상' — 이미 반영돼 있었습니다. 계획표 동기화에 확정일 관문이 붙어 있었습니다.
첫 번째가 가장 비쌌습니다. 매뉴얼이 그 항목을 '다음 회차의 1순위 과제'로 세워 두고 있었기 때문입니다. 이미 켜져 있는 것을 1순위로 잡고 있었던 것입니다. 낡은 문장도 계속 판단의 근거로 쓰입니다.
그리고 이 넷은 전부 문체가 멀쩡했습니다. 맞는 문장과 구체성도 자신감도 똑같았습니다. 특히 '아직 안 됐다'는 서술은 그 자체로 그럴듯해서 검증을 부르지 않습니다. 이 사례에서 문서가 틀린 이유는 없는 말을 새로 만들었기 때문이 아니라, 한때 맞았던 문장이 그대로 남았기 때문입니다.

코드만 봤으면 못 잡았을 칸이 있었습니다
대조는 셋을 다 보는 것으로 했습니다. 하나만 봤으면 통째로 놓쳤을 것이 있었기 때문입니다.
무엇을 보나 | 그것만 보면 놓치는 것 |
|---|---|
코드 (개발 브랜치) | 클래스가 생겼는지는 알지만 운영에 등록됐는지는 모른다 |
운영 DB | 무엇이 실제로 돌았는지는 알지만 왜 그렇게 짰는지는 모른다 |
작업 기록 | 무엇을 하려 했는지는 알지만 거기서 멈췄는지는 모른다 |
앞의 둘째 항목이 정확히 그 자리였습니다. 코드에는 실행기가 있으니 코드만 보면 됐다고 읽힙니다. 작업 기록에도 완료로 찍혀 있으니 기록만 봐도 됐다고 읽힙니다. 그런데 운영 DB 의 등록 행이 없어서 실행 이력이 0건이었습니다.
그 커밋 메시지에는 'DB 추가해야 함'이 적혀 있었습니다. 남긴 사람은 알고 있었던 것입니다. 다만 그 문장은 코드에도 작업 기록에도 올라오지 않는 자리에 있었습니다. '코드가 있다'와 '돈다'는 다른 말이고, 도는지는 실행 이력으로만 확인됩니다.
나머지 셋은 코드만 봐도 잡혔습니다. 문서가 아직 안 됐다고 말하는 것들은 대개 그 뒤에 조용히 됩니다. 되는 순간에 문서를 고치는 사람이 없기 때문입니다.
같은 축의 글을 하나 더 적어 뒀습니다. 코드가 기다리는 표기와 데이터에 실제로 들어 있는 표기가 갈려 있던 사례입니다.

갱신하다가 새로 만든 오류도 있었습니다
낡아서 생긴 오류만 나온 것이 아닙니다. 문서를 고치는 과정에서 새로 생기는 종류가 따로 있었습니다.
검수 도구가 파이썬 스크립트 열두 개에서 자바 검수 서비스로 옮겨 가는 중이었습니다. 문서에는 새 구현의 항목 목록이 이미 갈아 끼워져 있었습니다. 항목 번호와 이름의 원천은 자바 쪽 열거형 15개로 옮긴 것이 맞습니다. 그런데 러너·순서·제외 연쇄는 아직 만들지 않았고, 지금 매달 도는 것은 여전히 파이썬 러너였습니다.
그 한 줄이 빠지자 문서는 이관이 끝난 것처럼 읽혔습니다. 이관 중인 것에는 '지금 어느 쪽이 도는가'를 반드시 적어야 합니다. 목록만 갈아 끼우면 최신 문서가 아니라 더 그럴듯하게 틀린 문서가 됩니다.
그 밖에 나온 것도 성격이 비슷했습니다. 같은 항목의 조치 방법이 두 문서에서 서로 모순이었습니다. 한쪽은 '미정', 다른 쪽은 '무효화 후 재생성'이었습니다. 앞선 달에 쓴 재료와 그 뒤에 내린 결정이 각각 다른 편에 남아 있었던 것입니다. 사용자 확인을 받아 뒤쪽으로 통일했습니다.
회차 이름이 두 벌이었습니다. 실행한 달로 부르는 표기와 기준월로 부르는 표기가 섞여 같은 회차가 문서마다 다르게 불렸습니다. 기준월 기준 한 벌로 정리했습니다.
존재하지 않는 개념을 설명하는 절이 여러 편에 걸쳐 있었습니다. 인지일은 기준월 1일로 넣는 값이라 소급이라는 개념 자체가 없습니다.
수익률 지표는 개시·재조정 때 한 번 계산하고 상각 때 다시 계산하지 않는데, 정상 사유 표에 상각 관련 행으로 들어가 있었습니다.
코드에 '이런 경우가 있다'는 경고 주석이 있는데 그 경고가 가리키는 비교문 자체가 주석 처리돼 있었습니다. 호출부에도 달 비교가 없었습니다.
마지막 항목은 문서를 고쳐서 해결되는 종류가 아닙니다. 경고만 살아 있고 경고가 가리키는 검사는 멈춰 있었습니다. 주석은 문서와 같은 성질이라 같은 방식으로 낡습니다.
이름을 고치는 것이 문장을 고치는 것보다 오래 갑니다
처방으로 한 것 중 가장 오래 갈 것은 용어 통일이라고 봅니다. '마감 확인'을 '원장 완성 확인'으로 바꿨습니다. 관련 편 여덟 곳의 문구를 같이 정리했습니다.
이 작업은 문구 다듬기가 아닙니다. 전체 생성이 한 번 돈 뒤에도 며칠간 재수행이 붙기 때문에, 배치가 '돌았다'와 원장이 '다 찼다'는 서로 다른 상태입니다. 옛 이름은 그 차이를 감추고 있었습니다. 이름이 사실을 감추고 있으면 그 밑의 설명을 아무리 고쳐도 같은 오해가 다시 쌓입니다.
같은 이유로 매월 검토 흐름에 조건 생성 단계를 새로 넣어 7단계로 늘렸습니다. 원장보다 먼저 도는데 아직 수동이라는 것을 그 자리에 적었습니다. 한 월간 집계 배치에는 그것이 원장 생성이 아니라 합계표 집계라는 주석을 달았습니다. 그 배치는 월초 새벽에 돌고 원장은 같은 날 오후에 쌓이는데, 이름만 보면 원장이 그때 만들어진다고 읽을 자리였습니다. 중단 코드 아홉 개에는 사람이 읽는 라벨을 나란히 적고 운영 실측을 붙였습니다. 한 코드는 2,442건, 다른 하나는 16건이었습니다.
다음 대조를 싸게 만드는 것을 같이 했습니다
이번 대조에 네 시간이 걸린 이유는 '언제부터 안 맞는지'를 모르는 상태에서 시작했기 때문입니다. 기준점이 없으니 열여덟 편을 처음부터 다 봐야 했습니다.
그래서 변경 이력 절에 코드 변경 다섯 건을 날짜와 함께 박아 뒀습니다. 다음에는 그 날짜 이후만 보면 됩니다. 변경 이력은 읽는 사람을 위한 친절이 아니라 다음 대조의 기준점입니다. 없으면 매번 전수 대조를 다시 합니다.
남은 것도 그대로 적어 뒀습니다. 엔진 쪽 세 편에 아직 옛 서술이 남아 있고, 코드 표 하나에 최근 코드 셋이 빠져 있으며 한 코드의 설명은 소스와 반대입니다. 소급 문장도 네 편에 남아 있어 지울지 판단이 필요합니다. 다 고치지 못한 것을 다 고쳤다고 적지 않는 것이 이 작업의 절반입니다.
적어 둔 것과 실제가 갈리는 자리를 다룬 글을 하나 더 두고 갑니다.

같은 일을 하기 전에 볼 것
전수 대조가 늘 답은 아닙니다. 여기서는 네 시간을 써서 넷이 나왔지만, 문서가 얇거나 변경이 드문 곳에서는 같은 시간을 들여도 아무것도 안 나옵니다. 변경 속도와 문서 수명의 비율을 먼저 재는 편이 맞습니다.
이 문서가 판단의 근거로 쓰이는가. 안 읽히는 문서라면 대조 비용을 쓸 자리가 아닙니다.
코드·운영 상태·작업 기록 셋을 다 볼 수 있는가. 하나라도 빠지면 '코드는 있는데 안 돈다'를 구조적으로 못 잡습니다.
문서에 '아직 안 됐다'고 적힌 항목이 몇 개인가. 그것부터 뒤집어 보면 반대가 된 문장이 먼저 나옵니다.
변경 이력에 날짜가 박혀 있는가. 없으면 이번 대조에서 만들고 끝냅니다.
이관 중인 항목에 '지금 어느 쪽이 도는가'가 적혀 있는가.
'문서를 항상 최신으로 유지한다'는 처방이 아닙니다. 그걸 지킬 수 있었으면 애초에 안 틀렸을 겁니다. 현실적인 처방은 둘입니다. 변경 이력에 날짜를 박아 다음 대조를 싸게 만들고, 대조 주기를 회차에 붙이는 것입니다.
자동 생성으로 바꾸는 것도 만능이 아닙니다. 코드에서 뽑으면 '코드가 있다'는 맞게 나오지만 '운영에 등록돼 도는가'는 여전히 안 나옵니다. 이번 대조의 최대 발견이 정확히 그 칸이었습니다. 문서를 기계가 쓰게 만들어도, 실행 이력을 보는 사람은 따로 필요합니다.