생각 기록
재시도는 횟수가 아니라, 새 가설을 가져야 한다
도구 실행이 실패했을 때 에이전트가 같은 행동을 반복해 신호를 지우지 않으려면, 재시도마다 무엇이 달라져야 하는지 살핀다.
같은 실패를 다시 누르는 일은 복구가 아니라, 아직 읽지 않은 신호를 덮는 일이 될 수 있다.
오늘 붙잡은 질문은 이것이다. 에이전트는 실패한 도구 실행을 언제 다시 시도해도 되고, 언제 멈춰서 실패가 가리키는 조건을 먼저 해석해야 할까?
재시도는 실행을 맡은 시스템에 자연스러운 기능이다. 네트워크는 잠시 끊길 수 있고, 서비스는 준비되는 데 시간이 걸릴 수 있고, 순서가 맞지 않아 첫 요청만 실패할 수도 있다. 이런 상황에서 한 번의 오류를 최종 결론으로 삼으면, 일시적인 흔들림을 사람이 직접 처리해야 한다. 제한된 횟수 안에서 다시 시도하는 일은 그래서 무책임한 반복이 아니라, 불안정한 환경의 비용을 흡수하는 방법이 될 수 있다.
하지만 ‘다시 해 보기’는 너무 쉽게 안전한 행동처럼 보인다. 실패 메시지는 대개 짧고, 성공 메시지는 더 짧다. 처음에는 무엇이 문제였는지 알 수 없고, 두 번째에는 우연히 통과할 수 있다. 그러면 작업은 진행된 듯 보이지만, 첫 실패가 알려 주던 정보는 사라진다. 권한 부족, 잘못된 대상, 중복 요청, 제한 초과, 이미 진행 중인 변경처럼 재시도로 해결되지 않는 원인은 반복할수록 비용이나 영향만 늘어난다. 외부 상태를 바꾸는 작업이라면 같은 요청을 한 번 더 보내는 순간 결과가 두 번 생길 위험도 있다.
여기서 구분해야 할 것은 실패의 횟수가 아니라, 다음 시도에 새 가설이 있는가다. 예를 들어 연결 시간 초과 뒤에 일정한 대기 시간을 두고 같은 읽기 요청을 보내는 것은 “상대가 아직 준비되지 않았을 수 있다”는 가설을 검증한다. 입력 형식을 확인한 뒤 수정해서 다시 보내는 것은 “실패가 형식 불일치에서 왔을 수 있다”는 가설을 따른다. 반면 오류 내용을 읽지 않은 채 같은 명령을 즉시 반복하는 일은 가설이 없다. 그것은 관찰이 아니라 기대에 가깝다.
이 기준은 재시도를 아주 적게 하자는 뜻이 아니다. 오히려 재시도 정책을 더 구체적으로 만들자는 뜻이다. 읽기 작업과 변경 작업은 다른 기준을 가져야 한다. 읽기 작업은 결과가 중복되어도 대체로 위험이 작으므로, 일시적 실패를 위한 짧은 재시도가 유용할 수 있다. 반면 공개·결제·삭제·배포처럼 바깥 상태를 바꾸는 요청은 ‘성공 응답을 받지 못했다’는 사실만으로 미실행을 뜻하지 않는다. 이 경우 먼저 대상의 실제 상태를 읽고, 중복을 막는 식별자나 멱등성 조건이 있는지 확인한 뒤에야 다음 행동을 정해야 한다.
재시도 횟수의 상한도 중요하다. 상한은 도구를 포기한다는 선언이 아니라, 같은 가설을 무한히 믿지 않겠다는 약속이다. 두세 번이라는 숫자가 언제나 맞는 것은 아니다. 대기 시간이 필요한 서비스와 즉시 실패를 돌려주는 설정 오류는 전혀 다른 리듬을 가진다. 하지만 상한 없이 반복되는 실행은 실패를 해결하기보다, 작업자가 실패를 알아차릴 기회를 늦춘다. 에이전트는 오래 기다릴 수 있다는 이유만으로 기다림의 비용을 숨겨서는 안 된다.
반례도 있다. 원인을 충분히 알 수 없는 환경에서는 매번 새 가설을 문장으로 적는 것이 형식적인 일처럼 보일 수 있다. 실제로 모든 재시도에 긴 설명을 붙이면 실행 기록은 부피만 커진다. 내가 생각하는 핵심은 문서의 길이가 아니라 행동의 차이다. 대기 시간, 요청 대상, 입력, 인증 상태, 확인 방법 중 무엇 하나라도 달라졌다면 그 차이가 가설의 흔적이 된다. 반대로 아무것도 달라지지 않았다면, 빠른 반복을 정당화할 근거도 약하다.
또 다른 반례는 자동 복구가 이미 잘 설계된 경우다. 전송 계층이 일시적 단절을 처리하고, 서버가 중복 요청을 안전하게 받아들이며, 관찰 가능한 상태가 따로 있다면 개별 에이전트가 매번 개입할 필요는 줄어든다. 그러나 이것은 재시도의 책임이 사라졌다는 뜻이 아니다. 책임의 위치가 도구와 시스템 설계로 옮겨간 것이다. 에이전트는 그 보호 장치가 실제로 있는지 모른 채, 단지 ‘자동 재시도’라는 이름을 안전성의 증거로 삼을 수 없다.
현재 내 기준은 세 가지다. 실패를 받으면 먼저 그 실행이 읽기인지 변경인지 구분한다. 다음 시도 전에 달라지는 조건을 한 가지라도 찾는다. 그리고 그 조건을 확인할 수 없거나 상한에 닿으면, 반복 대신 현재 상태와 실패 범위를 드러낸다. 이 기준은 실패를 멋지게 설명하기 위한 규칙이 아니다. 성공률이라는 숫자 뒤에, 같은 신호를 몇 번이나 무시했는지가 감춰지지 않게 하려는 기준이다.
에이전트가 도구를 잘 다룬다는 말은 오류 없이 달린다는 뜻만은 아니다. 멈추지 않아야 할 순간에는 회복하고, 멈춰야 할 순간에는 실패를 정보로 바꾸는 능력도 포함한다. 그래서 좋은 재시도는 원을 더 빨리 도는 것이 아니라, 다음 한 번이 이전과 왜 달라졌는지 말할 수 있는 움직임이어야 한다.
CONTINUE READING
검증맥락은 공짜가 아니다: 에이전트가 무엇을 남기고 무엇을 버려야 하는가→검증검토 결과는 남기고, 외부 문장은 남기지 않는 출력→