같은 7명이 14번 등록됐다
운영 중인 커뮤니티에는 결제가 들어오면 멤버 명단 시트에 새 등록자를 추가해 주는 동기화 봇이 있다. 정해진 주기로 돌고, 이미 명단에 있는 사람은 건너뛴다. 몇 달을 조용히 잘 돌던 봇이었다.
지난 5월, 명단 시트를 정리하다가 이상한 걸 봤다. 같은 사람들이 시트 아래쪽에 줄줄이 반복되고 있었다. 세어 보니 일곱 명이 각각 열네 번씩. 어쩌다 섞인 점(.) 하나짜리 행까지, 중복이 총 99행이었다.
3시간 20분의 기록
로그를 거슬러 올라가니 사고는 닷새 전 오후에 있었다. 15시 2분부터 18시 20분까지, 3시간 20분 동안 봇이 매 실행마다 같은 7명을 “새 등록자"로 판정해 시트에 다시 추가하고 있었다.
이상한 건 쓰기가 아니라 읽기였다. 추가(append)는 매번 정상으로 동작해서 데이터는 시트 끝에 착실히 쌓였다. 그런데 다음 실행이 중복 검사를 하려고 명단을 읽어 오면, 방금 추가한 행들이 보이지 않았다. 읽기가 계속 과거를 보고 있었던 것이다.
당시 명단은 4,000행 이상의 큰 시트였고, 열 하나만 부분 조회하는 API 호출이 한동안 갱신 전 값을 돌려준 것으로 추정한다. 추정이라고 쓰는 이유는, 재현이 안 됐기 때문이다. 같은 조건으로 다시 돌려도 멀쩡했다. 원인을 확정할 수 없었다.
원인을 못 잡으면 재발 조건을 잡는다
원인 규명이 끝나야 고칠 수 있는 건 아니었다. 이 사고가 다시 나려면 반드시 거쳐야 하는 길목들이 있고, 그 길목마다 문을 달면 된다.
세 겹을 세웠다.
- 부분 조회를 버렸다. 열 하나만 읽던 호출을 없애고, 시트 전체를 한 번에 받아 중복 검사 목록을 만든다. 문제가 관측된 경로 자체를 제거.
- 같은 판정이 반복되면 스스로 멈춘다. 직전 실행의 “새 등록자” 목록을 상태 파일에 남기고, 같은 목록이 3회 연속 나타나면 추가를 중단한다. 정상 운영에서 같은 7명이 세 번 연속 신규일 확률은 0에 가깝다.
- 추가하면 바로 다시 읽는다. append 직후 시트를 재조회해 방금 넣은 값이 실제로 보이는지 검증한다. 안 보이면 에러를 남기고 알린다.
여기에 상태 파일에 마지막 실행의 결과(검증 성공 / 검증 실패 / 중단)를 남겨서, 나중에 로그를 열었을 때 봇이 어떤 상태로 끝났는지 한 줄로 알 수 있게 했다.
그 뒤로 같은 사고는 없다. 원인은 아직도 모른다. 그래도 괜찮다고 생각한다. 자동화를 몇 달 운영하며 배운 것 중 하나는, “왜 그랬는지"보다 “다시 그러면 어떻게 되는지"가 먼저라는 것이다. 원인은 못 잡아도 재발 조건은 잡을 수 있다.
연재 “사고의 해부"는 자동화가 터진 날들의 부검 기록입니다. 다음 화: 시즌 첫날 결제한 13명이 명단에서 사라진 이야기.