페이지 새로고침 후에도 AI 비디오 작업 상태 유지하기
요약
AI 비디오 생성 앱 EaseGen을 예시로, 페이지 새로고침 후에도 AI 작업의 상태를 유지하고 재개하는 방법을 설명합니다. 단순히 프롬프트만으로는 부족하며, 히스토리 레코드 ID, 태스크 ID 등 충분한 복구 데이터를 저장하여 백엔드에서 작업을 식별해야 합니다.
핵심 포인트
- 작업 재개를 위해 히스토리 ID와 태스크 ID 같은 상세 정보를 저장해야 함.
- 새로운 기록을 불러올 때 기존의 보류 중인 작업은 명시적으로 성공/실패 보고가 없으면 유지되어야 함 (조정 규칙).
- 로컬 카드와 서버 기록 간의 불일치를 작업 ID를 기준으로 조정하는 것이 중요함.
- 작업 설명자(task descriptors)를 별도의 맵에 저장하여 최신 히스토리 페이지에서 벗어난 작업도 추적해야 함.
사용자가 페이지를 새로고침해도 AI 비디오 작업은 계속 실행될 수 있습니다. 브라우저는 컴포넌트 상태를 잃지만, 생성 서비스는 여전히 처리해야 할 작업을 가지고 있습니다. 페이지가 다시 로드되면 UI는 해당 작업을 찾아 상태 확인을 재개하고, 궁극적으로 보류 중인 카드를 결과 또는 유용한 오류로 대체해야 합니다.
이 글에서는 AI 이미지 및 비디오 생성 앱인 EaseGen을 예시로 사용합니다. 이 내용은 EaseGen을 대표하여 게시되었습니다. 기사 초안 작성에는 AI가 사용되었으며, 기술적 세부 사항은 프로젝트의 현재 구현과 대조하여 확인했습니다. 아래 코드는 전체 애플리케이션 복원 로직의 축소된 예시입니다.
작업을 재개하기에 충분한 정보 저장하기
프롬프트와 모델 이름만으로는 사용자가 요청한 내용을 설명하기에 충분합니다. 하지만 실행 중인 작업에 다시 연결하기에는 충분하지 않습니다.
EaseGen의 비디오 인터페이스는 계정 기록에서 보류 중인 시도를 복원합니다. 복구 데이터에는 히스토리 레코드 ID, 생성 태스크 ID, 제공업체 라우팅 값, 그리고 서버가 반환하는 크레딧 예약 메타데이터가 포함됩니다. 재개된 상태 요청은 이 태스크 ID와 관련 필드들을 애플리케이션 백엔드로 전달합니다.
이러한 필드들은 각기 다른 역할을 합니다. 히스토리 ID는 카드를 식별합니다. 태스크 ID는 실행 중인 생성을 식별합니다. 라우팅 값은 백엔드가 올바른 서비스를 쿼리할 수 있게 해줍니다. 크레딧 예약 메타데이터는 백엔드가 터미널 실패를 원래의 예약과 연결할 수 있게 합니다.
서버는 여전히 로그인한 사용자가 해당 작업에 접근할 권한이 있는지 검증해야 합니다. 태스크 ID나 클라이언트가 제공하는 크레딧 값은 인증(authorization)이 아니며, 브라우저가 환불 여부를 결정해서는 안 됩니다.
시작 시간 또한 영구적인 기록에 포함되어야 합니다. 복원된 카드는 컴포넌트가 마운트될 때 타이머를 재설정하는 대신 원래 시도부터 경과 시간을 계산해야 합니다.
최근 기록 응답은 부분적인 보기입니다
비디오 인터페이스는 최신 20개의 기록을 요청합니다. 이는 최근 활동을 렌더링하는 데 유용하지만, 모든 이전 작업이 여전히 존재하는지 여부는 알 수 없습니다.
브라우저가 작업 A를 추적하고 있고 새로운 응답에 작업 B부터 U까지 포함되어 있다고 가정해 봅시다. A가 부재하기 때문에 이를 제거하면 실행 중인 생성 작업이 사라질 수 있습니다. 또한 로컬 업로드도 아직 서버 기록이 되지 않았기 때문에 누락될 수 있습니다.
조정(reconciliation) 규칙은 다음과 같습니다:
- 일치하는 기록이 명시적으로 성공 또는 실패를 보고하지 않는 한, 기존의 보류 중인 항목은 유지합니다.
- 알려진 히스토리 ID나 작업 ID를 중복하지 않고, 히스토리에서 복구된 보류 중인 항목을 추가합니다.
다음은 간단한 JavaScript 구현 예시입니다. 이 예시에서는 로컬 및 서버 항목 모두 미완료 작업을 위해 pending을 사용하며, 애플리케이션은 이를 다른 UI 상태에 매핑할 수 있습니다.
function reconcilePending(previous, snapshot) {
const terminal = snapshot.filter(
item => item.status === 'succeeded' || item.status === 'failed'
...
임시 로컬 카드와 영구 히스토리 기록의 레코드 ID가 다를 때 작업 ID로 일치시키는 것이 중요합니다. 또한 레코드 ID로 일치시키는 것은 아직 작업 ID를 가지고 있지 않은 항목도 포함합니다.
카드를 유지하는 것만으로는 복구가 절반에 불과합니다. EaseGen은 또한 작업 ID를 키로 하는 맵에 복구된 작업 설명자(task descriptors)를 보관합니다. 만약 작업이 최신 히스토리 페이지에서 벗어나더라도, 이 맵은 다음 상태 확인에 필요한 정보를 계속 제공합니다. 명시적인 최종 기록(terminal records)은 이를 맵에서 제거합니다.
컴포넌트마다 작업을 위한 폴링 소유자 지정하기
새로 제출된 작업은 이미 상태 루프를 가질 수 있습니다. 히스토리 새로고침은 원래 루프가 여전히 실행 중인 동안 동일한 작업을 발견할 수 있습니다.
복구된 작업을 쿼리하기 전에, 비디오 인터페이스는 로컬 제출 흐름에 의해 이미 처리된 작업 ID 세트를 확인합니다. 만약 해당 ID가 존재하면, 복구 흐름은 이를 해당 루프에 맡깁니다. 별도의 인플라이트 가드(in-flight guard)는 타이머와 포커스 이벤트가 근접하게 발생할 때 중복되는 히스토리 새로고침을 방지합니다.
해당 가드(guard)는 현재 컴포넌트 인스턴스 내에서만 적용됩니다. 모든 브라우저 탭을 조정하지 않으며, 정확히 한 번의 생성(exactly-once generation)을 보장하지도 않습니다. 백엔드 작업 접근 확인 및 이상치 금융 작업(idempotent financial operations)은 여전히 별도의 보호가 필요합니다.
포커스 시 재개, 네트워크 오류 시 불확실성 유지하기
EaseGen은 창에 포커스가 오거나 문서의 가시성이 변경될 때 비디오 히스토리를 새로고침합니다. 복구 루프는 문서가 숨겨져 있을 때는 히스토리 쿼리 시작을 방지합니다. 언마운트(unmount) 시에는 이벤트 리스너를 제거하고, 재시도 타이머를 지우며, 해당 컴포넌트에 결과를 적용하는 것을 중단합니다.
상태 요청 실패가 반드시 생성 실패를 의미하지는 않습니다. 연결이 끊긴 브라우저는 그 결과를 알 수 없습니다. 복구 흐름은 마지막으로 알려진 보류 상태(pending state)를 유지하고 나중에 재시도합니다.
백엔드가 명시적으로 실패를 보고하면, 인터페이스는 보류 항목을 제거하고 반환된 실패 이유를 표시합니다. 성공을 보고하면, 흐름은 출력 미디어(output media)를 영속화하고 완료된 히스토리 기록을 조정합니다.
상태 확인이 시간 초과되었다고 해서 자동으로 생성을 재제출해서는 안 됩니다. 원래 작업이 여전히 완료될 수 있으며, 새로운 제출은 또 다른 청구와 함께 또 다른 작업을 생성할 수 있습니다.
경쟁하는 작업 및 불완전한 스냅샷 테스트하기
유용한 확인 사항은 단일 성공적인 새로고침을 넘어섭니다:
| 시나리오 | 예상 동작 |
|---|---|
| 새로고침 후 히스토리에 보류 작업이 나타남 | 해당 카드를 복원하고 저장된 필드로 상태 확인을 재개합니다. |
| ... | |
| 하나의 경계가 남아 있습니다: 이 복구 접근 방식은 작업 식별자(task identifier)를 영속화하는 것에 의존합니다. 만약 생성 서비스가 생성 요청(create request)을 수락하지만, 그 식별자가 기록되기 전에 응답이 손실되면, UI만 새로고침하는 것만으로는 모호성을 해결할 수 없습니다. 그러기 위해서는 백엔드 요청 식별자와 승인된 작업을 조회할 방법이 필요합니다. 맹목적으로 재시도하는 것은 안전하지 않습니다. |
비동기 생성 인터페이스의 경우, 히스토리 피드는 복구 계약(recovery contract)의 일부입니다. 이 응답은 최종 결과(terminal outcome)와 미완성된 뷰를 구별해야 하며, 클라이언트는 해당 뷰 밖에 떨어진 작업들을 계속 확인하기에 충분한 정보를 유지해야 합니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기