4.4 KiB
4.4 KiB
숏폼 큐 — Opal 연동 작업 큐/결과 저장 설계
2026-08-03. 유튜브 URL을 h-lab에 등록하면, 구글 Opal "숏폼 생성기" 앱(무료, Gemini Pro 영상분석)을 실행 엔진으로 삼아 결과를 DB에 구조화 저장하고 조회하는 기능.
배경·제약
- Opal은 외부 API가 없다. 실행은 (A) 클로드가 브라우저 자동화로 대행하거나 (B) 사용자가 수동 실행 후 결과를 붙여넣는다. 두 경로 모두 동일한 저장 API로 수렴한다.
- Gemini API 직접 호출은 Pro가 유료(2026-04부터 무료 티어 제외)라 배제. 단, 실행 엔진 교체가 쉽도록 h-lab은 "결과 텍스트를 받아 파싱·저장"만 담당한다.
- Opal 출력 형식(프롬프트 v13.x): 구간(ID 1~5)별로
N=====구분자 + ```json 블록(capcut2 붙여넣기용) + 📌 타이틀 후보 5선 + ⏱️ 컷 길이 검산표.
구성요소
1. 백엔드 — domain/shortform/ (DDD 컨벤션)
엔티티
ShortformJob(테이블shortform_job): id, youtubeUrl, videoId(URL에서 추출), title(nullable, 결과 JSON의 title_main 첫 값 또는 null), status(PENDING/DONE/FAILED), rawOutput(TEXT, 파싱 실패 대비 원문 보존), createdAt, completedAtShortformClip(테이블shortform_clip): id, job FK, clipNo(1~5), capcutJson(TEXT), titleCandidates(TEXT), durationTable(TEXT), titleTop/titleMain(파싱값, nullable)
API (ApiResponse<T> 래핑, /api/shortform/..., web/ 스타일 경로)
POST /api/shortform/jobs{youtubeUrl} → 큐 등록(PENDING). 중복 URL 등록 시 기존 작업 반환GET /api/shortform/jobs→ 목록(최신순)GET /api/shortform/jobs/{id}→ 상세(클립 포함)POST /api/shortform/jobs/{id}/result{rawText} → 파싱·저장, status 갱신POST /api/shortform/import{youtubeUrl, rawText} → 등록+결과 저장 한 번에 (수동 실행 후 붙여넣기용)DELETE /api/shortform/jobs/{id}
파서 (ShortformOutputParser)
N=====형태 구분자로 섹션 분리 → 섹션마다 ```json 코드블록, "타이틀 후보" 블록, "검산표" 블록 추출- JSON 파싱 성공 시 titleTop/titleMain 추출. 어떤 단계든 실패하면 해당 클립은 원문 조각만 저장하고 job은 DONE 유지(rawOutput이 항상 원본 보존) — 파싱 실패로 데이터를 잃지 않는다
- 클립이 0개 추출되면 FAILED + rawOutput 보존
2. 프론트 — /shortform 페이지 (Thymeleaf, layout/base)
- 사이드바에 "숏폼" 메뉴 추가 (
currentPage=shortform) - 상단: URL 입력 폼(등록) + "결과 붙여넣기" 토글(URL+원문 textarea → import API)
- 목록: 작업 카드(썸네일
img.youtube.com/vi/{videoId}/mqdefault.jpg, 상태 뱃지, 등록시각) - 상세(카드 펼침 또는 별도 영역): 클립 1~5 카드 — 타이틀(top/main), 타이틀 후보 5선, 검산표, capcut2 JSON 복사 버튼(클립보드 API)
3. 스킬 — .claude/skills/shortform-queue/SKILL.md
트리거: /shortform-queue, "숏폼 큐 돌려줘" 류 요청.
절차(오늘 세션에서 검증된 노하우를 명문화):
GET /api/shortform/jobs에서 PENDING 목록 조회 (h-lab은 localhost:8088)- 크롬 자동화로 opal.google → 숏폼 생성기 앱(edit URL 고정) 열기
- YouTube Video 노드 클릭 → URL 입력 → Apply → Preview의 Start
- 완료 폴링(전체 4~5분, Step 3 각 ~90초). 앱 UI는 접근성 트리에 안 잡히므로 스크린샷 +
iframe#opal-appcontentDocument에 JS 주입(shadow DOM 관통)으로 상태 확인 - Output 전문 추출(JS,
"cuts"포함 최대 텍스트) →POST /api/shortform/jobs/{id}/result - 노드 에러 시 1회 재실행, 재실패면 FAILED 보고 후 다음 작업 진행. 큐 소진까지 반복, 요약 보고 주의사항: Opal 프롬프트 끝 중복 칩 이슈(2026-08-03 해결) 같은 앱 구조 변경 감지 시 사용자에게 보고.
순서·범위
- 백엔드(엔티티→파서→API) — 파서는 오늘 실행에서 얻은 실제 Output 샘플로 단위 테스트
- 프론트 페이지
- 스킬 파일 빌드·커밋은 변경 단위별. 실제 Opal 실행 검증은 스킬 완성 후 사용자 요청 시.
하지 않는 것 (YAGNI)
- Gemini API 직접 호출(비용) — 파서/저장 구조만 호환되게 유지
- n8n 연동, 스케줄 자동 실행(Opal이 로그인 세션 필요, 무인 실행 불가)
- capcut2 앱으로의 직접 전송(현행 수동 붙여넣기 유지)