5분이 충분하지 않을 때: AI 인제션을 Sync에서 Async로 전환 (그리고 99% Compute 절감)

발행: (2026년 2월 13일 오후 12:38 GMT+9)
6 분 소요
원문: Dev.to

Source: Dev.to

배경

이전 글에서 저는 Synapse라는 AI 시스템을 소개했습니다. 이 시스템은 제 아내를 위해 만든 것으로, 지식 그래프를 활용해 LLM에 “깊은 메모리”를 제공합니다. 초기 데모에서는 채팅이 끝난 후 약 50 초 안에 그래프가 업데이트되는 모습을 보여줬지만, 실제 사용에서는 근본적인 결함이 빠르게 드러났습니다.

문제점

수십 개의 메시지가 오가는 45분짜리 채팅 세션 동안 “End Session” 버튼이 몇 분씩 회전하고 결국 크래시되었습니다. 원인은 단순한 타임아웃 버그가 아니라 아키텍처 자체였습니다.

초기 동기식 구현

  1. Convex (Orchestrator) → 내 Python 백엔드에 HTTP POST를 트리거합니다.
  2. FastAPI (Brain) → Graphiti + Gemini를 호출해 텍스트를 처리합니다.
  3. FastAPI는 결과가 나올 때까지 기다렸다가 반환합니다.
  4. Convex는 결과를 데이터베이스에 저장합니다.

이는 전형적인 동기식 요청‑응답 패턴입니다.

실패 이유: Convex Actions에는 실행 제한 시간이 존재합니다(플랜에 따라 5–10 분). 짧은 대화는 1–2 분 안에 끝났지만, 큰 세션은 12–18 분이 소요되어 제한을 크게 초과했습니다.

연쇄적인 실패

  • Convex Actions에 지수 백오프 재시도를 추가했습니다.
  • 각 재시도마다 새로운 백그라운드 프로세스가 시작되고, 이전 프로세스는 계속 실행돼 토큰 사용량이 두 배가 되었으며 “좀비” 작업이 생겼습니다.
  • 사용자는 여전히 오류를 보았고, 백엔드는 과부하되었습니다.

진단

Axiom에 전송된 OpenTelemetry 트레이스는 ingestion 자체가 실패한 것이 아니라 단순히 느리게 진행되고 있음을 보여주었습니다. 큰 세션에서는 일관되게 12–18 분이 걸렸습니다.

비동기 폴링 아키텍처로 전환

클라이언트나 서버가 기다릴 수 있는 시간을 초과하는 작업은 요청과 응답을 분리해야 합니다.

새로운 흐름

  1. ConvexPOST /ingest를 보냅니다.
  2. FastAPI는 즉시 202 AcceptedjobId를 반환합니다(≈ 300 ms).
  3. FastAPI는 무거운 처리를 백그라운드 작업(asyncio.create_task)으로 시작합니다.
  4. Convex는 잠시 대기한 뒤 몇 분 간격으로 작업 상태를 폴링합니다.

폴링 전략

  • 지수 백오프에서 선형 백오프로 전환했습니다.
  • 스케줄: 5 분 후 확인, 그 다음 10 분 후, 이후 매 10 분마다 확인.
  • 불필요한 부하와 서버 잡음을 줄여줍니다.

리소스 사용량 비교

시나리오작업 시간총 청구 컴퓨트토큰 낭비
동기식5 분 (블로킹) → 타임아웃 → 재시도 (추가 5 분)~10–15 분높음 (중복 처리)
비동기 폴링트리거 ≈ 300 ms, 폴링 ≈ 300 ms, 최종 가져오기 ≈ 300 ms< 2 초최소

우리는 작업당 약 10 분 정도의 컴퓨트를 낭비하던 상황에서, 실제 실행 시간 2 초 이하로 줄였으며 중복 처리를 완전히 없앴습니다.

교훈

  • AI 작업은 본질적으로 느립니다. “빠른” LLM 호출이라도 30 초가 걸릴 수 있고, “깊은” 지식 그래프 업데이트는 15 분이 소요될 수 있습니다.
  • 타임아웃만 늘리지 마세요. 요청과 응답을 분리해 시스템을 회복력 있게 만들고 비용을 절감하세요.
  • 폴링에 선형 백오프를 적용하면 장기 실행 작업의 예상 소요 시간에 맞춰 서버 트래픽을 줄일 수 있습니다.

코드 저장소

비동기 요청‑응답 패턴 구현은 다음 저장소에서 확인할 수 있습니다:

피드백 요청

다른 분들은 장기 실행 LLM 작업을 어떻게 처리하고 계신지 궁금합니다. X 또는 LinkedIn을 통해 언제든지 연락 주세요.

0 조회
Back to Blog

관련 글

더 보기 »