
TanStack Start × Cloudflare Workers로 상품 사진에서 이미지·동영상 광고를 생성하는 「Photo2Ads」를 만들다
요약
TanStack Start와 Cloudflare Workers를 활용하여 상품 사진 한 장으로 다양한 광고 소재를 생성하는 AI 워크스페이스 'Photo2Ads' 개발 사례를 소개합니다. 여러 생성 AI 모델을 하나의 UI에 통합하고 광고 제작 워크플로우를 효율적으로 관리하는 설계 방식을 다룹니다.
핵심 포인트
- TanStack Start와 Cloudflare 기반의 기술 스택 활용
- 다양한 이미지 및 동영상 생성 AI 모델의 통합 UI 설계
- 모델별 특성에 맞춘 가변적 설정 UI 구현
- 프롬프트와 참조 이미지를 재사용하는 워크플로우 최적화

상품 사진을 한 장 준비하는 것만으로 SNS 광고, EC 사이트용 배너, 세로형 동영상 광고 등을 한꺼번에 제작할 수 있는 AI 광고 스튜디오 「Photo2Ads」를 개발했습니다.
이 기사에서는 Photo2Ads를 만든 이유, 제품 전체의 설계, TanStack Start와 Cloudflare를 사용한 기술 구성, 여러 생성 AI (Generative AI) 모델을 하나의 UI에 통합할 때 고려한 점을 소개합니다.
Photo2Ads란
Photo2Ads는 상품 사진으로부터 이미지 광고와 동영상 광고를 만들기 위한 AI 광고 제작 워크스페이스입니다.
기본적인 흐름은 심플합니다.
상품 사진 업로드
↓
광고 목적 및 표현 방향 선택
...
이미지를 한 번 생성하고 끝내는 것이 아니라, 동일한 상품으로부터 여러 광고 포맷을 지속적으로 제작할 수 있다는 점을 중시하고 있습니다.
이미지 광고에서는 동일한 상품을 사용한 1~4종류의 크리에이티브를 생성할 수 있습니다. 정사각형, 세로형, 가로형 등 광고 매체에 맞춘 종횡비 (Aspect Ratio)도 선택할 수 있습니다.
동영상 광고에서는 상품 이미지나 인물 이미지를 참조하면서, 모델별로 동영상 시간, 해상도, 음성 유무 등을 설정할 수 있습니다.
왜 이 제품을 만들었는가
AI로 이미지나 동영상을 만들 수 있는 서비스는 이미 수없이 존재합니다.
하지만 실제로 광고 제작에 사용하려고 하면 다음과 같은 문제가 발생합니다.
- 모델마다 별도의 서비스를 열어야 함
- 동일한 상품 정보를 반복해서 입력해야 함
- 생성한 프롬프트 (Prompt)나 설정을 나중에 재사용하기 어려움
- SNS, EC, 동영상 광고마다 사이즈를 다시 만들어야 함
- 모델별 요금이나 기능 차이를 알기 어려움
- 과거에 만든 광고 소재를 관리하기 어려움
즉, 문제는 "AI로 이미지를 생성할 수 있는가"만이 아닙니다.
광고 제작에 필요한 것은 상품 소재, 프롬프트, 모델 설정, 생성 이력, 비용, 출력 형식을 하나의 흐름으로 관리할 수 있는 워크플로우 (Workflow)입니다.
Photo2Ads에서는 이 제작 공정 전체를 하나의 화면에 통합하는 것을 목표로 했습니다.
주요 기능
현재의 Photo2Ads는 크게 다음과 같은 기능으로 구성되어 있습니다.
1. Image Ads
상품 사진을 참조하면서 정지 화상 광고를 생성하는 기능입니다.
여러 개의 상품 이미지를 추가하고 광고 목적, 비주얼 방향성, 종횡비, 품질, 생성 매수를 지정할 수 있습니다.
대응하는 모델은 공통 UI에서 선택할 수 있으며, Google의 Nano Banana 계열 모델이나 GPT Image 2 등 서로 다른 이미지 생성 모델을 용도에 따라 전환할 수 있도록 했습니다.
2. Video Ads
상품 사진이나 인물 이미지를 사용하여 짧은 동영상 광고를 생성하는 기능입니다.
동영상 모델에는 각각 다른 특징이 있습니다.
- Seedance 계열 모델
- Veo 3.1 Fast
- Kling 3 Turbo
- Wan 2.7 Reference
모델에 따라 대응하는 동영상 시간, 해상도, 참조 이미지 수, 음성 생성, 종횡비가 다릅니다.
따라서 단순히 모델명만 전환하는 것이 아니라, 선택한 모델의 능력에 맞춰 설정 UI도 변화하도록 설계했습니다.
3. Video Examples
동영상 생성에서는 모델명만 봐서는 완성된 결과를 상상하기 어렵다는 문제가 있습니다.
그래서 Photo2Ads에서는 75개의 재생 가능한 동영상 예시를 준비했습니다.
각 예시에는 다음과 같은 정보가 연관되어 있습니다.
- 실제로 사용하는 프롬프트
- 상품 참조 이미지
- 필요에 따른 인물·아바타 이미지
- 사용 모델
- 종횡비 및 동영상 시간
마음에 드는 예시를 선택하면 프롬프트와 참조 소재를 생성 화면으로 그대로 가져올 수 있습니다.
단순한 갤러리가 아니라, 바로 제작을 시작할 수 있는 템플릿으로서 설계되었습니다.
4. History와 Favorites
생성한 이미지나 동영상은 이력 (History)에 저장됩니다.
마음에 드는 결과는 즐겨찾기 (Favorites)에 추가할 수 있어, 여러 안을 비교하면서 채택할 크리에이티브를 정리할 수 있습니다.
AI 광고 제작에서는 한 번의 생성으로 완성된다고 단정할 수 없습니다.
과거의 결과를 확인하고 설정을 변경하여 재생성할 수 있는 것 또한 생성 품질만큼이나 중요하다고 생각합니다.
기술 구성
Photo2Ads는 Cloudflare 위에서 동작하는 풀스택 (Full-stack) Web 애플리케이션입니다.
| 영역 | 사용 기술 |
|---|---|
| 프론트엔드 | React 19 |
| ... |
요청은 대략 다음과 같이 처리됩니다.
Browser
↓
Cloudflare Worker
...
TanStack Start의 Server Function을 사용하여, 클라이언트에서 타입 안전(Type-safe)하게 서버 처리를 호출하고 있습니다.
입력값은 Zod로 검증하며, 로그인이 필요한 처리나 관리자용 처리에는 각각 인증 미들웨어(Authentication Middleware)를 적용하고 있습니다.
여러 AI 모델을 어떻게 통합했는가
개발 과정에서 어려웠던 부분 중 하나는 여러 모델의 기능 차이를 하나의 UI로 통합하는 것이었습니다.
모델마다 API 형식이 다를 뿐만 아니라, 다음과 같은 차이점이 있습니다.
- 대응 해상도 (Resolution)
- 종횡비 (Aspect Ratio)
- 영상 시간
- 참조 이미지 최대 개수
- 음성 생성 지원 여부
- 생성 비용
- 비동기 작업 (Asynchronous Job)의 상태 형식
- 에러 형식
이것들을 화면 측에 직접 작성해 버리면, 모델을 추가할 때마다 UI 전체를 변경해야 합니다.
그래서 각 모델의 능력을 공통 설정으로 정의하고 있습니다.
다음은 사고방식을 간략화한 예시입니다.
type ModelCapability = {
id: string;
mediaType: 'image' | 'video';
...
UI는 이 설정을 읽어 들여, 선택 중인 모델이 대응하는 항목만 표시합니다.
예를 들어, 음성을 지원하지 않는 영상 모델에서는 음성 설정을 표시하지 않고, 참조 이미지가 1장뿐인 모델에서는 업로드 수를 제한합니다.
이러한 설계 덕분에 모델의 추가나 사양 변경을 비교적 국소적으로 처리할 수 있게 되었습니다.
생성 처리는 비동기로 관리한다
이미지나 영상 생성에는 시간이 걸립니다.
특히 영상은 요청을 보낸 후 완료될 때까지 몇 분이 걸릴 수도 있습니다. 따라서 일반적인 HTTP 요청 안에서 완료를 기다리는 설계로는 만들지 않았습니다.
생성 시작 시에는 먼저 D1에 생성 레코드를 작성합니다.
pending
↓
processing
...
그 후, Cloudflare Workflows를 사용하여 생성 처리를 진행합니다.
완성된 이미지나 영상은 R2에 저장하고, D1의 생성 이력에 결과를 기록합니다. 브라우저를 닫거나 다른 페이지로 이동하더라도, 사용자는 나중에 이력 화면에서 결과를 확인할 수 있습니다.
실패했을 경우에도 상태를 남기기 때문에, "아무것도 표시되지 않는" 상황을 피할 수 있습니다.
크레딧 수를 사전에 표시한다
AI 모델의 비용은 일정하지 않습니다.
같은 모델이라도 해상도, 영상 시간, 음성, 생성 매수 등에 따라 필요한 크레딧이 달라집니다.
그래서 생성 버튼을 누르기 전에, 현재 설정으로부터 필요한 크레딧 수를 계산하여 표시하고 있습니다.
사용 모델
+ 해상도
+ 영상 시간
...
사용자가 결과를 예측할 수 없는 상태에서 크레딧을 소비하는 것이 아니라, 실행 전에 비용을 확인할 수 있다는 점을 중시했습니다.
상품의 외형을 보호한다
광고용 이미지에서는 단순히 아름다운 이미지를 만드는 것만으로는 부족합니다.
상품 패키지, 로고, 색상, 라벨, 형태 등이 크게 바뀌면 광고 소재로 사용하기 어려워집니다.
Photo2Ads에서는 프롬프트와 생성 플로우(Flow) 모두에서 다음 사항을 중시하고 있습니다.
- 상품의 형태를 유지한다
- 브랜드 컬러를 불필요하게 바꾸지 않는다
- 로고나 패키지를 가능한 한 유지한다
- 존재하지 않는 가격이나 효과를 멋대로 추가하지 않는다
- 읽을 수 없는 글자를 대량으로 생성하지 않는다
- 공개 전에 사람이 확인할 수 있는 상태로 만든다
AI 생성 결과를 그대로 자동 공개하는 것이 아니라, 마지막에는 이용자가 확인하고 선택하는 것을 전제로 하고 있습니다.
테스트와 출시
사용자용 기능을 추가할 때는 다음과 같은 흐름으로 확인하고 있습니다.
Spec
↓
Code
...
먼저, E2E 테스트 카탈로그에 사용자의 조작 순서와 기대 결과를 추가합니다.
구현 후에는 실제 브라우저에서 화면을 조작하고, 그 후 Playwright 테스트로 옮깁니다.
생성 AI를 포함하는 서비스는 외부 API의 응답이나 비동기 상태에 의해 문제가 발생하기 쉽기 때문에, 단일 컴포넌트뿐만 아니라 다음과 같은 일련의 흐름을 확인하는 것이 중요합니다.
- 로그인한다
- 상품 이미지를 업로드한다
- 모델과 설정을 선택한다
- 필요 크레딧을 확인한다
- 생성을 시작한다
- 이력에서 결과를 확인한다
개발하며 알게 된 점
모델을 공통화하는 것만으로는 부족하다
API 호출을 공통화하더라도 모델별 기능 차이가 UI에 남아 있으면 관리가 어려워집니다.
프로바이더(Provider) 계층뿐만 아니라 해상도, 시간, 음성, 참조 이미지 수, 요금 등의 능력 정보도 공통화할 필요가 있었습니다.
예시는 "보는 것"이 아니라 "시작하는 곳"이다
완성된 영상을 나열하는 것만으로는 사용자가 동일한 결과를 만들 수 없습니다.
프롬프트(Prompt), 참조 이미지, 모델 설정을 함께 계승할 수 있도록 함으로써, 제작 사례 페이지가 제작의 시작점이 되도록 했습니다.
AI의 품질과 조작성은 별개의 문제
고성능 모델을 연결하더라도, 설정이 이해하기 어렵거나 실패 후 결과를 추적할 수 없다면 프로덕트(Product)로서는 사용하기 불편한 상태로 남게 됩니다.
생성 품질에 더해, 이력(History), 에러 표시, 비용의 투명성, 재사용성을 갖추는 것이 중요했습니다.
인프라의 실체 확인이 중요
Cloudflare D1, R2, KV, Workers 등은 설정 파일에 이름이 있는 것만으로는 불충분합니다.
운영 환경(Production)의 리소스, 시크릿(Secret), 마이그레이션(Migration), 저장소가 올바르게 연결되어 있는지 실제 환경에서 확인할 필요가 있습니다.
향후 추가하고 싶은 기능
앞으로는 단발성 광고 생성 도구에서, 지속적인 광고 제작 워크스페이스(Workspace)로 발전시키고자 합니다.
구체적으로는 다음과 같은 기능을 검토하고 있습니다.
- 브랜드 컬러나 폰트를 저장하는 Brand Kit
- 자주 사용하는 상품 정보나 프롬프트의 재사용
- 하나의 상품으로부터 이미지 광고와 동영상 광고를 한꺼번에 생성하는 기능
- 팀 단위의 리뷰와 코멘트
- 광고 퍼포먼스(Performance) 데이터와의 연동
- 성과가 좋은 크리에이티브(Creative)를 기반으로 한 개선안 생성
요약
Photo2Ads를 만들면서 가장 강하게 느낀 점은, 생성형 AI 프로덕트의 가치는 단순히 모델을 호출하는 것만으로 결정되지 않는다는 것입니다.
상품 소재를 관리하고, 목적에 맞는 모델을 선택하며, 비용을 확인하고, 생성 결과를 비교하며, 재사용할 수 있는 단계까지 하나의 경험(Experience)으로 설계해야 합니다.
Photo2Ads에서는 상품 사진으로부터 광고 크리에이티브를 만드는 공정 전체를 가능한 한 심플한 워크플로우(Workflow)로 통합했습니다.
관심이 있다면 꼭 실제 제작 사례와 대응 모델을 확인해 보시기 바랍니다.
Discussion

AI 자동 생성 콘텐츠
본 콘텐츠는 Zenn AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기