사진 한 장으로 'Burning Bridges' 비디오 생성기 제작 과정
요약
본 글은 인물 사진 한 장으로 개인화된 'Burning Bridges' 비디오를 생성하는 웹 앱 제작 과정을 공유합니다. React, TanStack Start, Cloudflare Workers 등을 사용하여 프론트엔드와 백엔드를 구축했으며, 외부 비디오 생성 서비스를 연동하고 작업 상태 추적 및 크레딧 관리를 체계적으로 구현한 것이 핵심입니다.
핵심 포인트
- React/TanStack Start를 사용한 웹 앱 구조 설계
- Cloudflare Workers 기반의 서버리스 아키텍처 채택
- 외부 AI 서비스와의 비동기 작업 흐름(State Machine) 관리
- 데이터베이스 트랜잭션 및 크레딧 차감 로직 구현
저는 Drake Burning Bridges AI라는 작은 웹 앱을 만들었습니다. 이 앱은 인물 사진 한 장을 받아서 개인화된 버전의 'Burning Bridges' 파티 장면을 생성합니다.
사용자는 자신의 사진으로 메인 캐릭터를 선택할 수 있습니다. 저는 비디오 레퍼런스와 프롬프트를 설정해 두었기 때문에, 사용자가 직접 장면 지침을 작성할 필요가 없습니다. 결과물은 제공된 사운드트랙이 포함된 20초 분량의 720p 와이드스크린 MP4 파일입니다.
이번 포스팅에서는 이 짧은 업로드 플로우를 구현하는 과정에서 제가 내렸던 선택들을 공유하고 싶었습니다.
입력 최소화 유지하기
스튜디오는 인물 사진 한 장만 받습니다. 이 사진은 메인 피사체의 외모 레퍼런스를 제공하며, 비디오 레퍼런스는 파티 배경, 제스처, 카메라 움직임을 안내합니다.
저는 장면 및 출력 설정을 고정했습니다. 사용자는 전경에 누가 나타날지 선택할 수 있지만, 게스트를 임의로 지정하거나 지속 시간을 변경할 수는 없습니다. 이는 만들 수 있는 범위가 제한된다는 의미이며, 업로드 페이지에는 명확한 역할이 주어집니다: 사용자에게 사용할 만한 사진을 고르게 돕고 예상되는 결과물을 이해시키는 것입니다.
서버는 파일 크기, 이미지 유형 및 치수를 확인합니다. 단순히 파일 확장자나 브라우저가 제공하는 MIME 타입만으로는 업로드를 검증하기에 충분하지 않습니다.
사용 기술 스택 (The stack)
저는 앱에 React와 TanStack Start를 사용하고, 인증에는 Better Auth를 사용했습니다. 이 애플리케이션은 Cloudflare Workers에서 실행됩니다. 작업 및 크레딧 기록은 D1에 저장하며, 업로드된 사진과 완성된 비디오는 R2에 저장합니다.
이 앱은 외부 비디오 생성 서비스에 요청을 보냅니다. Workers가 직접 비디오 추론(inference)을 수행하기보다는 애플리케이션 흐름을 처리합니다.
생성을 저장된 작업으로 취급하기
비디오 요청은 사용자가 페이지를 떠나도 유지되어야 합니다. 저는 작업을 처리하기 전에 먼저 저장하고, 다음 상태들을 거치며 진행 상황을 추적합니다:
queued → processing → composing → saving → succeeded
구성(composition) 단계에서 제공된 사운드트랙이 추가됩니다. 저는 생성 제공업체가 처음 성공을 보고할 때가 아니라, 완성된 비디오를 저장한 후에 작업을 성공으로 표시합니다.
사용자는 '내 비디오(My videos)'로 돌아가 기존 작업을 확인할 수 있습니다. 브라우저를 전체 작업 시간 동안 열어둘 필요는 없습니다.
재시도 및 크레딧 처리
각 생성은 1개의 크레딧을 사용합니다. 저는 요청 ID를 사용하여 제출물과 해당 작업을 연결합니다. 동일한 사용자가 동일한 요청을 다시 보내면, 애플리케이션은 기존 작업을 반환합니다. 이 ID를 다른 입력값과 함께 재사용하는 것은 거부됩니다.
데이터베이스에서는 트리거(trigger)를 이용해 작업 생성과 크레딧 차감을 연결합니다. 만약 차감이 완료되지 못하면, 작업 삽입이 롤백(rollback)됩니다. 또한 실패한 작업에 대한 크레딧 반환에도 고유한 원장 참조 번호(ledger reference)를 부여하여, 동일한 실패 처리가 다시 이루어져도 추가적인 크레딧이 차감되는 것을 방지합니다.
덜 명확한 경우는 비디오 제공업체로 제출하는 도중에 발생하는 시간 초과(timeout)입니다. 제공업체는 제 애플리케이션이 응답을 받지 못했더라도 작업을 수락했을 수 있습니다. 이 시점에서 새로운 요청을 제출하면 두 번째 유료 생성이 발생할 수 있습니다.
저는 그 제출 시도를 기록하고, 조정(reconciliation)을 위해 불확실한 결과를 유지합니다. 확인된 실패는 크레딧을 반환하고, 응답 누락은 더 많은 조사가 필요합니다. 이로 인해 일부 경우는 지원팀 검토가 필요한 상황이 생기지만, 알 수 없는 결과를 재제출 권한으로 간주하는 것을 방지할 수 있습니다.
비디오에 대한 기대치 설정
AI는 사람이 움직일 때 얼굴 디테일이나 손을 변경할 수 있습니다. 작업 완료란 사용자가 비디오를 받았다는 의미이지, 모델이 모든 프레임에서 그들의 외모를 보존했다는 의미는 아닙니다.
방문자들이 의도된 장면을 확인할 수 있도록 예시(examples)를 포함했습니다. 이들은 앱을 통해 유료로 생성되었다는 증거가 아니라 480p 샘플입니다. 설정된 출력은 720p입니다.
이 사이트는 Drake와 아무런 관련이 없는 독립적인 프로젝트입니다. 사용자는 피사체의 동의를 얻어 사용할 권한이 있는 사진을 업로드해야 합니다.
프로젝트는 drakeburningbridgesai.video에서 확인할 수 있습니다. 업로드 흐름이나 작업당 비용을 부과하는 앱에서 불확실한 제공업체 응답을 처리하는 방법에 대한 피드백을 환영합니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기