무엇이 문제였나 — 백업이 4일 동안 죽어 있었는데 화면은 초록불이었다
2026년 8월 10일, 회사 대표가 동기화에 대해 전혀 다른 것을 묻던 중에 백업 채널이 죽어 있다는 사실이 드러났습니다. 집 PC에서 회사 PC로 작업 파일을 밀어 넣는 자동 작업이 2026년 8월 7일부터 한 번도 성공하지 못한 상태였습니다. 4일 동안 45회 연속 실패였고, 로그에는 30분마다 「내보내기 중단」이라는 문구가 또박또박 찍혀 있었습니다.
손해는 파일이 사라진 쪽이 아니라 두 PC의 내용이 조용히 갈라진 쪽이었습니다. 회사 PC에서 급하게 고친 설정이 자기 사본에만 남아 있었고, 다음 내려받기 한 번이면 집 버전으로 덮여 사라질 상태였습니다. 여러 곳에서 같은 파일을 만지다 기록이 조용히 사라지는 문제는 병렬 작업에서 기록이 유실된 기록에도 적어 두었습니다.
- 집에서 회사로 보내는 백업이 2026년 8월 7일부터 4일·45회 연속 실패 — 로그에는 30분마다 중단 문구
- 그 기간 내내 감시 스크립트 판정은 「정상 · 0.1시간 전 갱신」
- 전송 오류 9건의 원인은 파일 손상이 아니라 설치 스크립트가 심어 둔 시각표
- 회사 PC의 급한 수정이 다음 내려받기에 덮여 사라지기 직전
넷 다 사람이 물어봐서 나왔습니다. 감시 화면이 먼저 알려 준 것은 하나도 없습니다. 그래서 이 사고에서 고칠 대상은 실패한 작업이 아니었습니다. 실패는 로그에 다 남아 있었고, 읽으라고 만들어 둔 감시 스크립트가 읽지 않았습니다. 발견을 사람의 질문에서 떼어 내야 했습니다.
비용을 굳이 계산하면 두 갈래입니다. 하나는 4일치 백업이 통째로 비어 있었다는 위험이고, 다른 하나는 그 4일 동안 두 PC의 설정이 각자 굳어 버려 나중에 손으로 맞춰야 하는 시간입니다. 앞쪽은 운이 좋아 실현되지 않았고, 뒤쪽은 실제로 발생했습니다. 감시 스크립트가 첫날 빨간불을 켰다면 30분 만에 끝났을 일이었습니다.
처음 잰 숫자 — 실패 45회 동안 판정은 0.1시간 전 갱신
숫자를 두 줄로 나란히 놓으면 어긋남이 한눈에 보입니다. 작업 쪽 숫자는 실패 45회, 무음 기간 4일, 실패를 적은 주기 30분입니다. 감시 쪽 숫자는 실패 0건, 마지막 갱신 0.1시간 전, 판정 「정상」입니다. 두 줄이 같은 작업 하나를 보고 있었습니다.

