SW/인공지능

AI Agent는 왜 프로덕션에서 자꾸 깨질까: Temporal Durable Execution 실전 기준

얇은생각 2026. 7. 18. 07:30
반응형

로컬에서 잘 돌던 AI Agent가 배포 후 깨지는 이유는 대개 모델 성능이 아니라 실행 흐름 때문입니다. API가 늦고, worker가 재시작되고, 10단계 중 6단계에서 죽었을 때 “어디서 이어갈지”를 시스템이 모르면 Agent는 데모를 벗어나기 어렵습니다. 이 글은 그 복구 기준을 잡기 위한 글입니다.

AI Agent를 처음 만들 때는 Python 스크립트 하나로도 충분해 보입니다. 루프를 돌리고, LLM을 호출하고, 필요한 tool을 붙이면 그럴듯하게 움직입니다. 하지만 실제 서비스에 올리는 순간 질문이 바뀝니다.

“답을 잘하느냐”보다 먼저 봐야 할 것은 이것입니다.

실패했을 때 이미 끝난 일을 다시 하지 않고, 마지막으로 안전한 지점부터 이어갈 수 있는가?

 

Temporal이 AI Agent 쪽에서 자주 언급되는 이유가 여기에 있습니다. Temporal은 새로운 Agent 프레임워크라기보다, 오래 걸리고 여러 단계로 나뉘는 작업을 실패 후에도 이어가게 만드는 durable execution 플랫폼에 가깝습니다.

 

AI Agent workflow continuing from a saved checkpoint after a worker failure, with completed steps preserved in an event-history timeline.

 

 

데모 Agent와 운영 Agent의 차이는 실패 지점에서 드러난다

로컬 데모에서는 이런 코드가 자연스럽습니다.

while not done:
    thought = llm(...)
    tool_result = call_tool(thought)
    update_state(tool_result)

 

짧은 테스트에서는 충분합니다. 문제는 이 코드가 “프로세스가 계속 살아 있고, 네트워크가 정상이고, tool call이 성공하고, 중복 요청이 없고, 배포 중 재시작도 없다”는 전제 위에 있다는 점입니다.

운영 환경에서는 그 전제가 금방 깨집니다.

  • LLM API가 timeout 난다
  • 외부 API가 rate limit에 걸린다
  • worker가 배포 중 재시작된다
  • 인증 토큰이 만료된다
  • 여러 tool call 중간에서 예외가 난다
  • 이미 이메일 발송, DB 저장, 결제 요청 같은 side effect가 일어난 뒤 다음 단계가 실패한다

 

여기서 단순 retry는 오히려 위험할 수 있습니다. 이미 끝난 일을 다시 실행할 수 있고, 중간 상태가 꼬일 수 있고, 실패 위치를 로그에서 추리해야 합니다. Agent 운영이 피곤해지는 이유는 모델 호출 한 줄이 아니라 그 주변의 retry, state, timeout, authorization, observability 코드가 계속 커지기 때문입니다.

이 문제는 Cloud Agent에서도 그대로 반복됩니다. 긴 작업을 클라우드에서 돌릴 때 왜 인프라가 병목이 되는지는 이전에 정리한 Cloud Agent가 로컬보다 느린 이유와 해결법과도 연결됩니다. Agent가 오래 일할수록 모델보다 실행 흐름을 버티게 하는 장치가 중요해집니다.

 

 

Temporal을 한 문장으로 이해하면 상태의 기준이 바뀐다

Temporal을 가장 단순하게 보면 이렇습니다.

workflow 상태를 worker 메모리에만 두지 않고 Temporal Service의 Event History에 기록해, worker가 죽어도 같은 흐름을 다시 이어가게 만드는 실행 구조입니다.

 

여기서 중요한 단어는 “retry”가 아니라 “Event History”입니다. Temporal은 workflow에서 이미 일어난 일을 기록하고, workflow code를 replay하면서 이전 상태를 재구성합니다. 메모리 snapshot을 통째로 되살리는 것이 아니라, 기록된 이벤트를 기준으로 같은 상태에 도달하는 방식입니다. 이 동작은 Temporal Workflow 공식 문서에서 확인할 수 있습니다.

