---
name: showreel
description: 한국어 모션그래픽 영상(쇼릴·홍보 영상·프로필 영상·티저·브랜드 필름·행사 홍보·제품 소개·교육 영상·메이킹 필름)을 기획 브리프부터 납품까지 만드는 스킬. 사용자에게 주제·분위기·길이(15초·30초·60초·100초·5분)·이미지 생성 여부·나레이션 여부를 물어 방향을 정한 뒤, 조사 → 원고 → ElevenLabs 나레이션(기본 Marcus 바리톤) → 음악·효과음 → codex-image 이미지 → HTML 모션 엔진 렌더 → 믹스 → 자동 검수까지 끝낸다. '쇼릴', '모션그래픽', '애니메이션 영상 만들어줘', '홍보 영상', '소개 영상', '인물 소개 영상', '1분 영상', 'N초 영상', '이력서용 쇼릴', '놀라운 모션 그래픽 디자이너', '전력을 다해요', '키네틱 타이포', '나레이션 넣은 영상', '티저 영상', '하네스가 어떻게 동작하는지 영상으로' 같은 요청이면 영상이라는 말이 없어도 이 스킬을 쓴다. 실사 촬영본 컷 편집, 파일 자르기·변환만 하는 작업, Sora·Veo 같은 생성형 비디오 모델 호출, 슬라이드·PDF만 만드는 작업은 범위가 아니다.
---

# 쇼릴 모션그래픽 영상 제작

목표는 "AI가 만든 슬라이드 동영상"이 아니라 이력서에 붙일 만한 모션 디자이너의 쇼릴이다. 첫 3초에 강한 시각 사건을 두고, 한 화면에 메시지 하나만 전하고, 화면의 변화를 나레이션 단어와 음악 히트에 프레임 단위로 맞춘다.

이 스킬은 실제 제작 13건(인물 프로필·기업 홍보·행사·교육·티저·음악 기반 등)에서 쓴 방법과 그때 겪은 문제의 해결책을 스크립트와 문서로 정리한 것이다. 같은 실수를 반복하지 않도록 각 단계의 스크립트를 그대로 쓴다.

## 기본값

사용자가 정하지 않은 항목은 아래 값으로 진행한다. 사용자가 바꾸면 그 값을 따른다.

| 항목 | 기본값 |
| --- | --- |
| 길이·규격 | 60초, 16:9 1920×1080, 30fps |
| 분위기 | 웅장한 시네마틱(어두운 배경, 따뜻한 흰 글자, 금색 강조, 레터박스·필름 그레인) |
| 나레이션 | ElevenLabs Marcus `ibCGc01503OQd2R6i1n1`(깊은 바리톤 한국어), `eleven_multilingual_v2`, stability 0.45 · similarity 0.8 · style 0.4 |
| 음악 | ElevenLabs Music(유료 플랜). 쓸 수 없으면 `synth_music.py` 합성 음악 |
| 이미지 | 필요한 장면만 codex-image로 생성. 실존 인물의 얼굴은 생성하지 않고 실제 사진만 쓴다 |
| 산출물 | 마스터 MP4, 공유용 MP4, 포스터 JPG, 자막 SRT, 제작노트 |
| 음량 | -14 LUFS, true peak -1.5 dBTP |

## 작업 위치

모든 작업 파일은 프로젝트 폴더 아래에 만든다. `/tmp`, `/private/tmp`, 세션 scratchpad에는 아무것도 저장하지 않는다. 세션이 끝나면 임시 폴더는 지워지고, 재생성 명령·검수 시트·생성 이미지·나레이션 테이크를 다시 쓸 수 없게 된다. 검수용 스틸과 시트는 `<프로젝트>/qa/`, 중간 렌더는 `<프로젝트>/out/`에 둔다.

프로젝트 폴더는 브리프에서 정한다. 사용자가 지정하지 않으면 현재 작업 폴더 아래에 영문 소문자 이름(`./<주제-slug>/`)으로 만든다.

## 진행 방식

사용자 확인은 **1단계 기획 브리프에서 한 번만** 받는다. 브리프가 확정되면 질문하지 않고 납품까지 진행한다. 진행 중 판단이 필요한 일(보이스가 막힘, 음악 API 불가, 사실 확인이 안 되는 내용)은 아래 대체 경로로 처리하고 납품 보고에 적는다. 사용자가 "묻지 말고 바로"라고 하면 브리프도 기본값으로 채워 요약만 보여 주고 진행한다.

