
운영 환경의 AI 이미지 생성에서 비동기 처리가 필요한 이유
요약
AI 이미지 생성 서비스를 운영 환경에 적용할 때 발생하는 타임아웃, 중복 요청, 상태 관리 문제를 해결하기 위한 비동기 워크플로우 설계 방안을 다룹니다. 요청과 처리를 분리하고 상태 머신을 도입하여 시스템의 안정성과 멱등성을 확보하는 방법을 제안합니다.
핵심 포인트
- 단순 요청-응답 방식은 타임아웃 및 중복 생성 위험이 있음
- 사용자 요청과 실제 생성 처리를 분리하여 백그라운드에서 수행해야 함
- 상태 머신(created, queued, processing 등)을 통한 명확한 상태 관리 필요
- 멱등성을 유지하여 중복 콜백이나 재시도 시에도 시스템 안정성 확보
AI 이미지 생성은 언뜻 보면 단순한 요청-응답 (Request-Response) 기능처럼 보입니다.
사용자가 프롬프트 (Prompt)를 입력하고, 생성 버튼을 누른 뒤, 이미지가 돌아오기를 기다리는 방식입니다.
프로토타입이라면 이 형태만으로도 충분히 작동합니다. 하지만 운영 환경의 프로덕트 (Product)로 다루게 되면, 이 설계는 금방 취약해집니다.
이미지 생성에는 수 초에서 수 분이 걸릴 수 있습니다. 프로바이더 (Provider)에 따라서는 처음에 작업 ID (Job ID)만 반환하고, 최종 결과는 나중에 반환하기도 합니다. 결과가 Webhook으로 전달되는 경우도 있고, 직접 폴링 (Polling)을 해야 하는 경우도 있습니다. 요청이 실패하거나, 타임아웃 (Timeout)이 발생하거나, 사용자가 페이지를 떠난 후에 완료되기도 합니다.
따라서 AI 이미지 생성은 비동기 워크플로우 (Asynchronous Workflow)로 설계하는 것이 다루기 쉽습니다.
이 기사에서는 Image 2를 개발하면서 정리한, AI 이미지 생성을 비동기화하는 이유와 기본적인 설계를 정리합니다.
가장 직접적인 구현은 다음과 같은 형태입니다.
User -> API route -> AI provider -> result -> user
이해하기 쉬운 구성이지만, 몇 가지 문제가 있습니다.
- HTTP 요청이 타임아웃될 가능성이 있음
- 재시도 (Retry)에 의해 중복 작업이 생성될 가능성이 있음
- 프론트엔드 경험이 프로바이더의 응답 시간에 의존함
- 과금 및 크레딧 (Credit) 소비 보호가 어려워짐
- 생성된 이미지가 일시적인 프로바이더 URL에 의존함
- 요청 종료 후 실패 상태를 복구하기 어려움
이 형태는 데모에는 적합합니다. 하지만 실제 사용자, 결제, 스토리지 (Storage), 재시도가 관여되면 안정적으로 운용하기 어려워집니다.
더 견고하게 만들려면 사용자의 요청과 실제 생성 처리를 분리해야 합니다.
User request
|
v
...
사용자용 API는 생성 태스크 (Task)를 생성하고 즉시 반환합니다. UI 측에서는 queued, processing, completed, failed와 같은 상태를 표시합니다.
시간이 걸리는 처리는 백그라운드 (Background)에서 진행합니다.
비동기 워크플로우로 만들면 시스템이 실패로부터 회복하기 쉬워집니다.
프로바이더의 응답이 느린 경우, 태스크를 processing 상태로 유지할 수 있습니다.
프로바이더 측에서 실패한 경우, 태스크를 failed로 업데이트하고 필요하다면 크레딧을 되돌려줄 수 있습니다.
Webhook을 받지 못했더라도, 나중에 스케줄 작업 (Scheduled Job)으로 폴링할 수 있습니다.
Webhook과 폴링이 모두 동일한 최종 결과를 보았을 때라도, 중복된 확정 처리를 무시할 수 있습니다.
마지막 점은 운영 환경에서 매우 중요합니다. 동일한 생성 결과가 여러 번 관측될 수 있습니다. completed나 failed와 같은 종단 상태 (Terminal State)로의 업데이트는 멱등성 (Idempotency)을 유지해야 합니다.
처음부터 복잡한 상태 머신 (State Machine)을 만들 필요는 없습니다. 작은 모델로도 충분히 시작할 수 있습니다.
created -> queued -> processing -> completed
|
-> failed
각 상태는 명확한 의미를 갖도록 합니다.
created: 요청을 접수함
queued: 백그라운드 처리를 예약함processing: 프로바이더 측의 작업이 시작됨completed: 최종적인 이미지 에셋 (Asset)을 사용할 수 있게 됨failed: 태스크를 완료할 수 없음
중요한 것은 종단 상태를 보호하는 것입니다. 일단 completed 또는 failed가 된 태스크에 대해, 재시도나 중복 콜백 (Callback)이 동일한 결과를 재적용하지 않도록 합니다.
많은 AI 프로바이더는 생성된 이미지의 URL을 반환합니다. 하지만 그 URL은 일시적이거나 프로바이더 측의 관리 하에 있습니다.
운영 프로덕트에서는 최종 결과를 자신들의 스토리지에 복사하는 것이 다루기 쉽습니다.
Provider result URL -> app storage -> stable asset URL
Cloudflare를 사용하는 경우라면, 최종 이미지를 R2에 저장하고 자신들의 CDN 도메인을 통해 배포하는 구성을 생각할 수 있습니다.
이를 통해 다음과 같은 처리를 관리하기 쉬워집니다.
- 사용자 소유권 확인
- 다운로드
- 클린업 (Cleanup)
- 모더레이션 (Moderation)
- 안정적인 프리뷰 (Preview) URL
- 과금 이력과의 연결
AI 프로바이더 (AI Provider)는 이미지를 생성합니다. 반면, 이미지를 프로덕트 (Product) 내에서 어떻게 다룰지는 애플리케이션 (Application) 측에서 책임져야 할 영역입니다.
여러 모델 (Model)이나 생성 방식을 다루는 앱에서는 비동기 워크플로우 (Asynchronous Workflow)의 가치가 더욱 커집니다.
텍스트에서 이미지를 만드는 모델, 이미지 편집 모델, 참조 이미지를 사용하는 워크플로우는 각각 동작이 다릅니다. 즉시 결과를 반환하는 것도 있는가 하면, 프로바이더 측의 잡 ID (Job ID)가 필요한 것도 있습니다. 고해상도 출력을 지원하는 것도 있는가 하면, 입력 제한이 서로 다른 것도 있습니다.
이러한 차이점을 프론트엔드 (Frontend)에 직접 노출하면 UI와 상태 관리 (State Management)가 복잡해집니다.
반면, 백엔드 (Backend) 측에 공통의 태스크 라이프사이클 (Task Lifecycle)을 갖추어 두면, 사용자에게는 심플한 생성 경험을 제공하면서 프로바이더별 차이점을 내부로 격리할 수 있습니다.
이는 특정 프로바이더 API를 중심으로 설계하는 것이 아니라, 프로덕트의 워크플로우를 중심으로 설계한다는 사고방식입니다.
AI 이미지 생성은 단순한 모델 호출이 아닙니다. 프로덕트로서는 시간이 걸리는 잡 (Job), 중복 콜백 (Callback), 재시도 (Retry), 스토리지 (Storage), 모더레이션 (Moderation), 크레딧 처리 (Credit Processing)까지 포함된 워크플로우입니다.
실험 단계라면 동기적인 API 루트 (API Route)로도 충분합니다. 하지만 운영 환경 (Production)에서는 비동기 아키텍처 (Asynchronous Architecture)로 구성함으로써 느린 처리나 실패를 더욱 안정적으로 다룰 수 있습니다.
모델은 이미지를 만듭니다. 워크플로우는 프로덕트를 신뢰할 수 있게 만듭니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Qiita AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기