AI Agent에 이 차이는 큽니다. 예를 들어 “사용자 질문 분석 → 필요한 tool 선택 → 외부 API 호출 → 결과 요약 → 사용자에게 전달” 같은 흐름에서 외부 API 호출 뒤에 worker가 죽었다고 가정해 보겠습니다.

상태 기준이 worker 메모리라면 어디까지 성공했는지 애플리케이션이 직접 복원해야 합니다. 상태 기준이 Temporal Event History라면 workflow는 이미 완료된 단계의 기록을 바탕으로 다음 지점부터 이어갈 수 있습니다.

이것이 durable execution의 실전 가치입니다. 실패를 없애는 것이 아니라, 실패해도 전체 일을 망가뜨리지 않게 만듭니다.

 

Diagram showing an AI Agent workflow controller separating external work into durable activity blocks and recording results in an event-history timeline.

 

Temporal 구조는 다섯 개만 먼저 보면 된다

Temporal 용어가 처음에는 많아 보이지만, AI Agent를 올릴 때는 아래 다섯 개부터 잡으면 됩니다.

  • Client: workflow 실행을 요청합니다. 사용자 요청을 Agent 작업으로 시작하는 쪽입니다.
  • Worker: workflow와 activity 코드를 실행합니다. 실제 Python 코드가 도는 프로세스입니다.
  • Temporal Service: workflow 상태와 event history를 보관합니다. worker가 죽어도 기준이 되는 쪽입니다.
  • Workflow: 전체 업무 흐름입니다. “질문 분석 → tool 선택 → 호출 → 정리” 같은 순서를 잡습니다.
  • Activity: 외부 세계와 닿는 작업입니다. LLM 호출, 검색 API, DB 작업, 파일 I/O, 이메일 발송 같은 단위입니다.

 

이 중에서 가장 중요한 구분은 Workflow와 Activity입니다.

Workflow는 순서를 정합니다. 어떤 결과를 보고 다음 단계로 넘어갈지 결정합니다. 반면 Activity는 실제로 외부 시스템을 건드립니다. Temporal에서 Activity는 재시도, timeout, heartbeat 같은 운영 정책을 붙일 수 있는 실행 단위입니다. 개념 자체는 Temporal Activity 문서를 함께 보면 이해가 빠릅니다.

AI Agent에서는 보통 이렇게 나눕니다.

  • 판단과 순서: Workflow
  • LLM 호출: Activity
  • tool/API 호출: Activity
  • DB write, 파일 I/O, 이메일, 결제: Activity
  • 단순 문자열 정리나 내부 분기: Workflow 안에서 처리 가능

 

이 구분을 놓치면 Temporal을 써도 장점이 줄어듭니다. 특히 LLM 호출을 Workflow 안에서 직접 해버리면 replay 때 다른 응답이 나와 workflow 결정이 달라질 수 있습니다. Workflow는 같은 history에 대해 같은 결정을 내려야 하므로 deterministic해야 합니다. 외부 세계와 닿는 작업은 Activity로 빼는 편이 안전합니다.

 

 

Activity 경계는 “장애 때 보고 싶은 단위”로 잡는다

Activity를 너무 크게 잡으면 복구가 둔해집니다. “여행 계획 만들기” 전체를 하나의 Activity로 만들면 호텔 검색에서 실패했을 때 앞의 항공권 검색까지 다시 생각해야 할 수 있습니다.

반대로 Activity를 너무 작게 쪼개면 workflow가 지저분해지고 event history도 불필요하게 길어집니다. 모든 문자열 변환이나 작은 if문까지 Activity로 만들 필요는 없습니다.

 

실무에서는 아래 기준이 가장 유용합니다.