```
0 환경 점검 → 1 기획 브리프(사용자 확인) → 2 조사·자료 → 3 스토리보드·원고
→ 4 오디오 먼저(나레이션·음악·효과음 → 타임라인) → 5 이미지 → 6 장면 제작(스타일 프레임 먼저)
→ 7 초안 렌더·검수 반복 → 8 최종 렌더·믹스·마감 → 9 자동 검수·납품 보고
```

오래 걸리는 작업(조사, TTS, 음악 생성, 이미지 생성, 최종 렌더)은 Bash `run_in_background`나 서브에이전트로 돌리고 그동안 다음 단계를 진행한다. `sleep`으로 기다리지 않는다. 완료 알림을 받으면 이어 간다.

스크립트 경로는 이 스킬 폴더 기준이다(`~/.claude/skills/showreel/scripts/`). 아래에서 `S=~/.claude/skills/showreel/scripts`로 줄여 쓴다.

## 0. 환경 점검

```bash
python3 $S/preflight.py
```

결과의 "쓸 수 있는 경로"를 브리프에 반영한다.

- **codex CLI나 이미지 스킬이 없을 때**: codex-image·photoreal·codex-cli 스킬은 https://github.com/revfactory/skills 에 있다. 출력된 설치 명령을 사용자에게 안내한다. 설치하지 않겠다면 타이포·그래픽·사용자 제공 사진으로 구성한다. 사용자가 "realphoto"라고 부르는 스킬의 실제 이름은 `photoreal`이다.
- **ElevenLabs 키가 없을 때**: 나레이션을 원하면 `preflight.py`가 출력하는 키 발급 절차를 그대로 안내한다. 키를 받기 전까지는 음악·자막 버전으로 진행할 수 있다고 함께 알린다.
- **기본 보이스가 막힐 때**(Free 플랜은 라이브러리 보이스를 쓸 수 없다): `python3 $S/eleven.py voices --lang ko`로 쓸 수 있는 보이스를 고르거나 플랜 업그레이드를 안내한다.

## 1. 기획 브리프 (사용자 확인)

`references/brief.md`를 읽고 질문한다. 요청에 이미 있는 항목은 다시 묻지 않는다. AskUserQuestion은 한 번에 질문 네 개까지라서 최대 두 번 묻는다.

확인할 항목:

- 주제와 목적: 누구·무엇을, 누구에게 보여 줄 영상인가
- 분위기·테마
- 길이와 화면비
- 이미지: AI 생성 / 실제 사진·자료 / 둘 다 / 타이포·그래픽만
- 나레이션 유무와 보이스
- 꼭 들어갈 정보: 이름·직함·날짜·장소·URL·CTA
- 자료 위치: 사진 폴더, 로고, 참고 URL

답을 받으면 `<프로젝트>/brief.md`를 쓰고, 요약(장면 구성안 한 줄, 길이, 무드, 보이스, 예상 시간·크레딧)을 보여 준 뒤 **이대로 진행할지 한 번 확인**한다.

## 2. 조사와 자료

먼저 프로젝트를 만든다. 폴더 구조, 엔진 템플릿, 한글 폰트, 렌더러 의존성이 한 번에 준비된다.

```bash
python3 $S/new_project.py <프로젝트> --ratio 16:9 --duration 60
```

인물·기업·행사·제품이 주제면 조사를 서브에이전트에 백그라운드로 맡긴다. 프롬프트 형식은 `references/brief.md`의 "조사 요청"에 있다.

- 결과는 `research/research.md`에 남긴다. 사실마다 출처 URL과 확실도(확인/단일 출처/미확인)를 적는다.
- 영상에 넣는 숫자와 사실은 출처가 있는 것만 쓴다. 사용자가 준 정보가 조사 결과와 다르면 조사 결과를 따르고, 납품 보고의 "요청과 다르게 반영한 것"에 적는다.
- 실제 사진은 사용자 제공 자료, 공식 사이트, 보도 사진에서 고른다. 출처를 `research/photos.md`에 적는다. 보도 사진은 납품 보고에서 "공개 전 사용 허락 확인 필요"로 표시한다.
- 브랜드 색은 공식 사이트 CSS나 로고에서 뽑는다. 로고는 그 회사의 영상일 때만 공식 파일을 쓰고, 다른 회사 로고는 그리지 않는다.

