Field Log · Entry
OpenAI SDK vs Temporal vs LangGraph — LLM 에이전트 백엔드 비교 2026
OpenAI Agents SDK는 agent loop와 도구 호출을, LangGraph는 상태와 분기·checkpoint를, Temporal은 durable workflow와 Activity 실행을 설계하는 데 사용합니다. 역할은 겹치는 부분도 있습니다. 셋을 모두 넣는 것이 정답이 아니라, 어디까지 복구해야 하고 어떤 부작용의 중복을 막아야 하는지부터 정해야 합니다.
이 글은 2026-09-08에 공식 문서를 대조한 아키텍처 가이드입니다. 아래 비교는 같은 workload로 측정한 benchmark가 아니며, Temporal 예제는 2026-08-14 갱신된 공식 OpenAI Agents SDK 통합 recipe의 구조를 따릅니다. API key·Temporal Service를 사용하는 전체 통합 실행은 이 블로그의 로컬 예제 테스트 범위에 포함하지 않습니다.
먼저 결정할 질문: 어디서 다시 시작해야 하나
한 번의 LLM 요청이 실패하는 것과, 결제·승인·검색·알림으로 이어지는 업무가 중간에 멈추는 것은 다른 복구 문제입니다.
| 질문 | 확인할 경계 |
|---|---|
| LLM HTTP 요청이 429/5xx로 실패했나 | provider SDK/transport retry·전체 deadline |
| agent가 너무 많은 turn을 사용했나 | max turns·token/cost·tool call budget |
| process 재시작 뒤 대화를 이어야 하나 | session 저장소와 실행 상태 복원 |
| 일부 분기만 재실행해야 하나 | graph checkpoint/task 결과 저장 |
| 외부 승인 뒤 며칠 후 이어야 하나 | durable workflow·timer·signal·운영 service |
| 도구가 성공했지만 결과 저장 전에 죽었나 | idempotency key·결과 확인·중복 부작용 방지 |
이 표는 특정 제품 하나가 나머지를 모두 해결한다는 뜻이 아닙니다. 예를 들어 retry가 있어도 중복 결제를 막으려면 결제 시스템과 application이 같은 idempotency 계약을 지켜야 합니다.
SDK·graph·workflow의 책임
상태 저장과 운영 복구의 조건을 함께 비교해야 합니다. 같은 “durable”이라는 표현도 저장소·체크포인트·실행 단위에 따라 적용 범위가 달라집니다.
| 도구/층 | 잘 표현하는 것 | 별도로 설계할 것 |
|---|---|---|
| OpenAI Agents SDK | agent instructions·tools·handoff·실행 loop | session/실행 상태 저장 선택, 비용 budget, 외부 부작용 |
| LangGraph | state graph·분기·checkpoint와 이어가기 | durable checkpointer, thread ID, 재실행할 task 경계 |
| Temporal | workflow history·Activity·timer·signal과 복구 | 결정적인 workflow, Activity 멱등성, Service/worker 운영 |
| FastAPI | HTTP 요청과 응답 | 요청 수명 밖의 작업 상태 |
| RabbitMQ | 메시지 전달과 소비 | 업무 상태·단계별 보상/재실행 정책 |
LangGraph와 Temporal을 함께 쓰는 구성은 하나의 선택지입니다. 단일 application에서 graph persistence로 요구사항을 만족한다면 workflow service를 추가하지 않아도 됩니다.
OpenAI Agents SDK 예제에서 생략된 책임
OpenAI의 Agents SDK 안내는 agent 구성을 위한 진입점입니다. Python의 실행은 Agent 인스턴스 메서드가 아니라 Runner.run(agent, input)을 사용합니다.
from agents import Agent, Runner, function_tool
@function_tool
def search_docs(query: str) -> str:
"""Return a synthetic example, not a company manual."""
return "[DEMO] Pump A: inspect according to the approved local procedure."
agent = Agent(
name="demo-docs-agent",
instructions="Use only the supplied demo evidence; say when it is insufficient.",
tools=[search_docs],
)
# Run inside an async function or an async-capable notebook.
result = await Runner.run(agent, "What is the demo pump instruction?", max_turns=4)
print(result.final_output)
이 코드는 API를 호출하며 비용이 발생할 수 있습니다. model·provider 설정과 설치한 SDK version을 고정해야 합니다. 검색 함수는 합성 고정 응답이며 실제 RAG의 권한·retrieval 품질을 구현하지 않습니다.
SDK에 retry, session, tracing 관련 기능이 있다는 것과 애플리케이션 전체가 재시작을 견딘다는 것은 별개입니다. “429면 항상 즉시 중단한다”, “session은 모두 메모리에만 있다”, “감사가 불가능하다”처럼 일반화하지 않습니다. 선택한 SDK/provider의 자동 retry와 application retry가 중첩되는지, session backend가 무엇인지 확인합니다.
한계 점검은 다음처럼 구체화할 수 있습니다.
- 완료된 tool 결과와 아직 진행 중인 실행 상태 중 무엇을 저장하는가?
- 전체 deadline 안에 SDK의 retry 대기 시간도 포함되는가?
- turn 제한에 닿기 전 token/cost·도구 부작용 budget을 검사하는가?
- 승인 대기 중 배포하거나 process를 재시작하면 어떻게 복원하는가?
Temporal은 기록된 workflow를 재생한다
Temporal은 workflow 진행 상태를 Event History로 보존합니다. Worker가 재시작하면 결정적인 workflow 코드를 replay하며 이미 기록된 결과를 사용합니다. 중단된 모든 외부 연산이 실행 도중의 CPU 지점에서 이어지는 것은 아닙니다.
네트워크·DB·LLM 호출 같은 외부 작업은 Activity나 통합 adapter의 경계로 보냅니다. Activity 수행 중 성공 결과가 history에 기록되기 전에 장애가 나면 재시도될 수 있습니다. 따라서 Activity의 외부 쓰기는 멱등하거나 결과를 조회해 중복 여부를 판별할 수 있어야 합니다. Temporal Activity 정의
시간 제한과 retry policy도 명시해야 합니다. Temporal을 넣는 것만으로 무한 retry, 비용 폭주, 외부 시스템 오류가 사라지지는 않습니다. 긴 history는 실행 한도와 Continue-As-New 전략으로 관리합니다.
공식 통합의 핵심: Runner와 Activity tool
다음은 파일 경계를 보여 주는 설계 발췌입니다. 설치와 고정 dependency, 완전한 실행 구성은 공식 recipe와 연결된 예제 repository를 기준으로 합니다.
# activities.py
from temporalio import activity
@activity.defn
async def search_docs_activity(query: str) -> str:
return "[DEMO] No production document is accessed by this example."
# workflows.py
from datetime import timedelta
from agents import Agent, Runner
from temporalio import workflow
from temporalio.contrib import openai_agents
from activities import search_docs_activity
@workflow.defn
class RagAgentWorkflow:
@workflow.run
async def run(self, question: str) -> str:
agent = Agent(
name="demo-rag-agent",
instructions="Use demo evidence and state its limitations.",
tools=[openai_agents.workflow.activity_as_tool(
search_docs_activity,
start_to_close_timeout=timedelta(seconds=10),
)],
)
result = await Runner.run(agent, question, max_turns=4)
return result.final_output
현재 recipe의 helper 위치는 openai_agents.workflow.activity_as_tool입니다. Agent.run()이나 상위 패키지의 임의 helper import로 대체하지 않습니다. SDK API가 바뀌면 recipe의 revision과 lockfile을 함께 갱신합니다.
# worker.py: async main() body
from datetime import timedelta
from temporalio.client import Client
from temporalio.contrib.openai_agents import (
ModelActivityParameters, OpenAIAgentsPlugin,
)
from temporalio.worker import Worker
from activities import search_docs_activity
from workflows import RagAgentWorkflow
client = await Client.connect(
"localhost:7233",
plugins=[OpenAIAgentsPlugin(model_params=ModelActivityParameters(
start_to_close_timeout=timedelta(seconds=30),
))],
)
worker = Worker(
client,
task_queue="demo-rag-agent",
workflows=[RagAgentWorkflow],
activities=[search_docs_activity],
)
await worker.run()
이 코드만 실행하면 worker가 대기합니다. 동일 plugin 설정의 starter client에서 execute_workflow(RagAgentWorkflow.run, question, id=..., task_queue="demo-rag-agent")로 요청해야 합니다. API 자격 증명, task queue, workflow ID의 충돌 정책은 환경에 맞춰 설정합니다. 여기에 실제 검색을 붙이면 tenant/ACL·timeout·idempotency를 별도로 구현해야 합니다.
LangGraph의 복구도 설정한 저장 경계에 달려 있다
LangGraph persistence 문서는 checkpointer·thread·checkpoint를 통한 상태 보존을 설명합니다. “메모리 안의 graph”와 durable 저장소에 연결한 graph를 같은 조건으로 비교하면 안 됩니다.
중단 뒤 재실행할 수 있는 코드에는 외부 부작용과 비결정적 작업을 적절한 task 경계로 분리합니다. 큰 node 전체를 하나의 재실행 단위로 두면 그만큼 다시 하는 작업이 커집니다. 이는 큰 Temporal Activity도 마찬가지입니다.
| 장애 지점 | 확인할 사항 |
|---|---|
| LangGraph node/task 수행 중 | 마지막 persisted checkpoint/result, task 분리, 외부 부작용의 멱등성 |
| Temporal Activity 수행 중 | 완료 event 기록 여부, retry/timeout, 외부 부작용의 멱등성 |
| 승인 대기 중 process 종료 | durable 저장소, thread/workflow ID, 복귀 API와 운영 service |
Temporal Activity 안에서 LangGraph를 실행하는 방법도 있습니다. 이때 Activity 재시도가 graph 전체를 다시 시작하는지, 같은 thread/checkpointer로 이어가는지 명시해야 합니다. “Temporal 바깥/LangGraph 안”이라는 그림만으로 두 persistence 계층이 자동 연동되지는 않습니다.
무엇을 먼저 선택할까
필요한 복구 단위부터 선택하고 구성 수를 늘립니다. 아래는 제품 기능 체크리스트가 아니라 설계 출발점입니다.
| 상황 | 시작점 | 확인할 완료 조건 |
|---|---|---|
| 짧은 단발 agent 호출 | SDK와 application budget | timeout·실패·취소를 구분 |
| 상태 분기와 사람 검토가 복잡 | LangGraph + 필요한 persistence | 동일 thread에서 checkpoint 복구 |
| 여러 서비스·긴 timer·승인 workflow | Temporal 검토 | worker 종료 뒤 재개·Activity 중복 방지 |
| 기존 queue/DB로 요구를 만족 | 현재 구성 유지 | 업무 상태와 retry 경계를 설명 가능 |
| 비용 폭주가 걱정 | 모든 구성에서 별도 budget | turn·token·시간·호출 수 제한 |
팀 규모나 “1~2분” 같은 시간은 보편 임계값이 아닙니다. 작은 서비스도 외부 부작용이 중요하면 강한 복구가 필요하고, 긴 read-only 분석도 실패 후 재실행을 허용할 수 있습니다.
운영 비용과 경험의 범위
2026-09-08 Temporal 가격 페이지는 Cloud Essentials 월 100 USD부터, Business 월 500 USD부터를 표시합니다. 사용량·지원 비율·추가 기능에 따라 총액이 달라집니다. Self-hosted는 운영 인력·저장소·장애 대응 비용이 남습니다. 가격을 도입의 유일한 기준으로 삼거나 고정 원화 환산을 사용하지 않습니다.
사내 RAG를 생각할 때 제 관심은 “어느 framework가 더 고급인가”보다 실패한 단계와 중복 실행의 영향을 설명할 수 있는가에 있습니다. 이 글은 동일 환경에서 세 제품의 복구율을 실측한 보고서는 아닙니다. 실제 선택 전에 정상 종료, tool 성공 직후 process 중단, checkpoint 이후 재개를 staging에서 재현해야 합니다.
자주 묻는 질문
Temporal을 넣으면 비용 폭주가 막히나요? 아닙니다. workflow retry와 agent budget은 별도입니다. API 호출·turn·token·시간 예산을 application에서 정해야 합니다.
LangGraph만으로는 운영할 수 없나요? 요구사항과 checkpointer·실행 환경을 갖추면 운영할 수 있습니다. Temporal 도입 여부는 복구 경계와 외부 서비스 orchestration 필요로 판단합니다.
SDK session과 Temporal history는 같은가요? 대화 기록과 업무 실행 이력은 다른 자료입니다. 선택한 session backend와 workflow state의 연결·보존·삭제 정책을 확인해야 합니다.
실행 예제에서 가장 먼저 확인할 것은? 공식 recipe의 dependency revision, Runner.run, Activity tool helper 경로, task queue와 worker 등록입니다. 이후 실패 시나리오를 재현하고 실제 서비스 호출을 연결합니다.
참고자료
Reader questions
읽으며 남긴 질문
글을 읽으며 붙잡아 둔 질문입니다. 다시 살펴보거나, 보내지 않은 질문을 한 번에 블로그 주인에게 전달할 수 있습니다.