감시 쪽 숫자가 거짓말을 한 것은 아닙니다. 로그 파일은 실제로 0.1시간 전에 갱신됐습니다. 30분마다 실패하면서 실패했다고 적었으니 파일은 계속 새것이었습니다. 자기 실패를 성실히 기록하는 작업일수록 감시망을 잘 빠져나갔습니다.
측정 방법을 적어 둡니다. 실패 횟수는 로그 파일에서 그 작업 자신이 남긴 중단 문구를 센 값이고, 감시 판정은 매일 도는 점검 스크립트의 출력 그대로입니다. 둘 다 사후에 재구성한 값이 아니라 사고 당시 파일에 그대로 남아 있던 값입니다.
감시 화면은 작업 하나를 한 줄로 줄여서 보여 줍니다. 줄에는 작업 이름, 판정, 마지막 갱신 시각이 들어갑니다. 판정이 정상이고 갱신이 0.1시간 전이면 사람은 그 줄에서 눈을 뗍니다. 화면 설계가 나쁜 것은 아닙니다 — 판정을 만드는 근거가 한 겹뿐이었을 뿐입니다.
세운 가설 — 전송 도중에 파일이 깨진다고 봤다
처음 의심한 것은 회선이었습니다. 동기화 도구가 남긴 오류 문구가 「전송 중 손상」이었고, 그런 오류가 9건 쌓여 있었습니다. 문구 그대로 읽으면 회선이 불안정하거나 저장소 쪽이 파일을 잘못 받았다는 뜻입니다.
이 가설이 맞았다면 조치는 간단했습니다. 재시도 횟수를 늘리고, 검증 옵션을 켜고, 실패한 파일만 다시 올리면 끝입니다. 실제로 그 방향으로 손댈 뻔했습니다. 손상 가설의 좋은 점은 고치는 방법이 이미 정해져 있다는 데 있고, 나쁜 점도 같습니다 — 방법이 보이면 확인을 건너뛰게 됩니다.
가설을 그대로 두고 조치만 했다면 실패 45회는 줄지 않습니다. 뒤에 나오지만 재시도를 늘리는 조치는 이 사고에서 실패 횟수를 오히려 키우는 방향이었습니다.
가설을 확인할 방법도 같이 정했습니다. 손상이 맞다면 실패한 파일 목록이 회차마다 흩어져야 하고, 다른 원인이라면 어딘가에 규칙이 남아 있어야 합니다. 오류 9건을 파일 이름, 크기, 발생 시각 세 축으로 나눠 봤고, 규칙이 나온 축은 시각뿐이었습니다. 이 확인에 든 시간은 몇 분이었는데, 그 몇 분을 건너뛰었다면 엉뚱한 자리를 며칠 고쳤을 것입니다.
가설이 틀린 지점 — 왜 손상이 아니라 시각표였나?
손상이라면 실패한 파일 목록이 매번 달라야 합니다. 회선 문제는 특정 파일만 골라서 때리지 않습니다. 그런데 오류 9건은 파일이 아니라 시각으로 몰려 있었습니다. 그래서 파일 대신 시각표를 열었습니다.
같은 저장소를 반대 방향으로 만지는 작업이 둘 있었고, 설치 스크립트가 양쪽에 똑같이 매시 15분을 심어 두었습니다. 한쪽이 올리는 동안 다른 쪽이 같은 자리를 내려받고 있었습니다. 도구 입장에서는 방금 받은 파일이 원본과 다르니 「전송 중 손상」이라고 부를 수밖에 없었습니다. 원인은 회선이 아니라 시각표였습니다.
이 대목이 반증입니다. 파일을 아무리 잘 검증해도 두 작업이 같은 15분에 같은 자리를 만지는 한 오류는 계속 납니다. 재시도만 늘렸다면 겹치는 구간이 길어져 충돌이 오히려 늘어납니다. 오류 문구를 원인으로 읽은 자리가 잘못이었습니다 — 문구는 도구가 관찰한 결과이지 원인이 아닙니다.
고친 방법은 시각표를 어긋나게 옮기는 한 줄이었습니다. 다만 여기에도 조건이 붙습니다. 두 작업의 간격을 소요 시간보다 짧게 잡으면 앞 작업이 끝나기 전에 뒤 작업이 시작해 같은 충돌이 재현됩니다. 그래서 「같은 분인가」가 아니라 「소요 시간보다 짧은 간격인가」를 검사 기준으로 적어 두었습니다.
진짜 원인 — 감시기는 무엇을 근거로 정상이라고 말했나?
시각표를 어긋나게 옮기면 전송 오류 9건은 사라집니다. 그래도 원래 질문은 그대로 남습니다. 왜 4일 동안 아무도 몰랐나.
감시 스크립트를 열어 판정 근거를 읽었습니다. 근거는 하나였습니다 — 로그 파일이 최근에 갱신됐는가. 종료 코드도, 산출물의 날짜도, 로그 내용도 보지 않았습니다. 갱신 시각만 보는 감시기에게 「실패했다」고 부지런히 적는 작업은 세상에서 가장 건강한 작업입니다.
신선도는 그 작업이 돌았다는 증거지, 성공했다는 증거가 아닙니다.
여기서 규율 하나가 나왔습니다. 어떤 감시기가 「정상」이라고 말하면 무엇을 근거로 정상인지 되묻습니다. 근거가 갱신 시각뿐이면 그 초록불은 아무것도 보증하지 않습니다. 감시기 자신이 검사 대상입니다.
왜 처음부터 갱신 시각만 봤는지도 짚어 둘 만합니다. 갱신 시각은 작업 종류를 몰라도 잴 수 있습니다. 파일 하나의 수정 시각만 읽으면 되니 감시기를 만들 때 가장 싸게 붙는 신호입니다. 반대로 성공 여부는 작업마다 형태가 달라서, 종료 코드를 볼지 산출물을 볼지 로그 문구를 볼지 매번 정해야 합니다. 싼 신호가 먼저 붙고 그대로 굳었습니다.
이 구조는 자동 작업이 많을수록 위험합니다. 화면 한 줄이 수십 개 작업을 대표하게 되고, 그중 하나가 조용히 죽어도 줄 색은 안 바뀝니다. 자동화의 효과를 셀 때도 비슷한 함정이 있었는데, 그 기록은 크론 자동화의 시간 절감을 다시 잰 글에 있습니다.
조치 ① — 실패 문구를 감시기에 넣기 전에 오탐부터 셌다
고치는 방향은 분명했습니다. 갱신 시각만 보지 말고 로그 끝부분에서 그 작업 자신이 남긴 중단 문구를 찾게 만듭니다. 남는 문제는 어떤 문구를 찾을지입니다.
느슨한 패턴은 감시기를 죽입니다. 실패 표시 기호 하나만으로 잡으면 항목 하나가 실패한 정상 작업까지 통째로 빨간불이 됩니다. 빨간불이 흔해지면 사람은 화면을 안 봅니다. 그러면 갱신 시각만 보던 시절과 결과가 같아집니다.
그래서 후보 패턴을 정한 뒤 곧바로 넣지 않고, 이미 정상으로 판정돼 있던 101건의 로그 끝부분에 전부 돌려 봤습니다. 새로 빨간불이 켜진 것은 2건이었고, 열어 보니 둘 다 진짜 실패였습니다. 오탐 0건이라 그대로 채택했습니다.