질문 Activity로 빼는 쪽이 유리한 경우
외부 시스템을 호출하는가? LLM, 검색 API, 결제, 이메일, DB, 파일 I/O
다시 실행되면 위험한가? idempotency key나 중복 처리 방어가 필요
오래 걸리는가? timeout, heartbeat, retry 정책을 따로 잡을 가치가 있음
결과를 replay 때 재사용해야 하는가? LLM 응답, tool 결과, 외부 API 응답
장애 때 따로 보고 싶은가? 단계별 latency와 실패 위치를 UI에서 확인해야 하는 작업

 

한 줄로 줄이면 이렇습니다.

운영 중 장애가 났을 때 “이 단계가 문제였다”고 보고 싶은 단위라면 Activity 후보입니다.

 

Temporal UI에서 workflow timeline, activity duration, input/output을 보는 이유도 여기에 있습니다. Agent가 실패했을 때 “LLM이 이상했다”로 끝내면 해결이 안 됩니다. 실제로는 검색 API가 느렸는지, 권한이 깨졌는지, 특정 tool argument가 잘못됐는지를 알아야 합니다.

 

 

Temporal이 필요한 순간과 아직 과한 순간

Temporal은 모든 Agent에 필요한 도구는 아닙니다. 한 번 질문하고 바로 답하는 챗봇, 실패하면 사용자가 다시 실행해도 되는 내부 스크립트, side effect가 거의 없는 짧은 작업이라면 queue와 DB 상태 테이블만으로도 충분할 수 있습니다.

하지만 아래 신호가 보이면 durable execution을 검토할 때입니다.

  • 작업이 몇 초가 아니라 몇 분 이상 걸린다
  • 여러 tool/API를 순서대로 호출한다
  • 이미 완료한 단계를 다시 실행하면 비용이나 부작용이 크다
  • 사용자가 나중에 결과를 확인하는 비동기 작업이다
  • 배포, 장애, worker 재시작 후에도 작업이 이어져야 한다
  • retry와 상태 복구 코드가 비즈니스 코드보다 커지고 있다
  • 실패 위치와 단계별 실행 시간을 UI에서 추적해야 한다

 

반대로 요청 하나가 짧고, 실패해도 처음부터 다시 실행해도 되고, 외부 side effect가 거의 없다면 Temporal은 아직 과할 수 있습니다. 도입 기준은 유행이 아니라 실패 비용입니다.

이미 Python Agent를 웹 환경에 올리는 단계까지 갔다면 다음 병목은 대개 “배포는 됐는데 오래 안정적으로 돌릴 수 있는가”입니다. 배포 자체의 출발점은 Python AI Agent를 FastAPI + Vercel로 배포하는 방법에서 다룬 흐름과 이어서 보면 좋습니다.

 

 

도입할 때 자주 틀리는 지점

Temporal을 붙였다고 자동으로 좋은 Agent 아키텍처가 되는 것은 아닙니다. 오히려 처음에는 아래 지점에서 많이 틀립니다.

 

1. Workflow 안에서 외부 호출을 직접 한다

Workflow는 replay될 수 있고, 같은 history에 대해 같은 결정을 내려야 합니다. 그런데 그 안에서 직접 LLM을 호출하거나 현재 시간을 읽거나 random 값을 만들면 replay 때 다른 결과가 나올 수 있습니다.

LLM 호출, 검색 API, DB 접근, 파일 I/O는 Activity로 빼는 것이 기본입니다. Workflow는 “무엇을 언제 호출할지”를 정하고, Activity가 “외부 작업”을 맡습니다.

 

2. Activity를 idempotent하게 만들지 않는다

Activity는 실패 후 재시도될 수 있습니다. 그래서 같은 Activity가 다시 실행돼도 결과가 망가지지 않게 만들어야 합니다.

결제, 이메일 발송, DB write는 특히 조심해야 합니다. 요청마다 idempotency key를 쓰거나, 이미 처리된 작업인지 확인하는 저장소가 필요합니다. Temporal이 retry를 해줘도 side effect의 안전성은 애플리케이션 설계에 달려 있습니다.

 

3. 관측 단위를 너무 크게 잡는다