## 3. 스토리보드와 나레이션 원고

`references/story.md`를 읽는다. 용도별 구성 표, 길이별 나레이션 분량, 카피 규칙, 발음 표기 규칙이 있다.

- `storyboard.md`: 장면 표(시간·화면 카피·나레이션·화면 설계·전환·효과음·출처)
- `script.json`: 나레이션 줄, 효과음, 음악. 형식은 `narrate.py` 맨 위 설명을 따른다.
  - 화면 표기(`text`)와 발음 표기(`tts`)를 나눠 쓴다. 숫자·연도·약어·영문은 한글로 읽히게 적는다.
  - 장면 전환과 맞출 단어는 `cues`로 이름을 붙인다.
- 나레이션 분량은 60초에 240~255자(공백·문장부호 제외)다. 처음부터 이 범위로 쓴다. 넘치면 화면이 나레이션을 따라가지 못한다.
- **나레이션이 없는 영상**도 `script.json`을 쓴다: `"lines": []`로 두고 `scenes`·`sfx`·`music`만 채운다. `narrate.py`는 건너뛰고 `timeline.py`부터 실행한다. 자막(SRT)은 나오지 않는다.
- 날짜가 나오면 요일을 달력으로 대조한다(`python3 -c "import datetime;print(datetime.date(2026,11,20).strftime('%A'))"`). 요청한 날짜와 요일이 맞지 않은 사례가 있었다. 맞지 않으면 요일을 빼고 보고에 적는다.

## 4. 오디오를 먼저 만든다

화면의 시각은 나레이션 단어와 음악 히트에서 정해지므로 오디오를 먼저 확정한다. 자세한 기준은 `references/audio.md`에 있다.

```bash
python3 $S/narrate.py <프로젝트>/script.json --stt            # 나레이션 + 발음 검증. ✗ 줄은 고쳐서 다시
python3 $S/music_tools.py plan <프로젝트>/audio/music/spec.json # 음악 스펙 → ElevenLabs 구성 플랜
python3 $S/eleven.py music <프로젝트>/audio/music/music.mp3 --plan <프로젝트>/audio/music/plan.json
#   402(유료 플랜 필요)면: python3 $S/synth_music.py music <프로젝트>/audio/music/spec.json <프로젝트>/audio/music/music.wav
python3 $S/music_tools.py analyze <프로젝트>/audio/music/music.mp3   # 템포·히트 → 장면 경계를 히트에 맞춘다
python3 $S/eleven.py sfx-kit <프로젝트>/audio/sfx --names impact,whoosh,riser,logo_hit   # 또는 synth_music.py sfx
python3 $S/timeline.py <프로젝트>/script.json --music-analysis audio/music/analysis.json
```

- 음악 섹션은 4마디 단위로 잡는다(120 BPM이면 8초). ElevenLabs Music은 그 단위로 곡을 만들기 때문에, 드롭이 원하는 시각보다 늦게 나오면 `music_tools.py splice`로 빌드업 끝 몇 박 뒤에 드롭 구간을 이어 붙여 당긴다.

`timeline.py`가 `timeline.json`(믹서·검수용)과 `reel/timeline.js`(화면용 큐·단어 시각·소리 크기 곡선)를 만든다. 겹침·길이 초과·큐 누락이 있으면 ✗로 알려 주므로, 모두 고친 뒤 장면을 만든다. 나레이션 문구나 시각을 바꿀 때는 `script.json`만 고치고 `narrate.py`(바뀐 줄만 다시 생성)와 `timeline.py`를 다시 실행한다.

## 5. 이미지

`references/images.md`를 읽는다.

- 생성: `~/.claude/skills/codex-image/scripts/codex_imagegen_batch.sh <프로젝트>/assets/gen "프롬프트::이름.png" …` (5장씩 병렬, 장당 약 1분)
- 사람이 나오는 사진풍 이미지: `photoreal` 스킬로 프롬프트를 만든다.
- 실제 대상을 닮게 만들 때: `$S/codex_ref_image.sh`로 참조 사진을 붙인다.
- 후처리: `python3 $S/prep_images.py <프로젝트>/assets/gen --out <프로젝트>/assets/img [--cutout]`. 레터박스 제거, 확대, 누끼를 한다.
- 확인: `prep_images.py --sheet`로 시트를 만들어 Read로 본다. 손가락·글자·로고가 섞인 이미지는 다시 만든다.

