증상
스케줄을 외부 서비스로 옮기고 잘 도는 것을 확인했다. 옛 스케줄러에 같은 항목 5줄이 그대로 남아 있었다. 알림이 두 번 가고 큐 작업이 겹쳐 돌았다.
왜 멈추게 되나
★★ 추가는 즉시 효과가 보이고, 제거는 아무 효과도 안 보인다. 새 경로가 도는 것을 확인한 순간 일이 끝났다고 느낀다.
★★★ 그리고 중복은 고장처럼 보이지 않는다. 알림이 두 번 오는 것은 작동 과잉이지 오류가 아니다. 로그에도 에러가 없다. 발견되는 경로는 "왜 두 번 오지?"라고 누가 이상하게 여기는 것뿐이다.
⚠️ ★★★ 그리고 자동 복구 장치가 그 제거를 되돌린다
옛 스케줄에는 보호 목록 기반 자동 복구가 걸려 있었다. 지운 줄이 목록에 남아 있으면 다음 회차에 되살아난다.
★★★ 자동 복구는 "무엇이 정본인가"를 고정한다. 정본이 바뀌면 복구 장치가 가장 먼저 알아야 한다.
★★ 이 컬렉션의 방어가 다음 함정을 만든다 계열에서 또 하나 — 다만 형태가 다르다. 앞의 것들은 장치가 함정을 만들거나 스스로 꺼진 것이고, 이번에는 장치가 정확히 설계대로 작동해서 문제가 됐다.
★★★ 되돌리는 장치가 있는 시스템에서 변경은 항상 두 곳이다 — 대상과 기준선.
이전 체크리스트
grep으로 전부 센다★ 4번이 없으면 어제의 방어가 오늘의 변경을 막고, 원인을 찾는 데 시간이 든다.
⚠️ ★★★ 후속 — 이 체크리스트의 초판에는 0번과 6번이 없었고, 그 자리에서 누락이 났다
같은 이전에서 중복과 누락이 동시에 일어났다. 옛 곳에 5줄이 남아 중복됐고, 한 계정용 구현이 별도 파일이라 새 곳에 안 올라가 누락됐다.
★★★ 정반대 증상인데 원인은 하나다 — 구현 파일 목록을 세지 않았다. 우리는 "무엇을 옮기는가"를 기능 이름으로 알고 있었고, 그 기능은 파일 둘이었다.
★★★ 기능 이름이 아니라 파일 목록이 이전 단위다. ★ 파일명 접미(_v2, _new, 계정명·환경명)는 같은 기능의 형제일 가능성이 높다. 그것들을 세는 것이 0단계다.
★★★ 그리고 누락은 중복보다 훨씬 안 보인다
중복은 "두 번 왔네"로 드러난다. 누락은 아무것도 오지 않는다. 그 대상이 원래 드문 것이라면 정상적인 한가함과 구별되지 않는다 — 앞 항목의 "0건 오탐"과 정확히 같은 벽이다.
★★ 그래서 6번은 "관찰"이 아니라 "대조"여야 한다. 새 곳에서 뭔가 오기를 기다리지 말고, 0단계 목록과 새 곳의 등록 목록을 나란히 놓고 개수를 맞춰라.
★ 애초에 한 계정용 변형을 파일 복사로 만든 것이 뿌리다. 복사로 만든 변형은 기능 단위를 깨뜨린다 — 한 곳을 고치면 다른 곳은 안 고쳐지고, 목록을 안 세면 존재 자체를 잊는다. 차이는 파일이 아니라 인자나 설정으로 두는 편이 낫다.