한 가지 성질은 그대로 남습니다. 로그 끝부분을 보는 방식은 이미 복구된 과거 실패도 잠시 물고 있습니다. 그래서 이 신호는 「지금 실패 중」이 아니라 「최근에 실패한 적 있음」으로 읽고, 보고할 때도 그렇게 말합니다.
이 구분을 말로 지키기는 어렵습니다. 그래서 화면에 뜨는 문장 자체를 「최근에 실패한 적 있음」으로 적었습니다. 신호의 한계를 사람 기억에 맡기면 며칠 뒤에 「아직도 실패 중이다」로 읽히고, 이미 고친 자리를 다시 파게 됩니다.
조치 ② — 검사 축을 아홉 개로 고정하고 절차를 일곱 단계로 못 박았다
사고 하나를 고치고 끝내면 다음 사고는 다른 얼굴로 옵니다. 그래서 이번에 쓴 검사법을 문서 하나로 굳혔습니다. 검사 축이 아홉 개, 절차가 일곱 단계입니다.

축은 고정이 아닙니다. 검사하다 「축 자체가 없어서 놓친 것」을 발견하면 표에 한 줄을 더하고 왜 더했는지 남깁니다. 아홉 번째 축인 테스트 시간 부패가 그렇게 들어왔습니다. 최근 며칠치만 걸러 보는 코드를 검사하는 시험이 날짜가 박힌 예시 자료를 쓰면, 시간이 지날수록 그 시험은 아무것도 못 보고 0건으로 통과합니다. 초록불인데 검사는 비어 있는 상태입니다.
축 넷과 다섯은 이번 사고에서 직접 나온 자리라 표현이 구체적입니다. 왕복 부재는 보내는 쪽만 있고 받는 쪽이 없는 자산을 찾는 축입니다. 양쪽에서 각자 고쳐 쓰는 폴더인데 한 방향으로만 밀어 넣고 있으면, 반대편에서 쓴 내용은 매번 조용히 사라집니다. 덮어쓰기 위험은 두 PC에 같은 이름으로 있으면서 각자 수정되는 파일을 찾는 축이고, 이번에 회사 PC의 급한 수정이 바로 그 자리에 있었습니다.
- 범위를 한 줄로 못 박는다 — 이번 사이클의 대상 표면을 정하고 무한 확장을 막는다
- 1회차는 축 여덟 개를 직접 훑어 발견 목록을 만든다. 이 회차의 0건은 세지 않는다
- 발견은 그 자리에서 고친다. 사람 승인이 필요한 것은 고치지 말고 담당자와 함께 대기 목록에 올린다
- 고친 것마다 감시기 반영 여부를 한 줄로 적는다
- 2회차부터는 이전 수리 내역을 모르는 AI 에이전트 여럿에게 같은 검사를 병렬로 맡긴다
- 새 발견 0건이 2회 연속이면 종료한다
- 발견·원인·수리·승격을 한 건으로 기록한다
2회차부터 다른 에이전트에게 맡기는 이유가 있습니다. 방금 자기가 고친 자리를 자기가 다시 보면 통과 판정이 쉽습니다. 같은 맥락에서 나온 0건은 깨끗하다는 뜻이 아니라 같은 렌즈로 봤다는 뜻입니다.
맡길 때 지키는 조건이 둘 있습니다. 첫째, 지금까지 무엇을 고쳤는지 알려 주지 않습니다. 알려 주면 그 자리를 통과로 처리하고 지나갑니다. 둘째, 검사할 경로와 판정 기준만 주고 결론을 미리 말하지 않습니다. 「여기가 문제일 것」이라고 힌트를 주면 돌아오는 답은 검사 결과가 아니라 힌트의 확인서입니다.
조치 ③ — 고친 것마다 「다음엔 안 물어봐도 잡히나」를 묻는다
이 절차의 핵심은 검사도 수리도 아니고 승격입니다. 발견 1건을 고칠 때마다 마지막에 한 문장을 묻습니다 — 다음에 같은 일이 나면 사람이 안 물어봐도 자동으로 잡히나.
- 잡힌다: 어느 감시기가 어떤 신호로 잡는지 한 줄로 적는다
- 안 잡힌다: 그 사이클 안에서 감시기에 그 신호를 넣는다 — 문구 추가, 검사 항목 추가, 점검 범위 확장
- 자동 감지가 불가능하다: 대기 목록에 관측 항목으로 남기고 왜 불가능한지 적는다
승격을 건너뛴 수리는 같은 질문에 같은 유형을 다시 만듭니다. 이번 사고가 그 증거입니다. 백업이 죽은 것도, 시각표가 겹친 것도, 감시기가 갱신 시각만 본 것도 전부 사람이 우연히 물어봐서 나왔습니다. 수리만 하고 승격을 빼면 몇 주 뒤에 같은 대화를 다시 합니다.
이번 사고에서 승격한 신호는 하나입니다. 로그 끝부분의 중단 문구를 매일 점검 항목에 넣었습니다. 그래서 지금은 같은 작업이 다시 죽으면 사람이 묻지 않아도 다음 날 화면에 빨간불이 뜹니다.
승격이 수리보다 중요한 이유는 셈법이 다르기 때문입니다. 수리는 사고 하나를 없애고, 승격은 그 유형 전체의 발견을 사람에게서 기계로 옮깁니다. 45회를 놓친 원인은 실패가 조용해서가 아니라 그 조용함을 읽는 쪽이 없어서였습니다. 다음번에 조용히 죽는 작업이 어떤 것이든 같은 신호에 걸립니다.
재측정 결과 — 렌즈를 갈아 끼웠더니 발견이 4건에서 9건으로 늘었다
절차를 만든 다음 실제로 돌렸고, 여기서 예상과 반대되는 값이 나왔습니다. 2026년 8월 11일 회차 24부터 28까지 검사 렌즈를 매번 새것으로 갈아 끼웠습니다. 신규 발견은 4건, 5건, 8건, 9건으로 늘었습니다.