## 6. 장면 제작

`references/engine.md`(엔진 API·장면 작성법·기법 코드)와 `references/design.md`(무드 프리셋·한글 타이포·모션 규칙)를 읽고 `reel/scenes.js`를 쓴다. 장면마다 다른 표현을 쓰려면 `references/techniques.md`(아이소메트릭 도시, 한글 자모 조립, 가변 굵기 물결, 유리 활자, 비트 그리드, 데이터 맥박, 3D 기기 UI, 입자 글자, 매치 컷 등 22종)에서 고른다. 같은 기법만 반복하면 쇼릴이 단조로워진다.

- 엔진 규칙: 화면은 시간 t의 순수 함수다. `Math.random`, `Date.now`, CSS transition·animation, 이전 프레임 상태에 기대는 코드를 쓰지 않는다. 렌더러가 임의 시각으로 이동하고 여러 워커가 나눠 그리기 때문이다.
- 시각은 숫자를 직접 쓰지 말고 `REEL.cue('이름')`로 타임라인 큐를 쓴다. 그래야 나레이션을 다시 만들어도 화면이 따라온다.
- 하드 컷·상태 전환은 큐보다 0.5프레임 앞에 둔다(`cue(x) - 0.5/fps`). 모션 블러 셔터가 프레임 앞뒤에 걸쳐 있어, 그래야 큐 프레임에 새 상태가 정확히 보인다.
- 0초 프레임부터 화면이 차 있고 움직여야 한다. 페이드 인으로 시작하지 않는다.
- 색은 무드 프리셋보다 주제의 브랜드 색(공식 사이트 CSS·로고)을 우선한다. 프리셋은 브랜드 색이 없을 때의 기본값이다.
- **역동성은 설계 단계에서 넣는다**(`design.md`의 "역동성 규칙"). 스킬 없이 만든 영상과 비교했을 때 이 스킬의 결과가 덜 역동적으로 보인 원인은 다섯 가지였다.
  - 한 구도를 4~8초씩 두었다. 정보 구간은 0.5~1박마다 새 사건을 넣고, 구도는 2마디 안에 바꾼다. 장면 경계는 `REEL.bar(n)`으로 마디에 놓는다.
  - 큰 타격이 컷 하나로 끝났다. 큰 히트마다 `FX.impact` + `FX.camera` 흔들림 + 1.3배·흐림에서 착지하는 글자를 함께 쓴다.
  - 퇴장이 투명도 페이드였다. `REEL.inout`으로 위로 밀리며 줄고 흐려지게 한다.
  - 검은 배경 위 글자만 있었다. `REEL.config({ push: 0.03 })`, `FX.floor`, `FX.dust`로 장면 뒤를 늘 움직인다.
  - 전환이 대부분 컷이었다. `FX.camera({ whips })`, `FX.wipe`로 화면 전체가 움직이는 전환을 섞는다.
- **스타일 프레임 먼저**: 대표 장면 2~3개를 만들고 스틸 시트로 확인한 뒤 나머지를 만든다.
- 3분 넘는 영상은 챕터마다 `scenes_chNN.js`로 나누고, 서브에이전트에 챕터를 나눠 맡길 수 있다(`references/engine.md`의 "긴 영상").

## 7. 초안 렌더와 검수 반복

```bash
node $S/render.mjs --dir <프로젝트>/reel --every 0.5 --outdir <프로젝트>/qa/stills     # 스틸(장면 하나를 만들 때마다)
python3 $S/contact_sheet.py --dir <프로젝트>/qa/stills --out <프로젝트>/qa/sheet_stills.png --timeline <프로젝트>/timeline.json
node $S/render.mjs --dir <프로젝트>/reel --out <프로젝트>/out/draft.mp4 --scale 0.5          # 초안(60초에 약 30초)
python3 $S/contact_sheet.py --video <프로젝트>/out/draft.mp4 --every 1 --out <프로젝트>/qa/sheet_draft.png
python3 $S/motion_check.py <프로젝트>/out/draft.mp4 --timeline <프로젝트>/timeline.json   # 멈춘 구간·큰 움직임 부족을 시각과 함께 알려 준다
python3 $S/contact_sheet.py --video <프로젝트>/out/draft.mp4 --around <장면 경계 초들> --frames 3 --out <프로젝트>/qa/sheet_cuts.png
```

