자동화는 한 번 잘 돌아가기 시작하면 믿음이 생깁니다. 그런데 저는 그 믿음이 가장 위험할 때가 “거의 다 되는데 가끔 하나가 빠지는” 순간이라는 걸 또 배웠습니다.
거의 동시에 온 문자 중 하나가 사라졌다
이번에는 업무용 문자 알림을 웹훅으로 받아 내부 알림방에 전달하는 자동화였습니다. 평소에는 잘 들어오는데, 같은 종류의 배송 알림 문자 2개가 거의 동시에 들어오면 이상하게 꼭 1개가 빠졌습니다. 완전히 안 되는 것도 아니고 매번 안 되는 것도 아니어서 더 헷갈렸습니다.
비개발자인 제 입장에서는 처음에 “문자 파싱이 잘못됐나?”, “중복 차단이 너무 강한가?”, “알림방 주소가 틀렸나?” 같은 생각부터 했습니다. 얼마 전에도 중복 차단 기준 때문에 다른 새 주문까지 막힌 일이 있었기 때문에, 저도 AI도 제일 먼저 중복 로직을 의심했습니다.
원인은 중복 차단이 아니라 마지막 전송이었다
그런데 이번 문제는 결이 조금 달랐습니다. 로그를 따라가 보니 웹훅 자체는 들어오고 있었고, 메시지를 파싱하는 코드에도 큰 문제는 없었습니다. 문제는 마지막 전달 단계였습니다. 외부 메신저 봇 API로 보내는 함수가 실패했을 때 다시 시도하지 않고 딱 한 번만 호출하고 끝나는 구조였습니다.
사실 이 부분은 전에 [AI와 같이 고친 에러들] 문자 중복차단이 새 주문까지 막던 이유에서도 비슷하게 헤맸던 지점이라, 그때 기록을 다시 들여다보면서 확인했다.
두 문자가 거의 동시에 들어오면 두 요청이 같은 봇 API를 거의 같은 순간에 두드리게 됩니다. 이때 외부 API가 잠깐 속도 제한이나 일시 오류를 내면 한 건은 성공하고 한 건은 조용히 실패할 수 있었습니다. 사람 눈에는 “2개 중 꼭 1개가 누락”처럼 보였지만, 코드 입장에서는 “보내기 시도 1회 실패 후 종료”였던 셈입니다.
AI와 같이 실제 수신 경로 파일을 열어 어느 함수가 알림을 보내는지 확인했습니다. 그다음 메신저 API 호출 함수에 재시도 로직이 있는지 찾았습니다. 관련 파일에서 429나 retry 같은 단어를 검색했지만 해당 경로에는 재시도가 없었습니다. 비슷한 다른 경로에는 이미 보강 로직이 있었지만, 이번 실제 경로에는 빠져 있었습니다.
실패할 때만 짧게 다시 시도했다
해결은 “무조건 여러 번 보내기”가 아니었습니다. 그렇게 하면 진짜 중복 발송이 생길 수 있습니다. 대신 외부 API 호출이 속도 제한이나 일시 오류로 실패했을 때만 짧게 기다렸다가 다시 시도하도록 했습니다.
변경이 엉뚱한 브랜치에 섞이지 않도록 작업 중 브랜치 상태도 다시 확인했습니다. 실제로 세션 도중 작업 폴더가 다른 브랜치로 바뀐 흔적이 있어, 임시 작업공간을 따로 만들고 main 기준으로 같은 수정만 깨끗하게 적용했습니다.
이 과정에서 자동화 운영은 세 가지를 따로 봐야 한다는 걸 배웠습니다. 첫째, 메시지가 정상적으로 들어오는가. 둘째, 중복으로 잘못 막히지 않는가. 셋째, 마지막 외부 전송이 실패했을 때 회복할 방법이 있는가.
자동화는 마지막 전달까지 확인해야 했다
외부 서비스와 연결된 자동화는 내 코드가 맞아도 상대 API의 순간적인 제한을 만날 수 있습니다. 그러면 “내 코드가 틀렸다”와 “잠깐 거절당했다”를 구분해야 합니다. 비개발자인 저는 이런 차이를 AI에게 질문하면서 배웁니다. 이번에도 에러 이름과 함수 이름을 하나씩 확인하며 원인을 좁혔습니다.
다음 편에서는 같은 작업 세션에서 발견한 또 다른 교훈, 여러 AI 세션이 같은 폴더를 만질 때 커밋이 엉뚱한 브랜치에 들어갈 수 있다는 이야기를 적어보려고 합니다. 바이브코딩은 코드를 쓰는 일만이 아니라 작업이 어디에 들어갔는지 끝까지 확인하는 일이기도 했습니다.