“Agent 실행” 하나로만 로그가 남으면 장애 때 할 수 있는 일이 별로 없습니다. 어느 Activity가 얼마나 걸렸는지, 어떤 input으로 실행됐는지, 어떤 단계에서 멈췄는지를 봐야 합니다.

Agent는 특히 결과가 그럴듯해 보여도 내부에서 어떤 tool이 어떤 근거로 호출됐는지 추적하기 어렵습니다. 최소한 tool call 단위의 timeline은 남겨야 디버깅이 가능합니다.

 

4. 기존 Agent를 한 번에 다 옮긴다

처음부터 전체 multi-agent 구조를 Temporal workflow로 바꾸면 복잡도만 커질 수 있습니다. 먼저 실패 비용이 큰 경계부터 옮기는 편이 낫습니다.

현실적인 순서는 이렇습니다.

  1. 사용자 요청 하나를 workflow execution 하나로 모델링한다.
  2. LLM 호출과 외부 tool call을 Activity로 분리한다.
  3. Activity별 timeout, retry, idempotency 기준을 정한다.
  4. Temporal UI에서 실패 위치와 latency를 확인한다.
  5. 오래 걸리는 작업에 heartbeat나 checkpoint가 필요한지 본다.

 

 

작은 Agent 하나로 먼저 검증해 보는 방법

처음부터 복잡한 시스템을 만들 필요는 없습니다. 오히려 실패가 눈에 보이는 작은 workflow가 좋습니다.

예를 들어 다음 정도면 충분합니다.

  • 사용자 질문을 받는다
  • LLM이 필요한 tool을 고른다
  • 외부 API를 호출한다
  • 결과를 요약한다
  • 중간 실패 시 같은 workflow에서 이어간다

 

이 workflow에 일부러 timeout이나 예외를 넣어 보면 Temporal의 장점이 빨리 보입니다. workflow execution이 생성되고, 어떤 Activity가 실행됐고, 어디서 멈췄고, 어떤 input/output이 있었는지 확인할 수 있습니다.

Temporal의 AI 관련 예제는 Temporal AI Cookbook에서 출발할 수 있습니다. 다만 예제를 따라 할 때 목표는 “코드가 돌아간다”가 아니라 “실패했을 때 어디서 이어지는지 이해한다”여야 합니다.

 

 

결론: Agent 운영의 질문을 바꿔야 한다

AI Agent를 만들 때는 “어떤 모델을 쓸까”, “어떤 프레임워크를 붙일까”가 먼저 떠오릅니다. 하지만 프로덕션에서는 더 먼저 물어야 할 질문이 있습니다.

이 Agent는 실패했을 때 어디서 다시 시작할 수 있는가?

그 답이 “처음부터 다시”라면 아직 데모에 가까운 구조일 가능성이 큽니다. 그 답이 “마지막으로 성공한 Activity 이후”라면 운영 가능한 구조에 가까워집니다.

Temporal은 모든 AI Agent의 정답은 아닙니다. 하지만 장기 실행, 다단계 tool call, 외부 side effect, 재시작 후 복구가 필요한 Agent라면 durable execution을 피하기 어렵습니다. 결국 AI Agent의 품질은 모델 호출 한 줄이 아니라, 실패해도 끝까지 일을 이어가는 실행 구조에서 갈립니다.

 

 

FAQ

 

Temporal을 쓰면 LangChain이나 LangGraph가 필요 없어지나요?

아닙니다. 역할이 다릅니다. LangChain이나 LangGraph가 Agent의 판단 흐름과 tool 사용을 구성한다면, Temporal은 그 실행 흐름이 실패 후에도 이어지도록 관리하는 쪽에 가깝습니다.

 

작은 개인 프로젝트에도 Temporal을 써야 하나요?

실패해도 처음부터 다시 실행해도 되는 프로젝트라면 필요하지 않을 수 있습니다. 작업이 오래 걸리거나, 외부 API 호출이 많거나, 이미 끝난 단계를 다시 실행하면 부작용이 큰 경우부터 검토하면 됩니다.

반응형