`motion_check.py`가 △를 내면 그 시각의 장면에 사건을 더하고 다시 초안을 뽑는다(기준: 20초 이하 멈춘 화면 8%·큰 움직임 15, 60초 이하 20%·7, 그보다 길면 35%·6). 만든 시트는 **반드시 Read로 열어 직접 본다.** 렌더한 프레임을 보지 않고 완료라고 하지 않는다. `references/qa.md`의 점검표로 고치고 2~3회 반복한다. 렌더러가 종료 코드 2로 끝나면 페이지 오류가 난 것이니 로그의 오류부터 고친다.

## 8. 최종 렌더·믹스·마감

```bash
node $S/render.mjs --dir <프로젝트>/reel --out <프로젝트>/out/video.mp4 --sub 4 --format png   # 모션 블러. 60초에 약 3~5분, 백그라운드로
python3 $S/mix.py <프로젝트>/timeline.json                  # 나레이션은 리버브 없이 둔다(웅장한 톤도 마찬가지)
python3 $S/finish.py --video <프로젝트>/out/video.mp4 --audio <프로젝트>/audio/mix.wav \
  --name "<제목>_<길이>s" --outdir <프로젝트>/out --timeline <프로젝트>/timeline.json
```

나레이션에 리버브를 넣지 않는다. 웅장한 느낌은 음악·효과음이 맡는다. 2.4초 홀을 `--hall 0.12`로 걸었던 영상에서 "나레이션에 에코가 너무 많다"는 지적을 받았다. 공간감이 꼭 필요할 때만 `--hall 0.04~0.08`을 쓰고, `mix.py`가 출력하는 "말 끝 잔향"가 ✓(-32dB 이하)인지 확인한다.

`mix.py`가 줄마다 "나레이션 대 배경" dB를 보여 준다. ✗(6dB 미만)인 줄은 근처 효과음을 줄이거나 핵심 단어에서 0.2~0.3초 비켜 놓고 다시 믹스한다. 오디오만 고칠 때는 영상을 다시 렌더하지 않고 `mix.py`와 `finish.py`만 다시 돌린다.

## 9. 자동 검수와 납품 보고

```bash
python3 $S/qa_check.py <프로젝트>/out/<이름>.mp4 --timeline <프로젝트>/timeline.json --script <프로젝트>/script.json --stt
```

규격, 음량, 너무 어두운 구간, 섬광, 멈춘 화면, 완성 믹스의 받아쓰기(숫자 오인식 포함)를 검사하고 `qa/qa_report.md`와 최종 시트를 만든다. "고칠 것"을 모두 처리하고 최종 시트를 Read로 본 뒤 납품한다. STT에서 한 번만 틀린 줄은 한 번 더 돌려 두 번 다 틀릴 때 고친다.

납품 보고와 `제작노트.md` 형식은 `references/qa.md`의 "납품"에 있다. 다음을 반드시 넣는다.

- 산출물의 **절대 경로 표**
- 장면 구성표
- 요청과 다르게 반영한 것
- 공개 전 확인할 것: 사진 사용 허락, 단일 출처 사실, 시점이 지나면 틀리는 정보, AI 생성 인물이 가상이라는 점
- 재생성 명령
- 사운드를 직접 들어 봐 달라는 요청. Claude는 소리를 들을 수 없고 수치로만 확인했다.

## 지킬 것

- 역동성: 같은 구도를 2마디 넘게 두지 않고, 퇴장도 움직임으로 처리하고, 장면 뒤에 움직이는 면을 깐다. 큰 타격은 `FX.impact`와 흔들림을 함께 쓴다. 규칙과 도구는 `design.md`의 "역동성 규칙"에 있고, 초안마다 `motion_check.py`로 확인한다.
- 실존 인물의 얼굴·몸은 이미지로 생성하지 않는다. 생성 이미지는 얼굴이 보이지 않는 환경·사물·뒷모습 컷으로 쓴다.
- 영상의 숫자·직함·연도는 조사 출처가 있는 것만 쓴다. 연출용 가상 수치를 쓰면 화면이나 보고에 그렇다고 밝힌다.
- 음악 프롬프트에 아티스트·작곡가·곡 이름을 넣지 않는다. 저작권 필터에 걸려 400으로 거부된다.
- ElevenLabs 크레딧을 아낀다. 바뀐 줄만 다시 만들고, `takes`는 고유명사·숫자 줄에만 쓴다.
- 섬광은 어두운 배경에서 opacity 0.15 이하로 쓰고, 1초에 3번을 넘기지 않는다(광과민성).

