이미지 모델이 App Store 스크린샷 승인을 계속 거절해서, 코딩 에이전트가 정확한 사양으로 렌더링하도록 만들었습니다
요약
App Store 스크린샷 생성 시 발생하는 이미지 모델의 기하학적 정확도 문제를 해결하기 위해, 코딩 에이전트가 HTML/CSS를 사용하여 결정론적으로 렌더링하는 HyperShots 기술을 소개합니다. 이미지 모델의 통계적 근사치 대신 CSS의 산술적 정확성을 활용하여 규격과 텍스트를 완벽하게 구현합니다.
핵심 포인트
- 이미지 모델의 통계적 한계를 CSS의 결정론적 렌더링으로 극복
- Headless Chrome을 활용한 픽셀 단위의 정확한 스토어 규격 구현
- Apple의 거절 사유(크기, 알파 채널, 용량 등)를 검증하는 Validator 포함
- 생성형 AI는 스티커 아트 등 보조적 영역에만 활용하여 일관성 유지
- HyperShots 오픈 소스 프로젝트를 통한 자동화 워크플로우 제공
올해 iOS 앱을 출시하는 많은 사람들처럼, 저도 이미지 모델을 사용하여 App Store 스크린샷을 생성하려고 시도했습니다. GPT Image, nano banana — 결과물은 정말 훌륭해 보였습니다. 하지만 App Store Connect에서 이를 거절했습니다: 잘못된 캔버스 크기, 미묘하게 왜곡된 텍스트, 실제 기기와 일치하지 않는 디바이스 프레임 때문이었습니다.
세 번째 거절을 겪은 후, 저는 문제가 프롬프트 엔지니어링 (Prompt Engineering)에 있지 않다는 것을 깨달았습니다. 프레임과 캔버스는 기하학이며, 기하학은 산술입니다 — 이는 코딩 에이전트가 CSS를 통해 완벽하게 표현할 수 있는 것이지만, 이미지 모델은 통계적으로 근사치만 낼 수 있는 영역입니다. 확산 모델 (Diffusion Model)에게 1290×2796 크기를 정확히 맞추고, 픽셀 단위로 정확한 베젤과 선명한 17px 모노 타입을 구현하라고 요구하는 것은 통계에게 산술을 수행하라고 요구하는 것과 같습니다.
그래서 저는 작업을 분리했고, 그 결과물을 Claude Code와 Codex를 위한 기술로 오픈 소스화했습니다: HyperShots.
분리: Apple이 규칙을 적용하는 곳은 결정론적으로, 판매가 이루어지는 곳은 생성적으로
결정론적(Deterministic) 영역 (AI를 전혀 사용하지 않음):
- 에이전트가 작은 기하학적 계약(contract)에 따라 단순한 HTML/CSS로 마케팅 패널을 디자인합니다 — 고정된 화면 종횡비(실제 캡처와 일치하는 0.460)를 가진 디바이스 프레임, 프로필 기반의 캔버스 변수, 스티커 프리미티브(sticker primitives)
- Headless Chrome이 이를 정확한 스토어 크기로 렌더링합니다: 430×932 CSS를 3배수로 적용하여 1290×2796 픽셀 단위까지 정확하게 구현
- **Fail-closed 검증기 (Validator)**가 Apple이 실제로 거절하는 모든 항목을 확인합니다: 크기, 알파 채널 (네, RGBA PNG는 거절됩니다), 비 sRGB ICC 프로필, 패널 개수 (최대 10개), 그리고 8MB 용량 제한. '통과(Green)'는 에셋 사양 때문에 스토어에서 거절당할 일이 없음을 의미합니다.
- 현지화(Localization)는 언어당 하나의 명령으로 처리됩니다:
data-i18n마커, 원자적 문자열 주입 (누락되었거나 사용되지 않는 키는 치명적입니다 — 영어로 조용히 배포되는 일은 없습니다), 그리고 독일어가 30% 더 길어질 때 넘치는 대신 기기 영역을 벗어나지 않을 때까지 크기가 줄어드는 자동 맞춤형 헤드라인
**생성적(Generative) 영역 (선택 사항, 본인의 fal.ai 키를 사용하세요):
- 컷아웃 스티커 아트 (Cut-out sticker art): 이미지 생성 (image generation) → 배경 제거 (background removal) → 투명 PNG, 에이전트가 일반 CSS 변환 (CSS transforms)을 사용하여 배치
- 선택 사항인 전체 세트 "메이크오버 (makeover)" 단계 — 렌더링된 패널에 대한 이미지 투 이미지 (image-to-image) 작업으로, 마스크 (mask)와 재합성 (re-composite) 단계를 통해 깨끗한 렌더링 결과물로부터 텍스트와 프레임을 나중에 복원합니다. 모델은 사용자의 타이포그래피 (typography)를 절대 직접 생성하여 내보내지 않습니다.
- 스타일 앵커 (style anchor)를 통한 세트 일관성 유지: 첫 번째 패널을 자유롭게 등급화(grade)한 다음, 나머지 패널의 참조 이미지 (reference image)로 전달합니다. 앵커가 설정된 세트 전반의 측정된 드리프트 (drift): 팔레트 기준 약 4%
그 후 fastlane deliver가 세트를 App Store Connect로 푸시합니다 — 이 기술은 제가 오후 시간을 허비하게 만들었던 첫 번째 버전의 메타데이터 충돌(metadata crash) 우회 방법을 포함한 런북 (runbook)을 함께 배포합니다.
고생하며 배운 것들
Chrome의 1fr은 min-content를 준수합니다. nowrap 캡션이 열(column)의 너비를 조용히 넓혔기 때문에, CSS 그리드(grid)에서 렌더링된 동일한 종횡비의 이미지들이 서로 다른 높이로 나타날 수 있습니다. repeat(N, minmax(0, 1fr))를 사용하지 않으면 기하학적 구조(geometry)가 당신을 속이게 됩니다.
Headless Chrome의 최소 창 너비는 500px입니다. 만약 "모바일" 스크린샷이 잘려 보인다면, 500px 레이아웃을 390px로 크롭하고 있는 것일 수 있습니다 — 페이지 자체는 문제가 없었습니다.
이미지 모델 편집 엔드포인트 (edit endpoints)는 스토어 규격의 치수를 전혀 출력할 수 없습니다. gpt-image 편집은 16의 배수로 스냅(snap)됩니다; 1290, 1284, 1320은 이에 해당하지 않습니다. 어떤 AI 스타일 패스 (style pass)든 반드시 리샘플링 (resample) + 재합성 (re-composite) 단계로 끝나야 하며, 그렇지 않으면 출력물은 구조적으로 규격에 맞지 않게 됩니다.
마스크 (Masks)는 가이드일 뿐, 보증이 아닙니다. 인페인팅 (Inpainting) 스타일의 "보호된" 영역은 모델을 통해 다시 렌더링되어 대략적으로만 보존됩니다. 텍스트가 픽셀 단위로 정확해야 한다면, 소스에서 다시 합성(composite)하십시오. 항상 그래야 합니다.
폰트는 반드시 번들링(vendored)되어야 합니다. 렌더링 시점에 Google Fonts @import를 사용하는 것은 타임아웃 발생 시 "결정론적 (deterministic)" 렌더러가 조용히 시스템 폰트로 폴백(fallback)하게 만들며, 상위 폰트 업데이트가 메트릭 (metrics)을 어긋나게 만듭니다. 로컬 woff2를 사용하는 @font-face를 쓰거나, 아니면 아예 쓰지 마십시오.
실제로 작동하는가?
지금까지 두 개의 프로덕션 앱이 이 파이프라인을 통해 스크린샷 세트를 출시했습니다. 하나는 단 한 문단의 브리프(brief)에서 시작하여 단 한 번의 에이전트 세션만으로 스토어 출시가 가능한 검증된 세트를 만들어냈으며, 이후 약 8번의 창업자 주도 수정 과정을 거치는 동안 단 한 번의 사양(spec) 오류도 발생하지 않았습니다. hypershots.dev의 갤러리에서 두 세트를 모두 확인할 수 있습니다. 사이트 자체 아이콘을 포함하여 해당 페이지의 모든 이미지는 이 파이프라인이 설명하는 방식대로 생성되었습니다.
이 프로젝트는 MIT 라이선스이며, 여러분이 이미 사용 중인 어떤 에이전트와도 함께 작동합니다. 또한 결정론적(deterministic)인 절반의 과정은 API 키가 필요하지 않습니다:
npx skills add hypersocialinc/hypershots
README와 게시물에 포함되어야 할 솔직한 한계점들을 말씀드리자면: iPad는 별도의 제작 단계가 필요하며(0.75 종횡비는 iPhone 패널로부터 다시 렌더링되지 않음), RTL(Right-to-Left)/CJK(한중일) 지원은 로드맵 단계에 있습니다(현재는 라틴 및 라틴 확장 폰트만 제공됨). 또한 스타일 패스(style pass)의 경우, 텍스트와 기기가 캔버스 전체를 덮는 레이아웃에 대해서는 문서화된 주의 사항이 있습니다.
만약 스크린샷 거절의 지옥을 경험해 보셨다면, 어떤 부분에서 문제가 발생했는지 진심으로 듣고 싶습니다. 그리고 이 도구로 스크린샷 세트를 출시하신다면, 갤러리에 제출하실 수 있습니다 (추천된 앱에는 백링크가 제공됩니다).
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기