AI 자동화는 실패한 단계부터 다시 시작할 수 있는가
자료 조회·공지 게시·결과 저장을 한 실행 단위로 묶으면 마지막 단계의 실패가 앞선 게시까지 반복시킬 수 있다. Temporal의 Activity 경계와 완료 기록을 통해 AI 자동화의 재시도 범위를 설계한다.

GPT Image 2로 생성한 개념 이미지. 반복되는 시도와 하나의 업무 결과를 표현했으며 실제 시스템의 구조도는 아니다.
AI가 승인된 공지를 게시하고 처리 결과를 파일에 남기는 업무를 가정해 보자. 공지는 정상적으로 올라갔지만 마지막 파일 저장이 권한 오류로 실패했다. 자동화 화면에는 하나의 작업이 실패했다고 나온다. 다시 실행하면 어느 지점부터 시작될까. 파일 저장부터일 수도 있지만, 공지 게시부터 반복될 수도 있다.
사람에게는 끝난 일과 남은 일이 분명해 보인다. 실행 시스템이 같은 경계를 알고 있다는 보장은 없다. 화면에 보이는 단계, 코드의 함수, 장애 뒤 다시 실행되는 단위가 서로 다를 수 있기 때문이다. AI 자동화의 복구 범위를 결정하는 것은 계획에 적힌 순서만이 아니라, 어떤 결과가 어디에 완료로 기록됐는가다.
멱등성과 영수증을 다룬 앞선 글은 같은 외부 작업이 중복 반영되지 않도록 의도와 시도를 구분하는 원칙을 설명했다. 이번 글에서는 그 원칙을 전제로 한 단계 더 들어간다. 자료 조회, 게시, 결과 저장을 어떤 실행 단위로 묶어야 이미 끝난 일을 다시 하지 않을 수 있는지, Temporal의 현재 Activity 문서를 통해 살펴본다.
세 단계가 한 Activity라면 처음부터 다시 실행된다
Temporal은 실행 이력을 보존해 긴 업무를 장애 뒤에도 이어 가도록 돕는 플랫폼이다. Workflow가 흐름을 조정하고, 외부 API 호출 같은 개별 행동은 Activity라는 함수로 수행한다. 여기서 중요한 것은 한 Activity 안에 작성한 여러 줄의 코드가 자동으로 각각의 복구 지점이 되지는 않는다는 사실이다.
공식 Activity Definition 문서는 데이터베이스 조회, 마이크로서비스 호출, 파일 저장을 한 Activity에 넣은 사례를 든다. 앞의 두 단계가 성공하고 파일 저장만 실패해도 재시도할 때는 Activity 전체가 다시 실행된다. 문서는 이를 더 작은 Activity로 나누면 실패한 단계만 재시도하도록 구성할 수 있다고 설명한다. 동시에 Activity 실행이 늘어나면 Event History도 커지는 비용이 있다고 덧붙인다. Activity 정의와 설계 안내
공지 업무에 적용하면 차이는 구체적이다. 조회부터 결과 기록까지 하나의 Activity로 묶었다면 마지막 저장 오류가 외부 게시의 반복까지 일으킬 수 있다. 게시와 결과 기록을 나누고 게시 Activity의 완료가 Temporal에 기록된 상태라면, 결과 기록을 재시도할 때 이미 끝난 게시를 다시 수행할 필요가 없다. 복구 지점은 담당자가 머릿속으로 구분한 업무 단계가 아니라 시스템이 보존한 완료 결과에 생긴다.
따라서 코드를 짧게 나누는 것만으로 충분하지 않다. 나눈 함수가 같은 Activity 안에서 순서대로 호출된다면 재시도 범위는 여전히 바깥 Activity 전체다. 어떤 단위에 재시도 정책이 붙는지, 그 단위의 완료가 언제 기록되는지 확인해야 한다. 이 설명은 Temporal의 Activity 실행 모델에 관한 것이며 모든 자동화 도구가 같은 경계를 제공한다고 일반화할 수는 없다.
완료 기록을 남기기 직전에도 장애가 난다
단계를 나누면 앞선 작업을 반복하는 범위를 줄일 수 있지만, 외부 시스템과의 경계는 남는다. 게시 전용 Activity에서도 공지 서버의 반영과 Temporal에 완료를 알리는 일은 별개의 사건이다. 공식 문서는 Activity가 작업을 마친 뒤 Worker가 완료 보고 직전에 중단되면 실행 이력에 성공이 남지 않아 Activity가 재시도될 수 있다고 설명한다. 현재 기본 브랜치의 고정 문서
이 상황은 Workflow 재생과 구분해야 한다. 완료가 기록된 Activity는 Workflow가 이력을 재생한다는 이유만으로 다시 실행되지 않는다. 반면 완료가 기록되지 않은 Activity의 재시도는 실제 함수를 다시 실행할 수 있다. 장애 뒤 흐름을 복구한다는 설명을 듣고 모든 외부 호출이 처음부터 반복된다고 생각하거나, 반대로 모든 호출이 반드시 한 번만 일어난다고 생각하면 둘 다 설계를 잘못 읽게 된다.
공지 사례를 두 시점에서 끊어 보면 차이가 드러난다. 게시 완료가 기록된 다음 결과 파일 저장에서 실패한 경우에는 저장 단계의 재시도로 좁힐 수 있다. 그러나 공지 서버가 반영한 직후 완료 보고 전에 끊겼다면 게시 Activity가 다시 실행될 수 있으므로 외부 중복 방지가 필요하다. 같은 공지가 이미 생겼는지 조회하고, 같은 작업의 요청을 반복해도 추가 공지가 생기지 않는 계약을 확인해야 한다.
Temporal 문서는 멱등성 키를 받아 중복을 막는 주체가 호출받는 서비스라고 명시한다. Workflow Run ID와 Activity ID를 조합하는 예도 제시하지만, 키를 만들었다는 사실만으로 게시 서버의 처리 방식이 바뀌지는 않는다. 완료 기록의 경계와 외부 쓰기의 멱등성은 서로 보완하는 설계다. 멱등성 설명
생성과 실행을 나누면 승인된 결과를 보존할 수 있다
여기서부터는 앞의 실행 모델을 AI 업무에 적용한 설계 제안이다. 초안 생성, 사람의 승인, 외부 게시, 결과 기록을 구분하고 각 단계가 다음 단계에 넘길 산출물을 정한다. 단계를 무조건 잘게 쪼개자는 뜻은 아니다. 실패했을 때 다시 계산해도 되는 부분과 그대로 보존해야 하는 결과를 가르는 것이 목적이다.
예를 들어 게시 결과를 기록하다 실패했는데 모델 호출부터 다시 시작하면 초안의 문구와 링크가 달라질 수 있다. 이전에 승인한 글과 새로 생성한 글이 같다는 보장이 없다. 모델의 새 판단을 끼워 넣는 복구는 승인된 작업을 재시도하는 것과 다른 행동이다. 게시 단계에는 승인된 본문 버전과 대상, 작업 식별자를 고정해서 전달하고, 기록 단계에는 외부 게시 ID와 확인한 결과를 넘기는 방식이 적절하다.
이때 각 경계에서 필요한 정보를 구체적으로 적어 볼 수 있다. 아래 표는 제품의 기본 스키마가 아니라 공지 업무를 위한 제안이다.
| 단계 | 다음 단계에 넘길 결과 | 장애 뒤 보존할 것 |
|---|---|---|
| 초안 생성 | 검토할 본문과 참조 자료 | 검토 대상의 버전 |
| 승인 | 승인된 버전과 게시 대상 | 승인 범위와 해당 작업의 식별자 |
| 게시 | 외부 게시 ID와 확인한 상태 | 같은 작업을 대조할 키와 승인된 입력 |
| 결과 기록 | 게시 결과와 연결된 기록 | 이미 확인한 게시 결과와 기록 대상 |
이 표를 만든 뒤에는 기록 단계 자체도 점검해야 한다. 매번 새 로그 행을 추가하는 방식이라면 기록을 재시도할 때 중복 행이 생길 수 있다. 게시를 멱등하게 만들었다고 뒤의 기록도 자동으로 멱등해지는 것은 아니다. 중복이 허용되는 시도 이력인지, 업무 하나당 하나여야 하는 완료 기록인지에 따라 저장 규칙을 달리 정해야 한다.
경계를 너무 많이 만들면 관리할 실행 이력과 상태가 늘어난다. 함께 다시 계산해도 문제가 없는 작은 변환은 묶을 수 있다. 반면 승인된 생성 결과, 비용이 큰 호출, 외부에 반영되는 쓰기는 복구 때 보존할 가치가 크다. Activity 개수보다 중요한 판단 기준은 한 부분의 실패가 어떤 완료 결과를 다시 사용하게 하고, 어떤 행동을 다시 일으키는가다.
장애를 넣는 위치로 재시도 설계를 검증한다
재시도 횟수만 설정해서는 복구 범위를 알 수 없다. 앞의 가상 업무라면 외부 게시 전에 실패하는 경우, 게시 직후 완료 보고 전에 실패하는 경우, 게시 완료 기록 뒤 결과 저장에서 실패하는 경우를 따로 시험해야 한다. 같은 오류 표시가 나더라도 각 경우에 다시 실행되어야 할 단계가 다르다. 이는 검증 시나리오 제안이며 실제 장애 실험을 수행한 결과는 아니다.
첫 경우에는 게시가 발생하지 않았다는 근거를 확인한다. 두 번째 경우에는 게시 Activity가 반복돼도 같은 공지가 중복되지 않는지와, 외부 결과를 다시 찾을 수 있는지를 본다. 세 번째 경우에는 게시가 다시 호출되지 않고 결과 기록만 이어지는지 확인한다. 마지막에는 Workflow가 성공으로 끝났다는 표시와 별도로, 승인된 공지가 의도한 위치에 존재하고 결과 기록이 그 게시를 가리키는지 대조한다.
시간과 비용의 상한도 각 실행 단위에 맞춰야 한다. Temporal의 Fixed Count of Retries 문서는 Python의 maximum_attempts=3이 최초 한 번과 재시도 두 번을 합친 총 세 번이라고 설명한다. 시도당 시간 제한을 함께 두고, 상한을 소진했을 때의 오류를 처리하도록 안내한다. 잘못된 입력처럼 반복해도 해결되지 않는 오류는 재시도 불가로 다룰 수 있다. 횟수 제한 패턴
같은 문서는 maximum_attempts=1로 재시도를 끄는 경우의 한계도 짚는다. 추가 호출은 막지만, 첫 외부 호출이 성공한 뒤 결과 기록만 유실됐다면 업무 상태는 여전히 불확실하다. 따라서 상한에 도달했다는 사실을 미실행으로 바꾸어 표시해서는 안 된다. 마지막 외부 상태와 남은 기록을 보존해 담당자가 이어받을 수 있어야 한다.
AI 자동화의 복구 설계는 실패한 코드를 다시 돌리는 기능에서 끝나지 않는다. 승인된 생성물을 지키고, 완료가 확인된 행동은 재사용하며, 확인하지 못한 외부 효과는 별도로 다루는 일이다. 실패를 넣어 볼 위치를 정하면 흐름도에서 보이지 않던 실행 경계가 드러난다. 그 경계가 업무의 실제 완료 단위와 맞을 때 비로소 실패한 단계부터 다시 시작할 수 있다.