## 자주 생기는 문제

| 증상 | 조치 |
| --- | --- |
| 나레이션이 목표 길이를 넘김 | 원고를 줄인다(60초 = 220~255자, 짧은 줄이 많으면 더 적게). 그래도 넘치면 speed 1.05까지만 올린다 |
| 영상이 멈춰 보이거나 밋밋함 | `motion_check.py`가 알려 준 시각에 사건을 더한다. 장면 뒤 `FX.floor`·`FX.dust`, 큰 히트에 `FX.impact`+흔들림, 퇴장은 `inout`, 컷 대신 휩·와이프 |
| 이름·숫자를 잘못 읽음(이훈희→이후니, 2026→2025) | 발음 표기 수정 → 쉼표로 끊기("이공, 이육") → `takes` 3~5 → 모델 `eleven_v3`로 그 줄만 교체 |
| 나레이션에 에코·울림이 많음 | `--hall` 없이 `mix.py`와 `finish.py`만 다시 돌린다(영상 재렌더 불필요). 리버브를 남길 때는 `mix.py`의 "말 끝 잔향"가 ✓일 때까지 `--hall`을 낮춘다 |
| 완성 믹스에서 말이 묻힘 | 타격음을 핵심 단어에서 0.2~0.3초 비키기, 해당 줄 `gain_db` +2~3, `--duck` 0.8 |
| 오류 JSON이 mp3로 저장됨 | `eleven.py`가 막는다. 직접 curl을 쓰지 말고 스크립트를 쓴다 |
| Python에서 ElevenLabs 호출 시 SSL 오류 | 검증을 끄지 않는다. `eleven.py`는 curl을 쓰므로 이 문제가 없다 |
| 화면 글꼴이 기본 고딕으로 나옴 | 렌더 로그의 "폰트" 줄 확인, `reel/fonts/fonts.css`에 그 굵기가 있는지 확인 |
| 장면 경계에서 빈 화면·잔상 | `contact_sheet.py --around`로 ±3프레임을 보고 퇴장을 컷 0.1초 전에 끝낸다 |
| 음악이 플랜의 섹션 길이와 다름 | 정상이다(대개 4마디 단위로 생성됨). `music_tools.py analyze`로 히트를 읽고 장면 경계를 히트에 맞추거나, `splice`로 드롭을 원하는 시각에 옮긴다 |
| 세로(9:16) 영상의 HUD·자막이 앱 UI에 가림 | `fx.js`가 세로 영상이면 위 250px·아래 420px을 자동으로 피한다. 직접 그린 요소도 이 영역을 비운다 |
| 영상이 yuvj420p·풀레인지로 나옴 | `render.mjs`와 `finish.py`를 거치면 yuv420p·tv로 나온다. 다른 도구로 인코딩하지 않는다 |

## 참조

| 파일 | 언제 읽나 |
| --- | --- |
| `references/brief.md` | 1단계: 질문 세트, 브리프 양식, 조사 요청 프롬프트, 시간·크레딧 추정 |
| `references/story.md` | 3단계: 용도·길이별 구성, 나레이션 분량, 카피·발음 표기 규칙, 원고 양식 |
| `references/audio.md` | 4·8단계: 보이스·모델·설정, ElevenLabs 키·플랜, 음악·효과음, 믹스 기준 |
| `references/images.md` | 5단계: 이미지 생성·실사 사진·누끼·후처리 |
| `references/design.md` | 6단계: 무드 프리셋, 한글 타이포, 모션·전환 규칙, 레이아웃 |
| `references/engine.md` | 6단계: 엔진 API, 장면 작성법, 기법별 코드, 긴 영상 분업 |
| `references/techniques.md` | 6단계: 표현 기법 카탈로그 22종(코드 포함)과 싱크·첫 프레임·섬광·결정성 규칙 |
| `references/qa.md` | 7·9단계: 검수 점검표, 시트 읽는 법, 납품 보고·제작노트 양식 |
