docs(spec): 인스타 카드뉴스 품질 고도화 + 업로드 친화 패키지
모던 미니멀 디자인 시스템 템플릿으로 카드 품질 격상 + 렌더 견고화 (fonts.ready 대기·1080x1350 정확·오버플로우 clamp로 known-issue 해결) + zip 패키지 다운로드(업로드 친화, 반자동). Graph API 미사용. 2 repo: insta-lab(템플릿/카피/zip/web-ui) + web-ai(렌더 워커). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,97 @@
|
||||
# 인스타 카드뉴스 품질 고도화 + 업로드 친화 패키지 — 설계 Spec
|
||||
|
||||
- **작성일**: 2026-06-02
|
||||
- **상태**: 설계 승인 (구현 plan 대기)
|
||||
- **대상**: `insta-lab`(템플릿·카피·zip·web-ui) + `web-ai/services/insta-render`(렌더 워커, **별도 repo**)
|
||||
- **사이클**: 스마트 에이전트 고도화 3종 중 **3번 인스타**. (1 로또·2 주식 배포 완료)
|
||||
|
||||
---
|
||||
|
||||
## 1. 배경 & 목표
|
||||
|
||||
현재 insta-lab은 뉴스→키워드→Claude 카피(cover+본문8+cta+caption+hashtags)→Redis push→**Windows insta-render 워커**가 Jinja→HTML→Playwright 스크린샷(1080×1350)→텔레그램 전달 흐름이다. 그러나 카드가 "진짜 카드뉴스" 품질에 못 미치고(메모리상 렌더 known-issue), 현재 default 템플릿은 55줄짜리 기본형(accent+headline/body/footer)이다.
|
||||
|
||||
CEO 목표: **진짜 카드뉴스 형식**으로 카드 품질을 끌어올리고, 완성 패키지를 **인스타에 업로드하기 쉽게** 만든다.
|
||||
|
||||
### 핵심 결정 (2026-06-02 brainstorming)
|
||||
1. **업로드 방식 = 반자동(현행 개선)**. Instagram Graph API/Meta 앱/IG 비즈니스 계정 미사용. 완성 카드+캡션을 사용자가 인스타 앱에서 직접 업로드하되, **마찰 없는 패키지 전달**(텔레그램 + zip 다운로드)로 개선.
|
||||
2. **카드 품질 = 디자인 시스템 템플릿 고도화**. 폴리시한 HTML/CSS 디자인 시스템 + Playwright 렌더, known-issue 해결. (AI 생성 비주얼·Vision import 수리 아님)
|
||||
3. **비주얼 = 모던 미니멀**. 넉넉한 여백·강한 산세리프 타이포·1~2 accent·깔끔한 그리드. 단일 강한 default 테마(멀티테마 X), accent만 카테고리별.
|
||||
|
||||
### 기존 자산 (재사용)
|
||||
- `insta-lab/app/card_writer.py` — Claude 카피 생성(cover_copy{headline,body,accent_color}, body_copies[8]{headline,body}, cta_copy{headline,body,cta}, suggested_caption, hashtags[]).
|
||||
- `insta-lab/app/templates/default/card.html.j2` — 격상 대상(현 55줄 기본형).
|
||||
- `web-ai/services/insta-render/`: `worker.py`(BLPOP `queue:insta-render` → `GET /api/insta/slates/{id}` → `render_slate` → webhook `/api/internal/insta/update`), `card_renderer.py`(`_build_pages`로 10페이지 spec 구성 cover/body8/cta, Jinja→HTML→`page.goto(file://, networkidle)`→`screenshot(full_page=False)` @viewport 1080×1350, `CARD_TEMPLATE_DIR`에서 템플릿 로드).
|
||||
- nginx `/media/insta/` → `/data/insta_cards/`(카드 PNG 공개 서빙) — 패키지 다운로드에 활용.
|
||||
|
||||
### known-issue 근원 (이번 작업으로 해결)
|
||||
- 웹폰트(@import Google Fonts) 로딩 전 스크린샷 → fallback 폰트 렌더.
|
||||
- `full_page=False` + 콘텐츠가 1350px 초과 → 하단 잘림.
|
||||
- (기존 minimal 테마) Vision-import 마스킹 좌표·background-image 경로 문제 → **신규 깨끗한 디자인 시스템 템플릿으로 경로 자체를 제거(우회)**.
|
||||
|
||||
---
|
||||
|
||||
## 2. 디자인 시스템 (모던 미니멀)
|
||||
|
||||
`insta-lab/app/templates/default/card.html.j2`를 페이지 타입별 레이아웃을 가진 디자인 시스템으로 재작성.
|
||||
|
||||
### 페이지 타입별 레이아웃 (`_build_pages`의 page_type 사용)
|
||||
- **cover** (page 1): 카테고리 배지 + 대형 헤드라인(96px급) + 서브카피 + 브랜드 핸들. 시선 집중.
|
||||
- **body** ×8 (page 2~9): 좌상단 번호 인덱스(02~09) + 포인트 헤드라인(72px급) + 본문(40px급, 2~4문장) + 하단 진행 인디케이터(점/바). 일관 그리드.
|
||||
- **cta** (page 10): 요약 헤드라인 + 마무리 본문 + 행동유도(팔로우/저장) + 핸들.
|
||||
|
||||
### 디자인 토큰
|
||||
- 타이포: Pretendard(우선) 또는 Noto Sans KR, weight 900/700/400, letter-spacing 음수, line-height 1.15~1.55.
|
||||
- 레이아웃: 1080×1350 고정, safe-margin(예: 좌우/상하 ~80px), 그리드 정렬.
|
||||
- 컬러: 라이트 배경(#F7F7FA 계열) + `accent_color`(카테고리별, 데이터 기존: economy #0F62FE / psychology #A66CFF / celebrity #FF5C8A 등) 포인트.
|
||||
- 푸터: `{page_no} / {total_pages}` + 브랜드 핸들. body는 진행 인디케이터.
|
||||
|
||||
### 제약
|
||||
- 각 페이지 = 정확히 1080×1350 고정 박스, `overflow:hidden`. 긴 본문 대비 본문 컨테이너 `max-height` + 줄수 clamp(말줄임 또는 폰트 축소).
|
||||
- 단일 default 테마. accent만 카테고리 차등(추가 테마 디렉토리 안 만듦).
|
||||
|
||||
---
|
||||
|
||||
## 3. 렌더 견고화 (web-ai 워커, known-issue 해결)
|
||||
|
||||
`web-ai/services/insta-render/card_renderer.py` 보강:
|
||||
- **폰트 보장**: `page.goto` 후 screenshot 전에 `await page.evaluate('document.fonts.ready')` 대기 추가. (가능하면 Pretendard를 워커에 self-host/번들해 네트워크 의존 제거 — 폴백으로 fonts.ready 대기.)
|
||||
- **정확한 1080×1350**: 템플릿이 `.card{width:1080px;height:1350px;overflow:hidden}`을 보장. `full_page=False` + viewport 1080×1350 유지. 콘텐츠 오버플로우는 템플릿 CSS(clamp/max-height)로 차단.
|
||||
- **PNG 검증**: 렌더 후 각 PNG가 1080×1350인지 + 0바이트/빈 페이지 아닌지 확인. 실패 시 webhook `failed`.
|
||||
- **템플릿 sync (open item)**: 워커의 `CARD_TEMPLATE_DIR`가 신규 디자인 템플릿을 받는 경로 확인·정립. (insta-lab 템플릿 → 워커로 어떻게 전달되는지 plan에서 확인: web-ai repo 복사본인지 별도 sync인지. 신규 템플릿이 워커에 반영돼야 효과 발생.)
|
||||
|
||||
---
|
||||
|
||||
## 4. 카피 정합 + 업로드 친화 패키지
|
||||
|
||||
- **카피 글자수 가이드**: `card_writer.py`의 프롬프트에 헤드라인/본문 글자수 상한 명시(디자인 박스에 맞게) → 오버플로우 예방. 시작 기준값(템플릿 박스 확정 시 ±조정): cover headline ≤ 22자 / body headline ≤ 26자 / body ≤ 120자 / cta headline ≤ 22자. CSS clamp가 2차 방어이므로 가이드는 근사치여도 안전.
|
||||
- **업로드 친화 패키지 (신규)**: 기존 텔레그램 미디어그룹(10장)+캡션/해시태그 유지 + **zip 다운로드** 추가:
|
||||
- 신규 API `GET /api/insta/slates/{id}/package` → 10 PNG + `caption.txt`(suggested_caption + hashtags) 묶은 zip 반환.
|
||||
- web-ui 슬레이트 상세에 "패키지 다운로드" 버튼.
|
||||
- 사용자가 zip 받아 인스타 앱에 캐러셀 업로드 + caption 붙여넣기.
|
||||
- **승인 게이트 유지**: 키워드 후보 푸시 → 사용자 선택 → 렌더 → 전달. 자동 게시 없음(반자동).
|
||||
|
||||
---
|
||||
|
||||
## 5. 에러·테스트·리스크·스코프
|
||||
|
||||
- **2 repo 배포 경로**: insta-lab = git push → Gitea webhook 자동배포. web-ai 워커 = Windows 머신에서 별도 갱신(repo: ai-trade.git). 템플릿·렌더 변경이 양쪽에 반영돼야 함.
|
||||
- **테스트**:
|
||||
- insta-lab: card_writer 글자수 제약, zip 패키지 구성(10 PNG + caption.txt), package API.
|
||||
- web-ai: 페이지 타입별 템플릿 렌더 HTML 스냅샷, PNG 1080×1350 크기 검증, fonts.ready 대기, 오버플로우 clamp (web-ai `tests/test_worker` 확장).
|
||||
- **리스크**:
|
||||
- 템플릿 sync 누락 → 워커가 구 템플릿 렌더(효과 없음). plan에서 sync 경로 확정.
|
||||
- 긴 카피 오버플로우 → 글자수 가이드 + CSS clamp 이중 방어.
|
||||
- 폰트 로딩 타이밍 → fonts.ready 대기(+self-host).
|
||||
- known-issue는 깨끗한 디자인 시스템 + 렌더 견고화로 **근본 해결**(Vision-import 경로 제거).
|
||||
|
||||
---
|
||||
|
||||
## 6. 결정 로그 (2026-06-02)
|
||||
1. 업로드 = 반자동(현행 개선, Graph API 미사용)
|
||||
2. 카드 품질 = 디자인 시스템 템플릿 고도화
|
||||
3. 비주얼 = 모던 미니멀, 단일 default 테마
|
||||
|
||||
## 7. 스코프 밖 / 향후
|
||||
- Instagram Graph API 자동 게시, 멀티 테마, AI 생성 비주얼, Vision design_importer 수리, 카테고리별 차별 테마 — 향후.
|
||||
- 9:30 자동 슬레이트(auto_select) 흐름 자체는 변경 안 함(품질·패키지만 개선).
|
||||
Reference in New Issue
Block a user