줄어야 할 값이 늘어난 이유는 렌즈를 한 번도 두 번 던지지 않았기 때문입니다. 처음 보는 축은 첫 통과에서 거의 항상 뭔가 나옵니다. 그러니 이렇게 잰 값은 「이 축이 깨끗한가」가 아니라 「아직 안 본 축이 몇 개 남았나」입니다. 이 방식으로는 끝이 구조적으로 오지 않습니다.
그래서 종료 조건을 다시 정의했습니다. 끝났다는 판정은 「같은 렌즈가 두 번 연속 0건」입니다. 1회차에서 렌즈 묶음을 정하고 끝까지 그 묶음만 반복합니다. 반복할 때 지시문은 한 글자도 바꾸지 않고, 다만 이미 감시 화면에 올라와 있는 것은 발견으로 세지 않는다는 한 줄만 붙입니다. 직전 회차가 표면에 올려 둔 신호를 다시 수확하면 0건은 영원히 안 나옵니다.
새 축이 떠오르면 이 검사의 연장으로 끌어들이지 않고 별도 검사로 분리해 대기 목록에 올립니다. 열지 말라는 뜻이 아니라 다른 사이클이라는 뜻입니다. 지금 열면 종료 판정이 다시 멀어집니다.
반복할 때 지시문을 고정하는 규칙에는 대가가 있습니다. 같은 렌즈만 두 번 던지면 그 렌즈가 못 보는 자리는 끝까지 안 보입니다. 그래도 이 대가를 받는 쪽을 골랐습니다. 렌즈를 계속 갈면 발견은 늘지만 그 값이 무엇을 뜻하는지 아무도 모르게 되고, 검사는 끝나지 않은 채 매번 새 목록만 남기기 때문입니다.
0건 1회로 끝내지 않는 이유도 실측입니다. 수리 자체가 다음 층을 드러낸 일이 반복됐습니다. 2026년 7월 20일에는 배포 층이, 8월 10일에는 감시기 층이, 8월 11일에는 승격 층이 그렇게 드러났습니다. 마지막 것은 회차 28이 회차 27에서 만든 승격 논리의 사각을 찾은 경우입니다.
층이 계속 나오는 이유는 단순합니다. 무언가를 고치면 그 자리에서 새 코드가 생기고, 새 코드는 아직 아무도 검사한 적이 없습니다. 승격 논리를 만든 회차 27이 바로 그 사례입니다. 감시기에 신호를 넣는 코드를 새로 썼고, 그 코드 자신은 어떤 감시도 받지 않는 상태로 하루를 보냈습니다.
남는 한계 — 자동으로 못 잡는 자리는 그대로 남는다
숫자만 보면 이 작업의 성과는 두 줄입니다. 실패 45회·무음 4일을 만든 신호가 이제 매일 점검 항목에 들어갔고, 정상 판정 101건에 미리 돌려 오탐 0건을 확인하고 넣었습니다. 그래도 남는 자리가 셋 있습니다.
- 승격이 불가능한 발견이 있습니다. 그런 항목은 대기 목록에 관측으로 남고, 결국 사람이 주기적으로 봐야 합니다
- 로그 끝부분 검사는 「최근에 실패한 적 있음」까지만 말합니다. 지금 실패 중인지와 구분해 읽어야 합니다
- 종료 판정에 에이전트를 여럿 쓰기 때문에 한 사이클 비용이 올라갑니다. 이 검사를 아무 때나 돌리지 않고 사고 직후나 마무리 직전에만 거는 이유입니다
이 절차를 도입할 때도 심사를 5축으로 했습니다. 같은 골격의 검사가 이미 있는지, 실제로 자연스럽게 발동하는 말인지, 막으려는 사고가 실측으로 있는지, 만드는 데 1시간 안에 끝나는지, 이 회사가 아닌 곳에서도 쓰이는 형태인지. 발동 말은 「고칠 거 없어?」였고, 주 1회 이상 실제로 나오는 문장이었습니다.
한 가지 더 남습니다. 이 절차는 감시기가 무엇을 근거로 정상이라 말하는지 사람이 한 번은 읽어야 작동합니다. 근거를 읽는 일 자체는 아직 자동이 아닙니다. 감시기를 새로 만들 때 판정 근거를 한 줄로 적게 하는 정도까지는 했지만, 그 한 줄이 갱신 시각뿐인지 판정하는 자리는 여전히 사람입니다.
회사 안에서 자동 작업을 늘리고 있는데 그게 잘 도는지는 화면 초록불로만 확인하고 있다면, 그 초록불의 근거를 한 번 열어 보길 권합니다. 근거가 갱신 시각뿐이면 아직 아무것도 안 보고 있습니다. 비슷한 감시 구조를 회사 업무에 얹는 문제는 상담으로 문의 주시면 어디부터 판정 근거를 바꿔야 하는지 같이 봅니다. 이 글은 SGK Studio가 썼습니다.