에셋 통합과 Shot·스토리보드·월드 구현 계획
상태: 0~3차 로컬 구현 완료 / 영향 범위 검증 완료
기준일: 2026-09-08
운영 배포는 하지 않았다. 아래 구현 기록에서 코드 반영과 실제 검증 범위를 구분한다.
2026-09-09 후속 변경: 필수 Shot 설계 단계는 Beat 기반 스토리보드로 대체했다. 아래 내용은 0~3차 구현 당시 결정과 검증 이력이다.
1. 목표와 적용 우선순위
SurfAI 전체를 단편영화 제작을 위한 서비스로 구성한다. 사용자는 공용 에셋에서 인물·의상·장소를 준비하고, 영화 프로젝트에서 필요한 에셋을 선택하여 Shot과 결과물을 만든다.
이번 논의에 따른 후속 구현은 이 문서를 기준으로 한다. 2026-08-21 Cinema 문서의 카메라 중심 Shot 설계와 후속 작업 순서 중 여기서 변경한 부분은 이 계획으로 대체한다. 기존 문서의 구현·삭제 이력은 그대로 보존하며, 계획을 현재 동작으로 읽지 않는다.
핵심 결정:
- 전역 메뉴의 페르소나·코디·배경·월드를 에셋 진입점으로 모은다.
- 배경 이미지와 3D 월드를 모두 유지하고, 배경 페이지 내부에서 구분한다.
- Shot 단계와
Scenario → Sequence → Scene → Beat → Shot흐름은 유지한다. - 초기 Shot 설계는 이야기의 표현 범위·행동·연속성·길이에 집중한다.
- 구도·카메라 위치·시야각·움직임은 향후 월드 작업에서 정하고 해당 시점·연출 데이터에 저장한다.
- 공통 화면비·해상도·FPS는 시나리오에서 확정하고 하위 제작에 상속한다.
- 프레임·스토리보드와 월드 작업은 Shot 페이지에서 이어진다. 별도의 필수 승인 단계를 추가하지 않는다.
2. 현재 출발점
2026-09-08 로컬 코드 확인 기준이다. 운영 환경의 배포 상태를 뜻하지 않는다.
| 영역 | 현재 상태 | 이번 계획에서 추가할 부분 |
|---|---|---|
| 내비게이션 | 시네마·월드·페르소나·스타일링이 별도 진입점 | 에셋 진입점과 배경 내부 분류 |
| 공통 제작 설정 | 시나리오 확정, 버전·출력 크기 기록, Shot 이미지 생성 연결 | 모든 신규 생성·월드 캡처 계약에 상속 |
| Shot | 카메라 항목이 DTO·편집기·AI 제안·Prompt 생성에 연결 | 서사 중심 설계로 함께 전환 |
| Prompt Package | Shot별 Frame·Motion Prompt 생성·수정·복사 | 새 설계 및 실제 참조 입력 반영 |
| 직접 생성 | Shot Frame Prompt로 공통 이미지 생성 요청 가능 | Shot별 결과 목록·선택·스토리보드 영속 저장 |
| Motion | Prompt와 공통 설정 복사 가능 | 영상 실행은 별도 연결·지원 검증 필요 |
| Worlds | 불변 WorldRevision, Artifact 수집, Pano·SPZ 뷰어 | Cinema 연결·시점 저장·복원·캡처 |
| 프로젝트 에셋 | Persona·Coordi의 고정 AssetVersion 연결 | 배경 이미지·WorldRevision의 타입별 연결 |
구형 Render Plan, Scene Proxy, Generation Attempt 관련 소스 파일의 존재를 활성 기능으로 간주하지 않는다. 현재 등록된 Cinema 서비스, Shot Prompt Package와 공통 생성 이력 위에 필요한 관계만 추가한다. 삭제된 테이블·API를 일괄 복구하지 않는다.
3. 메뉴와 에셋의 역할
영화 프로젝트 — 기존 Cinema
에셋
├─ 페르소나
├─ 코디
└─ 배경
├─ 배경 이미지
└─ 3D 월드
배경 이미지·3D 월드는 배경 페이지의 탭 또는 필터다. 각각을 전역 메뉴에 중복 노출하지 않는다. 홈·관리자·계정 등 보조 메뉴의 삭제나 전면 개편은 이번 범위에 포함하지 않는다.
| 종류 | 의미 | 사용 방식 |
|---|---|---|
| 배경 이미지 | 구도가 정해진 2D 이미지 | 업로드·생성 후 바로 참조로 사용 |
| 3D 월드 | 여러 시점을 선택할 수 있는 재사용 공간 | 공간을 열고 시점을 정해 배경 이미지 생성 |
| 월드 유래 배경 이미지 | 특정 월드 버전과 시점에서 얻은 이미지 | 참조로 사용하거나 원본 월드·저장 시점 다시 열기 |
모든 배경 이미지에 월드를 요구하지 않는다. 이미지 한 장을 사용하기 위해 월드를 먼저 생성하게 하지 않는다. 반대로 월드는 인물·이동 소품을 자동으로 배치한 완성 Shot으로 취급하지 않는다.
에셋 원본은 영화 간에 공유하고 프로젝트는 선택한 버전을 참조한다. 메뉴 통합 때문에 기존 Persona·Coordi·World 저장소를 하나의 테이블로 합치거나 원본 파일을 복제하지 않는다.
4. 모듈과 책임
| 모듈 / 서브모듈 | 책임 |
|---|---|
| Navigation / Asset Library | 에셋 진입점, 종류별 탐색, 기존 URL 연결 |
| Cinema / Shot Brief | Beat 표현 범위, 등장 대상, 행동 흐름, 제안·확정·버전 |
| Cinema / Shot Frames | Shot과 생성 결과 연결, 후보·선택 프레임, 이력 |
| Cinema / Storyboard | Scene 내 Shot 순서에 따른 선택 프레임 표시 |
| Cinema / Environment Binding | Scene 기본 배경과 Shot별 명시적 선택 |
| Worlds / Viewpoint Capture | 불변 월드 버전에 대한 시점 저장·복원·이미지 캡처 |
| Generation / Reference & Prompt | 기존 참조 UI, 안정적인 별칭, 실제 입력 매핑, 최종 Prompt |
| Cinema / Production Settings | 이미 구현된 영화 공통 출력 설정과 실행 Snapshot |
Worlds는 Cinema에 종속되지 않는다. 연결 책임은 Cinema의 Environment Binding에 둔다. 인물·소품 배치와 카메라 경로는 환경 생성 자체와 분리한다.
5. 0차 — 에셋 메뉴 정리
작업
- 전역 에셋 메뉴와 페르소나·코디·배경 내부 탐색을 만든다.
- 현재 스타일링 진입점 안의 코디·배경 경로를 조사해 각 항목으로 연결한다.
- 배경 페이지에 배경 이미지·3D 월드 분류를 제공하고 기존 생성·목록·상세 기능을 재사용한다.
- 에셋 종류에 맞는 만들기·업로드·공간 열기 동작을 제공한다.
- 기존 URL·상세 ID·쿼리·공유 링크를 유지한다. 새 경로가 필요하면 명시적 호환 경로를 둔다.
- 메뉴 활성 상태, 뒤로 가기, 생성 취소 후 복귀, 미저장 변경 경고, 모바일·키보드 탐색을 맞춘다.
메뉴 정리는 정보 구조 변경이다. 월드 유래 이미지의 출처 저장과 Shot 연결은 3차에서 구현한다. 0차에 동작하지 않는 캡처 버튼을 먼저 노출하지 않는다.
완료 기준
기존 에셋을 에셋 메뉴에서 찾고 생성·편집·사용할 수 있다. 배경 이미지와 월드는 같은 배경 페이지에서 구분되며, 기존 상세 링크와 데이터가 유지된다. 영화에 연결하지 않고도 공용 에셋을 준비할 수 있다.
6. 1차 — Shot 설계 개편
설계 항목
| 항목 | 내용 | 입력 원칙 |
|---|---|---|
| 제목·목적 | 관객에게 전달할 정보·감정 | 기존 제목·shotPurpose 재사용 |
| Beat Mapping | 표현할 원문·비트와 범위 | 기존 M:N·coverage 계약 유지 |
| 등장인물·대상 | 실제 등장 인물과 핵심 소품 | Character Mapping 재사용, 대상 설명 보완 |
| 행동 흐름 | 시작 상태 → 주요 행동 → 종료 상태 | 필요한 내용만 작성, 빈 선택 항목 허용 |
| 연속성·연출 조건 | 소품 상태, 정보 공개 시점 등 | 좌표나 렌즈 수치 대신 의미상의 조건 |
| 예상 길이 | 해당 행동에 필요한 시간 | durationMs 유지, FPS는 프로젝트에서 상속 |
Beat에 있는 사건·감정을 다시 입력하도록 강제하지 않는다. Shot은 해당 비트를 어느 범위까지 하나의 연속된 화면으로 표현할지 구체화한다. 예: “편지를 발견한다”라는 비트를 “서랍을 열고 편지를 발견한 뒤 손을 멈춘다”로 표현한다. 여러 인물과 상호작용을 지원하며 1인 Shot으로 제한하지 않는다.
작업
- Shot·Proposal 데이터, 생성·수정 DTO, 프론트 타입을 함께 변경한다.
- shotSize, cameraAngle, cameraHeight, focalLengthMm, lensDescription, cameraMovement, movementDescription, composition을 초기 설계의 필수 입력·자동 기본값에서 제외한다.
- 수동 편집, 단계별·통합 분석, AI 편집 제안, 채택·재승인 경로를 같은 새 계약으로 맞춘다.
- Shot 분할 기준을 렌즈별 coverage 생성보다 사건 표현 범위·시간·행동의 연결에 둔다. 사용자의 분할·병합·순서 편집은 유지한다.
- LLM Structured Output과 Prompt Package 입력도 변경해 숨겨진 카메라 지시가 다시 삽입되지 않게 한다.
- 목적·행동·연속성 패널과 기존 Prompt 패널을 Shot 작업 공간으로 정리한다.
- 기존 데이터와 과거 최종 Prompt는 보존한다. 새 의미 필드를 추측으로 채우지 않는다.
기존 카메라 값은 새 기본값으로 전파하지 않고 과거 사양으로 읽을 수 있게 보존한다. 촬영 조건을 다시 지정하려는 사용자는 향후 월드 작업에서 명시적으로 선택한다. 과거의 개발 데이터 일괄 삭제 정책을 이번 전환에 적용하지 않는다.
완료 기준
카메라 입력 없이 Shot의 생성·수정·AI 제안·확정·Prompt 생성이 가능하다. 기존 Shot은 열리고 Mapping·내용·이력이 유지된다. 실제 최종 Prompt에 제거한 렌즈·정면 구도 등의 기본 지시가 되살아나지 않는다.
7. 2차 — 프레임·스토리보드 관리
작업 공간
- 왼쪽: Shot 순서, 예상 길이, 대표 프레임, 진행 상태.
- 중앙: 선택한 프레임 미리보기. 3차에서 월드 작업 화면으로도 사용한다.
- 오른쪽: Shot 목적·행동·등장인물·연속성 조건.
- 하단: 프레임 목록과 재사용한 참조·Prompt 입력 영역.
- 공통 제작 설정: 읽기 요약과 시나리오 설정으로 이동하는 링크.
기존 GenerationReferencePanel, GenerationReferenceThumbnails, GenerationPromptMentionInput을 우선 재사용한다. 참조 영역은 기본 숨김이며 +로 토글하고, 썸네일 미리보기·삭제와 @ 목록을 제공한다. 별도 참조 강도나 참조별 설명 UI는 다시 추가하지 않는다.
참조 별칭은 삭제 후에도 다른 이미지로 재지정하지 않는다. 전송 시 별칭과 실제 첨부 순서를 함께 기록하며, 남아 있는 잘못된 멘션은 사용자에게 알려 수정하도록 한다. 입력 상한은 선택 Workflow의 지원 개수를 따른다. Persona 전용 16:9·캐릭터 시트 Prompt는 재사용하지 않는다.
프레임과 스토리보드
- Shot과 공통 Creation의 개별 이미지 결과를 영구 연결한다. 배치 결과는 creationId만으로 구분하지 않는다.
- Shot마다 후보 프레임 여러 장을 보관하고, 대표·시작·중간·종료 용도를 선택한다.
- 대표 프레임은 하나만 선택하고, 시작·종료는 선택 사항으로 둔다. 변경은 명시적 사용자 동작으로 처리한다.
- Shot 순서와 Shot 내부 프레임 순서를 분리해 저장한다.
- Scene 스토리보드는 사용자가 포함한 프레임을 Shot 순서대로 표시한다. 대표 프레임을 기본으로 활용한다.
- 생성 중·실패·재시도·빈 결과를 표시하고 새로고침 후에도 결과와 선택 상태를 복원한다.
- Shot 목록·미리보기·상세보기에서 생성 당시 전체 Prompt와 설정을 확인할 수 있게 한다.
프레임 한 장을 추가할 때 새 Shot을 자동 생성하지 않는다. 여러 프레임이 같은 Shot의 진행을 설명할 수 있다. 스토리보드를 위해 별도 필수 승인 계층이나 이전 Shot 완료 gate를 추가하지 않는다.
이력·일관성
요청 시 Shot 정의 버전, Prompt, 참조 별칭·실제 순서·원본 버전, 공통 제작 설정을 Snapshot으로 고정한다. 완료 이벤트가 중복되어도 결과 연결은 한 번만 생성한다. 결과가 늦게 도착해도 현재 대표 프레임을 자동으로 바꾸지 않는다.
Shot 내용이나 참조가 바뀌면 기존 결과를 보존하고 “이전 설정으로 생성됨”을 표시한다. FPS만 바뀐 경우 정지 이미지 자체를 무효로 만들지 않는다. Storyboard 포함 해제와 원본 Creation 삭제는 구분하며, 사용 중인 원본의 보관·삭제 처리는 기존 미디어 보존 정책과 연결한다.
완료 기준
생성한 이미지들을 Shot별로 다시 찾고, 선택·정렬하여 Scene 스토리보드로 볼 수 있다. 새로고침과 중복 완료 이벤트에도 선택 결과가 유지된다. 입력 변경 후에도 과거 결과와 당시 전체 입력을 조회할 수 있다.
8. 3차 — 월드 연동
선택과 저장
- Shot의 “배경 선택”에서 배경 이미지 또는 3D 월드를 선택한다.
- Scene 기본 배경을 두고 Shot은 기본값 사용·개별 선택·배경 미사용을 명시적으로 구분한다.
- World 선택은
worldId뿐 아니라worldRevisionId와 필요한 Artifact를 고정한다. - Scene 기본값 변경은 이를 따르는 Shot의 이후 입력에 반영하고 이전 결과를 표시한다. 개별 선택 Shot과 과거 Snapshot은 바꾸지 않는다.
- 기존 WorldSplatViewer를 활용해 시점 저장·복원·캡처를 구현한다.
- 캡처 결과를 배경 이미지로 저장하고 원본 월드·버전·시점을 다시 열 수 있게 한다.
- 선택한 월드 이미지와 Persona·Coordi·기타 참조를 실제 프레임 생성 입력으로 전달한다.
시점은 위치·회전·시야각·투영·좌표계·적용 변환을 포함해 버전이 있는 계약으로 저장한다. 현재 월드 좌표·스케일 변환을 재사용하며 같은 변환을 두 번 적용하지 않는다. 창 크기와 무관하게 프로젝트 화면비로 프레임 영역을 표시하고 목표 width·height로 캡처한다. 초기에는 자유 형식 렌즈 설명을 별도로 강제하지 않는다.
최소 데이터 관계 — 이름은 구현 시 확정
| 관계 | 최소 저장 내용 |
|---|---|
| Scene 기본 배경 | projectId, sceneId, 이미지 버전 또는 worldRevisionId, 변경 버전 |
| Shot 배경 선택 | shotId, 기본값 사용·개별 선택·미사용, 선택 대상 |
| 저장 시점 | worldRevisionId, Artifact 식별자, 카메라·좌표 변환 Snapshot, 버전 |
| 월드 유래 이미지 | 영구 미디어 식별자, 원본 WorldRevision·시점, 캡처 크기 |
| Shot 프레임 연결 | shotId, 개별 결과 식별자, 용도·순서, 생성 입력 Snapshot |
저장 대상은 영구 식별자와 저장 경로다. 만료되는 presigned URL을 원본 식별자로 저장하지 않는다. 월드·Artifact의 접근 권한과 준비 상태를 서버에서 검증한다. 필요한 Artifact가 없는 PARTIAL 월드는 가능한 미리보기만 제공하고 지원하지 않는 캡처를 완료로 표시하지 않는다.
월드에서 얻은 배경 캡처와 인물·행동까지 반영한 최종 프레임은 별개다. 배경 이미지 없이 월드 ID만 전달한 것을 이미지 모델의 실제 월드 참조로 취급하지 않는다.
확장 경계
3차의 완료 범위는 배경 선택·시점 저장·캡처·프레임 생성 연결이다. 인물·소품의 3D 배치, 카메라 경로와 실제 영상 실행은 후속 확장으로 둔다. 필요한 경우 별도의 Composition 데이터로 추가하며 원본 WorldRevision을 수정하지 않는다.
월드 Provider가 캐릭터 합성이나 카메라 경로 렌더링까지 제공한다고 가정하지 않는다. Motion 실행 연결 시 실제 Workflow의 FPS·길이·시작/종료 이미지 지원을 검증하고, 지원되지 않는 입력을 조용히 생략하거나 출력 설정을 낮추지 않는다.
완료 기준
같은 WorldRevision과 저장 시점으로 동일한 카메라 구도를 복원할 수 있다. 영화 공통 크기의 배경 캡처를 생성 참조로 사용하고, 결과에서 원본 월드와 실제 전송 입력까지 추적할 수 있다. 월드가 갱신되어도 이전 Shot 결과는 바뀌지 않는다.
9. 공통 설정과 Prompt 원칙
- 영화의 화면비·해상도·FPS는 이미 구현된 시나리오 공통 설정을 사용한다. Shot별 재선택 UI를 추가하지 않는다.
- Shot 길이는 독립적으로 조절하되 실행 프레임 수와 실제 길이는 공통 FPS 및 Workflow 지원 조건으로 검증한다.
- 요청 당시 설정 버전을 저장한다. 상세보기에서 현재 프로젝트 설정을 과거 실행 설정처럼 보여주지 않는다.
- Shot 내용, 선택한 프레임 시점, 명시적 참조 역할, 공통 설정을 조합하여 최종 입력을 만든다. 캐릭터 시트 전용 고정 레이아웃은 포함하지 않는다.
- 시점·참조에 따른 실제 이미지 입력과 Prompt의 설명이 일치해야 한다. @ 색상 표시만으로 모델에 매핑이 전달되었다고 간주하지 않는다.
- Frame Prompt와 Motion Prompt는 계속 독립적으로 편집·복사할 수 있다. Motion Prompt 작성에 Frame 생성 완료를 요구하지 않는다.
- 초기 확정 시 Prompt 제안은 기존 흐름을 활용하되, 사소한 편집마다 유료 재생성을 강제하지 않는다. 오래된 상태를 표시하고 사용자가 재생성을 선택한다.
- 실행 입력 확정과 결과 저장은 서버가 검증한다. 동시 수정·늦은 완료 결과가 최신 선택이나 새 Prompt를 덮어쓰지 않게 한다.
10. 구현 순서와 시작 체크리스트
| 순서 | 작업 단위 | 다음 단계로 넘어갈 조건 |
|---|---|---|
| 0 | 에셋 메뉴·배경 내부 분류·기존 경로 연결 | 기존 기능 접근과 링크 호환 검증 |
| 1 | Shot 데이터·DTO·LLM·UI·Prompt 동시 개편 | 카메라 없는 전체 Shot 흐름 검증 |
| 2 | 프레임 결과 연결·선택·스토리보드·입력 이력 | 새로고침·동시 생성·과거 결과 보존 검증 |
| 3 | Scene/Shot 배경 연결·월드 시점·캡처·생성 참조 | 실제 캡처와 최종 요청 입력 연결 검증 |
각 단계 시작 시 해당 코드와 실제 Workflow 계약을 다시 확인한다. 전체 스키마를 0차에 미리 생성하거나 아직 실행되지 않는 컨트롤을 노출하지 않는다.
구현 진입점:
- Frontend:
src/components/navigation/AppSidebar.tsx,src/features/cinema/components/ShotProposalWorkspace.tsx,ShotProposalEditorDialog.tsx,ShotPromptPackagePanel.tsx. - 공통 생성 UI:
src/features/generation/components/references/. - World UI:
src/features/worlds/components/WorldSplatViewer.tsx,worldFirstPersonControls.ts. - Backend:
src/cinema/cinema-shot-proposals.service.ts, Shot·Proposal Entity/DTO,src/cinema/llm/,cinema-shot-prompt-packages.service.ts. - 공통 설정:
src/cinema/production-settings/. - World 계약:
src/worlds/entities/,worlds.types.ts,providers/world-model-provider.interface.ts. - 프로젝트 에셋:
src/cinema/cinema-project-assets.service.ts및 현재 AssetVersion 계약.
0~3차 구현은 아래 범위로 분리 커밋했다. 체크박스는 로컬 코드 구현 상태이며, 운영 배포나 모든 워크플로우의 생성 품질 검증을 뜻하지 않는다.
11. 검증과 비범위
주요 검증은 메뉴 접근·기존 링크·카메라 없는 Shot 승인·참조 번호 유지·배치 결과 식별·재시도 멱등성·저장 시점 복원·출력 크기·버전 보존이다. UI만 바꾼 뒤 API·LLM의 구형 필수값을 남기는 부분 전환을 허용하지 않는다.
정적 검사와 영향 범위의 테스트를 우선한다. 사용자 dev server를 임의 재시작하거나 다른 포트를 열지 않는다. 실제 생성 테스트는 저장·매핑 검증과 구분해 결과를 기록한다.
이번 계획은 편집 타임라인·최종 영화 Export, 범용 의존성 그래프 UI, Blender 동기화, 자동 카메라 경로 설계, 3D 캐릭터 리깅, 기존 에셋 일괄 재생성을 포함하지 않는다.
관련 기준: Cinema 개요, 에셋과 연속성, Worlds, 기존 결정 기록.
12. 2026-09-08 구현 기록
단계별 커밋
각 저장소의 surfai-init 브랜치 기준이며 원격 push·운영 배포는 수행하지 않았다.
| 범위 | Frontend | Backend |
|---|---|---|
| 0차 에셋 메뉴·기존 경로 유지 | 2ccf24aa | 데이터 마이그레이션 없음 |
| 1차 서사 중심 Shot 설계 | 967cd830 | 1137294 |
| 2차 프레임 선택·스토리보드·참조 Prompt | daa52abe | c29ff25 |
| 배경 업로드 Snapshot 누락 수정 | 해당 없음 | 5957142 |
| 3차 배경 상속·월드 캡처·에셋 버전 참조 | 69564da7 | 369632c |
저장 계약과 화면
/assets는/personas로 연결한다. 코디와 배경 이미지는 기존/styling에category=coordi|background, 월드는 기존/worlds를 사용한다. 상세styleId를 유지하고 닫을 때 해당 카테고리로 돌아간다.- 메뉴 통합으로 Persona·Coordi·Lookbook·World 데이터를 이동하거나 지우지 않았다. 목록이 비어 보였던 사례는
jaytsol과surfai-admin의 소유 데이터 차이였으며 관리자 계정에서 기존 목록을 확인했다. - Shot/Proposal의
startState,action,endState,continuityNotes를 추가했다. 기존 카메라 필드는 이력으로 보존하되 새 설계의 필수 입력과 LLM 자동 지정에서 제외했다. 과거에 생성한 Prompt는 자동으로 다시 쓰지 않는다. - 개별
CreationResult.id를CinemaShot.frameSelections에 용도·포함 여부·순서와 함께 저장한다.frameSelectionVersion으로 동시 변경을 검사한다. 선택 중인 프레임은 공통 생성 이력에서 원본 삭제를 막고 먼저 선택 해제하도록 안내한다. - Prompt Package에 참조 목록과
lastReferenceId,editVersion을 저장한다. 삭제된 참조 번호는 재사용하지 않는다. 누락된 멘션은 생성 전에 오류로 알리고, 실제 입력 순서로 확장한 전체 Prompt와 참조 매핑을 생성 Snapshot에 저장한다. - 참조 UI는 기본 숨김, + 토글, 썸네일 상세보기·삭제, @ 목록을 재사용한다. 프로젝트에 연결된 페르소나·코디도 추가할 수 있고 해당
AssetVersion.id를 함께 보존한다. 참조 강도·참조별 설명 입력은 추가하지 않았다. - Scene의 기본 배경은
NONE, Shot의 기본 선택은INHERIT다.IMAGE는 배경의 결과 ID,WORLD는 고정 WorldRevision과 캡처 결과 ID를 저장한다. Scene과 Shot에 각각 변경 버전을 둔다. environmentGET/PATCH와environment/capturesPOST는/v1/cinema/projects/:projectId/scenes/:sceneId/shots/:shotId아래에 있다. 서버에서 프로젝트·Shot·월드·배경 소유권, 이미지 준비 상태, 변경 버전, 캡처 크기를 확인한다.- 캡처 시 위치·방향·up 벡터·FOV·좌표계, WorldRevision·Artifact, 공간 변환, width·height를
worldCapture에 기록한다. 캡처 이미지는 배경 라이브러리에 등록되고 월드 유래 이미지를 선택하면 저장 시점을 다시 열 수 있다. - 월드에서 캡처한 실제 이미지를
배경별칭으로 첫 입력에 넣고 이후 참조를 순서대로 연결한다. 월드 ID만으로 이미지 참조를 대신하지 않는다. - 프레임의 생성 당시 Shot 정의 버전·전체 Prompt·참조 버전·공통 제작 설정·배경 선택을 보존한다. 현재 입력과 다른 결과는 이전 설정으로 표시하며 FPS만 바뀐 경우 정지 이미지의 변경 사유로 삼지 않는다.
검증 결과와 남은 수동 확인
- Frontend TypeScript 검사와 수정 범위 ESLint 통과. Backend는 테스트 파일을 제외한
tsconfig.build.json타입 검사 통과. - 관련 Jest 11개 suite, 39개 테스트 통과: 카메라 없는 Shot DTO, 기존 분석·승인 경로, 참조 번호 공백과 실제 입력 순서, 미등록 참조 차단, 프레임 소유권·단일 대표·순서·동시 저장, 공통 설정, 카메라 벡터와 캡처 크기·출처, 배경 업로드 필수 Snapshot 필드.
- 2차는 스테이징 내용만 별도 임시 디렉터리에 펼쳐 두 저장소 타입 검사와 관련 테스트 12개를 통과시켰다. 이후 월드 파일을 요구하는 불완전한 커밋이 되지 않도록 확인했다.
- 브라우저에서 기존 페르소나·배경 이미지·월드 목록, 기존 영화의 시퀀스·Scene·Shot, 참조 토글, 프로젝트 페르소나 추가, @ 삽입, 참조 삭제, 실제 Prompt 저장을 확인했다.
- 실제 월드 뷰어에서 배경을 캡처·등록했고 브라우저 이미지의 원본 크기가
1920×1080임을 확인했다. 저장 시점 다시 열기 후 테스트 Shot은 원래INHERIT선택으로 복원했다. 검증 중 만든 배경 캡처 한 장은 배경 라이브러리에 남아 있다. - 유료 LLM/이미지/비디오 생성은 실행하지 않았다. 새 모델의 Shot 설계 품질과 최종 생성 이미지에서의 참조 반영은 다음 실제 생성 테스트로 확인해야 한다. 비디오 실행·3D 인물 배치·카메라 경로는 원래 계획대로 후속 범위다.
- 모든 모바일 크기, 모든 기존 공유 링크 조합과 대량 결과 목록의 수동 회귀 검증은 별도 확인이 필요하다. 전체 Backend 테스트 소스까지 포함하는 기본 tsc에는 기존 테스트 파일 타입 오류가 있어 런타임 소스 검사와 관련 Jest 실행 결과를 구분했다.