Remotion 구술 패키징 디자인 시스템 (v1 hub)
스타일 목표: 기준 영상의 구술 HUD 패키징 재현 (참고 이미지 프로젝트 refs/). 이 파일은 하드 컨스트레인트 허브입니다: 불문율 + 토큰 의미론 + 컴포넌트 요약 + 오답 노트; 세부 규칙은 references/에 있습니다 (2026-07-16 77개 차이점 심층 비교 결과 정착). 이 체계에 없는 시각적 결정은, 해당 섹션 파일에 먼저 보충한 후 코드를 작성하세요.
섹션 라우팅 테이블 (무엇을 할지 해당 파일을 읽으세요)
| 섹션 | 파일 | 담당 내용 |
|---|---|---|
| 스펙 테이블 (먼저 확인 후 코드 작성) | references/specs.md | 기준 영상 측정 진리값: 카드 너비/폰트 크기/위치/모션 프레임 수 조립 전 필수 확인, 테이블에 없으면 직접 측정하여 추가, 육안 추정 금지 |
| 레이아웃 구성 | references/layout.md | 3구역, 테이크오버 메커니즘 (A급은 PiP 없음, 어둡게 슬로우모션은 이미 기각), 한 화면 한 중심, 그룹핑 템플릿, 끼워맞춤 위치 |
| 타이포그래피 | references/typography.md | 유일한 최대 폰트, h1 의무, hero 샌드위치, SideLabel title 변형 |
| 색상 & 질감 | references/texture.md | 젤리 블록/글로우, SURFACE 밝음/어두움 변형, 스탬프 사양 유일선, 동일 화면 색상 계열 ≤2, 밝은 배경 텍스트 직접 사용 금지 세부 규칙 |
| 모션 | references/motion.md | useEnter/useExit 사용, 비트 분할, 빌드업, 서비스 구간, Breathe, 빈 화면 |
| 정보 디자인 | references/infographic.md | 차트 옵션, 비유적 그래픽, 와플, 큰 숫자 3단 구조, 마이크로 그래픽 어휘 |
| 내러티브/리듬/자막/소스/오디오 | remotion-assembly의 references/ | narrative / rhythm / subtitle / broll / audio |
| 오답 노트 (증상 → 수정법 인덱스) | 독립 스킬 remotion-gotchas-index | 전체 문서에서 '오답 #NN'의 수정 위치를 여기서 조회; 렌더링 이상/화면 불일치 시 먼저 확인 |
엔지니어링 베이스 목록 (substrate — 콜드 스타트 / 새 영상 시작 전에 먼저 확인)
이 디자인 시스템은 전체 저장소 공유 베이스이며, 각 영상마다 재구축하지 않습니다. 다음 파일들은 전체 프로세스(assembly '입력 검수→프레임 출력→3중 게이트' + motion §12 게이트) 실행의 전제 조건입니다; 새 영상은 기본적으로 이를 재사용하며, 자신의 composition + 자막 + Scene만 추가하고 베이스를 다시 만들지 않습니다. 콜드 스타트 독자(src/ 읽기 금지)는 종종 여기서 실패합니다 — 이 테이블을 따라 파일이 있는지 확인하고, 구체적인 값을 원하면 해당 파일을 열어 읽으십시오. 스킬이 값을 전달해 주기를 기대하지 마세요.
| 베이스 파일 | 내용물 | 콜드 스타트 사용법 |
|---|---|---|
src/design/tokens.ts | 수치 유일 진리값: COLOR (4가지 의미론적 색상 + 기본색 hex), SURFACE, FONT, GRADIENT, SIZE 계단 (kicker…mega), GRID, RADIUS, SAFE, MOTION 프레임 수 | SIZE.mega, 의미론적 색상 hex 등 구체적인 픽셀/색상은 이 파일에서 직접 가져오세요 — 스킬은 일부러 복사하지 않습니다 (스냅샷과 코드 불일치 방지, §1 참조); 파일이 없음 = 베이스 누락, 먼저 생성 |
src/design/*.tsx | 컴포넌트 라이브러리 (§3 전체 표: SideLabel/HeroText/Chip…) + FontGuard.tsx (폰트 문지기, 오답 #01) + qc.tsx (QC 프로브 QcProbe: 프레임별 [data-qc] 박스 판독하여 겹침 검사, 오답 #29) | 패키징 요소 작성 전 §3 컴포넌트 표에서 파일 위치 확인 |
src/design/motion.ts | useEnter/useExit/usePop 하위 훅 + MOTION 상수 | motion.md 규칙이 참조하는 훅은 모두 여기에 있음 |
src/design/fonts.ts | @fontsource 로컬 폰트 등록 (오답 #01: 웹폰트는 네트워크를 통해 가져올 경우 자동으로 명조체로 폴백) | package.json sideEffects에 반드시 포함 |
src/koubo/scenes/shared.tsx | 조립 레이어 게이트 4종 세트 Enter/DimAfter/Exit/ClearOut (motion §12) + Place 위치 박스 + qcAllow QC 끼워맞춤 화이트리스트 (assembly §2.5 게이트 ①) | 어셈블리 Scene 작성 시 이러한 래퍼를 직접 사용, opacity를 수동 조작하지 않음 |
src/Root.tsx | composition 등록 위치 (기존 <Composition id="Koubo-0715-01" fps={30} …/>) | 새 영상은 여기에 <Composition> 하나를 추가, id는 자유롭게 지정; 단편 렌더링 스크립트는 이 id와 일치해야 함 (assembly §6 render-service id 변경 참조) |
src/koubo/ | 각 영상 전용: subtitles-<영상명>.ts / SubtitleTrack.tsx / <영상명 메인 컴포넌트>.tsx / scenes/SceneNN.tsx | 새 영상은 이 레이어에만 파일을 추가 (구조는 assembly §4 참조) |
진정한 처음부터 부트스트랩 (src/가 완전히 비어 있음): 베이스가 준비되기 전에는 assembly 프로세스를 시작할 수 없습니다 (토큰 획득 불가, 첫 프레임 출력 불가, 3중 게이트 진행 불가). 순서 = 베이스 먼저 구축 후 어셈블리: ① tokens.ts 수치 진리값 설정 → ② fonts.ts + FontGuard.tsx (오답 #01) → ③ motion.ts 3개 훅 → ④ §3 컴포넌트 라이브러리 → ⑤ src/koubo/scenes/shared.tsx 게이트 4종 세트 + Place/qcAllow → ⑥ src/design/qc.tsx QC 프로브 → ⑦ src/Root.tsx composition 등록. 이 저장소의 src/design을 참조 구현으로 이식; 이식 후에도 수치는 여전히 tokens.ts에서 읽어오며, 스킬에 다시 채우지 않습니다.
0. 6대 불문율
- 정보 영역은 기본적으로 왼쪽, 인물은 오른쪽: 정보 영역은 기본적으로 왼쪽 (사용자 결정 작성자 기본값), HUD는 왼쪽 세로 방향으로 고정, 인물 영역은 진입 불가; 하지만 각 영상의 구성은 먼저 사용자에게 물어보고 임의로 결정하지 마세요, 3구역 좌표와 테이크오버 예외 메커니즘은 references/layout.md 규칙 1 참조.
- 모든 텍스트는 이중 구조: 대문자 넓은 자간 kicker (작게) + 중문 굵은 검정 (크게). 한 층의 텍스트만 있는 컴포넌트는 미완성으로 간주.
- 한 문장에서 하나의 단어만 강조: 중문 제목에서 색상 변경/강조 단어는 최대 한 곳, 색상은 반드시 4색 의미론 시스템에서 가져와야 함.
- 실제 소재가 주체, Remotion은 합성기이지 드로잉 보드가 아님 (2026-07-16 seg01 결정 업그레이드): '제품 경험'류 화면 (타이핑/생성/인터페이스/데모)은 모두 실제 소재 편집 — 직접 화면 녹화 > 공식 동영상 > 웹페이지 스크린샷 > UI 시뮬레이션 카드; 손 그림은 HUD 레이어(사이드 레이블/자막/차트/스탬프/비유적 그래픽)만 담당. CSS로 수제 모션 그래픽 전문가 팀의 작품을 따라 하면 반드시 실패하며, '아무리 조정해도 비슷하지 않음/차이가 크다'는 근본 원인은 드로잉 보드로 합성기의 싸움을 하는 것입니다. 수집 및 편집 파이프라인은 assembly references/broll.md 참조.
- 밝은 배경에 텍스트 직접 사용 금지 (2026-07-16 심층 비교 판결, 6개 섹션에 걸친 최상위 크로스 규칙): 밝은 배경 (흰 보드/흰 벽/밝은 색상 테이크오버 바닥) 위에 배경 없는 텍스트 금지 — 모든 텍스트는 반드시 어두운 색상 바닥판 (SURFACE.darkPlate), 카드 본체 또는 밝은 표면 변형 위에 위치해야 하며, textShadow는 해결책이 아님. 세부 규칙은 references/texture.md 참조.
- 한 화면에 하나의 지배 레이어: 각 정보 화면은 단 하나의 '최대 글자/최대 요소'만 있으며, 주 영역 외에 최대 2개의 칩 수준의 작은 요소만 허용. 세부 규칙은 references/typography.md와 layout.md 참조.
1. Design Tokens
유일한 진리값 = src/design/tokens.ts, 모든 컴포넌트는 거기서만 값을 가져와야 합니다. 이 섹션은 의미론과 사용 규칙만 작성하며, 수치는 복사하지 않습니다 — 이전에 스냅샷과 코드가 한 번 불일치했으며 (2026-07-16 kicker/h1 등 여러 곳 불일치 발견), 코드를 기준으로 합니다.
- 4색 의미론 (유일하게 허용되는 강조 색상): blue=정의/방법/중립적 진행; green=긍정/낮은 진입 장벽/이미 적용됨; yellow=기회/경고/논쟁/전환; red=부정/함정/위기. 기본 색상에는 white/grey/greyDim/cardBg/cardStroke가 별도로 있음.
- 폰트 (두 층으로 구분, 혼용 금지): MG 패키징 레이어 —
FONT.zh=Noto Sans SC (패키징 레이어 중문 유일 폰트, 제목은 일률적으로FONT.zhHeavy);FONT.en=Inter (kicker/본문/숫자);FONT.enTitle=Archivo Black (영문 제목과 큰 글자 결론, 좁은 사각형 초흑체, weight는 일률적으로 400 — Inter는 큰 글자 기세를 지탱하지 못함, 2026-07 자형 비교 결론). 하단 자막 레이어 —FONT.subZh=PingFang SC 400 /FONT.subEn=Inter 300 (2026-07-26 5단계 실사 비교 후 사용자 판결): 자막은 따라 읽기 레이어이지 패키징 레이어가 아니며, 가는 체만이 애플 자막의 질감을 가지며, MG 굵은 검정 제목과 계층을 나누고 주의를 빼앗지 않음; 구버전은 전체를 Noto 700으로 사용하여 스티커처럼 보였음. PingFang SC는 macOS 시스템 폰트이며,@fontsource번들링을 사용하지 않음 — 로컬 렌더링은 문제없지만, Windows/Linux 환경에서는 번들링된 Noto Sans SC 400 가는 파일로 폴백됨 (fonts.ts에 이미 포함되어 있어 느낌은 비슷하지만 동일 폰트는 아님), 교차 머신 렌더링 전에 먼저 한 프레임을 렌더링하여 자막 느낌 확인. 자막 영문 줄은 반드시 비례 서양 폰트를 사용해야 하며, 오답 #42 참조. - 큰 글자 결론은 일률적으로 순수 의미론적 색상 + textShadow를 사용하며, backgroundClip:text 그라데이션 폰트 금지 (오답 #06);
GRADIENT는 색상 블록/테두리류 용도에만 사용. - 글자 크기는
SIZE계단 (kicker / subSmall / chip / subZh / subEn / card / h2 / h1 / mega)만 허용하며, 계단 외 글자 크기 금지; 1080p 기준, 4K 출력은 등비 ×2. - 간격은 일률적으로
GRID(8px)의 배수; 둥근 모서리는RADIUS사용; 안전 영역은SAFE사용 (사이드 레이블 앵커, 스택 왼쪽 가장자리, 자막 바닥 거리; 상주 카드는 x55%를 넘지 않음, 인물 진입 금지 구역/오른쪽 구역 좌표는 layout.md 참조; 자막 금지 구역 y>82%, 왼쪽 영역 요소 하단 가장자리 ≤y840은 y82%보다 더 엄격한 왼쪽 영역 하드라인).
2. 챕터 사이드 레이블 SideLabel (전편 상주, 최우선 순위 컴포넌트)
- 구조:
│(4px 세로선, 의미론적 색상) +ENGLISH KICKER · 중문 구문(첫 번째 줄, 영문은 kicker 사양 + 의미론적 색상, 중문 흰색 34px) + 두 번째 줄 회색 24px 보충 설명. - 위치: 고정
SAFE.sideLabel, 전환 시 기존 레이블 페이드 아웃 12프레임, 새 레이블 왼쪽 슬라이드 인 15프레임. - 명명 규칙은 번호 체계:
SCENE 01,PATH 1/2/3, 대칭/반대 (DISSOLVED·01..vsIMMUNE·01..). - 색상 = 이 단락의 감정적 의미론, tokens 주석 참조. 참고:
refs/01-版式与侧标/.
3. 컴포넌트 사양 요약 (상세 사양은 구현과 함께 보충, 먼저 참고 이미지 확인 후 코드 작성)
| 컴포넌트 | 핵심 사양 | 참고 |
|---|---|---|
| BilingualSub | 중문 52 흰색+검은 그림자 / 영문 28 순수 흰색, 하단 중앙, 항상 최상위 레이어 | 임의 refs |
| HeroText | kicker + 중문 h1/h2, 강조 단어는 의미론적 색상 교체; 변형: 빨간색 취소선 교정, 노란색 브러시 밑줄, 기울어진 스탬프 | refs/02 |
| Chip | 검정 카드 RADIUS.chip + 컬러 아이콘 + 34px 텍스트, 한 곳 색상 변경 단어 가능 | refs/03 |
| Checklist | Chip 세로 쌓기, 하나씩 탄성 입력; 비활성화 항목 opacity 0.35 | refs/03 |
| InfoCard | 아이콘 + kicker + 44px 제목 + 파란색 강조 단어 | refs/01 |
| StepList | ①②③ 원형 번호 + 중문 + 영문 작은 kicker, 단계별 점등 | refs/04 |
| FlowChain | 검정 카드 + → 화살표 직렬 연결, 노드별 나타남 | refs/04 |
| CompareCard | 로고 + 이름 + 빨간색 ✕ 약점 chip + 초록색 ✓ 강점 chip, 세로 쌓기 | refs/04 |
| Formula | 큰 글자 A 기호 B (>, », ⇄, =), 기호는 의미론적 색상 사용 | refs/05 |
| BigNumber | Inter 큰 숫자 + 단위 작은 글자 + kicker; 카운터는 spring 스크롤 사용 | refs/05 |
| BarChart | 데이터 막대 8px 둥근 모서리; 강조 막대는 노란색 + 상단 왕관 chip; 나머지 회색 | refs/05 |
| CurveOverlay | 2–3px 노란색 곡선을 B-roll에 직접 오버레이, 오른쪽 끝점 레이블 | refs/05 |
| Timeline | 양 끝점 구간형 / 이벤트에 빨간색/초록색 결과 chip 부착형 | refs/05 |
| ScoreBoard | 초록색:빨간색 큰 숫자 점수판 | refs/05 |
| PhoneMockup | iPhone 외곽선 + 그라데이션 테두리 발광 + 내장 스크린샷 긴 이미지 스크롤 | refs/06 |
| WindowCard | mac 신호등 + 앱 아이콘 + 기능 chip, 내용 동적 | refs/04 |
| QuoteDoc | 흰색 배경 스크린샷 카드 + 노란색 형광펜 강조 + 검정 배경 중문 번역 바 오버레이 | refs/07 |
| TweetCard | 프로필 사진 + 신원 kicker + 빨간색 큰 글자 결론 + views chip | refs/07 |
| PersonCard | 원형 프로필 사진 + 이름 + 신원 작은 글자 + 기관 chip | refs/07 |
| Stamp | 기울기 -8°~-6° 테두리 스탬프 글자 (빨간색/초록색), 도장 애니메이션 = scale 1.3→1 + 가벼운 진동 | refs/08 |
| MatrixIcon | 사각형 매트릭스 아이콘: 빨간색 = 용해될 진영 / 초록색 = 면역 진영 | refs/08 |
| CardWall | 흰색 작은 카드 3→20장 차례로 화면 채우기, 수요 폭발 시뮬레이션 | refs/06 |
| BeforeAfter | 두 개의 아이콘 카드 + 파란색 화살표 + 하단 결론 chip | refs/04 |
| Breathe | idle 미세 모션 래퍼: 호흡 scale ±0.6% + 부동 ±3px, phase로 위상 분산하여 동기화 방지; 주인공 요소 외부 감싸기 | src/design/Breathe.tsx |
| BrickWall | 맞물린 금색 벽돌 가로 벽을 하나씩 쌓아 올림 + 중앙 레이블, '벽 쌓기/하드 장벽' 비유 | src/design/BrickWall.tsx |
| UnitMatrix | N개 그룹의 사각형 매트릭스를 셀별로 점등; fillRatio 와플 모드 (73% 데이터 필드) | src/design/UnitMatrix.tsx |
| CloneCascade | 소스 아이콘 카드 + 모조품이 차례로 페이드 인 + 경고 chip, '복제/증류' 비유 | src/design/CloneCascade.tsx |
일괄 생산 라인 Scene 인라인 요소 (2026-07-17 일괄 생산 추가, 아직 공유 요소로 승격되지 않음)
다음 요소는 현재 단일 Scene에만 존재하며, 'Scene 인라인, 두 번째 재사용 시 src/design 공유 요소로 승격하고 specs 사양 줄 추가' 로 표시 — 새 영상에서 유사한 요구사항 충돌 시 여기를 먼저 확인하고, 다시 만들지 마세요:
| 인라인 요소 | 위치 | 기능 | 승격 조건 |
|---|---|---|---|
| DissolveGrid | scenes/Scene08.tsx | 용해 그리드: 용해될 진영 블록이 셀별로 용해 분산, 중앙 ⚡ 바닥판 페이드 아웃 후 흰색 윤곽선 떠 있음 | 두 번째 '진영 용해' 비유 재사용 시 |
| VerdictBox (결산 프레임) | scenes/Scene17.tsx | 빨간색/초록색 미러 결산 프레임: ≈400×170 테두리 빈 프레임 먼저 세움 + 프레임 내 header + 가로 배열 3 chip 분할 입장 (빨간색 먼저 채워지고 초록색 나중에 채워져 '어느 쪽에 설래' 서스펜스 생성) | 두 번째 'VS 결산' 승격 시 |
| NamePlate + CtaBadge (CTA 배지 열) | scenes/Scene19.tsx | 엔딩 CTA 하단 가로 배열 한 줄: 명판 먼저 착지하여 앵커 역할 → 4개 액션 배지 차례로 탄성 입력 (댓글 배지 마지막이 가장 넓음 = 강조) | 두 번째 엔딩 CTA 마무리 시 |
아이콘 규칙
- 아이콘은 일률적으로 lucide-react 선형 SVG 아이콘 사용, 색상은 의미론적 색상 (
COLOR[accent]),strokeWidth 2.5정도; 이모지 금지 (컬러 둥근 모서리 블록은 기준 영상의 단색 선형 스타일과 충돌, 2026-07 세 번째 배치 검수 교훈). - Chip / Checklist / SideLabel의
iconprop은 모두 ReactNode를 허용:icon={<Lock size={26} strokeWidth={2.5} />}.
질감 규칙 → references/texture.md
젤리 블록 그라데이션, 동일 색상 glow, 비네트, 진짜 로고, SURFACE 밝음/어두움 변형, 스탬프 사양 유일선은 모두 texture.md에 있음 (2026-07-16부터 질감 유일 진리값, 이 섹션의 기존 내용은 이동됨).
4. 모션 규칙 → references/motion.md
useEnter/useExit, 비트 분할 입장, 서비스 구간, Breathe, 챕터 간 빈 화면, 금지 항목은 모두 motion.md에 있음 (2026-07-16부터 모션 유일 진리값, 이 섹션의 기존 내용은 이동됨; '이전 정보 투명도 감소 상주'는 '서비스 구간 + 퇴장 규율'로 대체되었음에 주의).
5. 내보내기 전 자체 점검 (매 렌더링 전에 실행)
- grep 검사로 tokens 외부의 색상 값/글자 크기/폰트를 컴포넌트에 인라인으로 사용했는지 확인.
- 모든 상주 카드가 faceZone / subtitleZone을 침범하는지 확인.
- 각 제목 강조 단어가 ≤ 1곳인지 확인; 영문 kicker가 모두 대문자 + 자간인지 확인.
- 3–5개의 키 프레임을 캡처하여 refs/의 해당 참고 이미지와 나란히 비교, 다르면 어떤 token 규칙을 위반했는지 파악하고 token을 수정, 컴포넌트 인라인을 수정하지 않음.
6. 오답 노트
#01 중문이 자동으로 명조체로 폴백 (2026-07-15 · 디자인 시스템 첫날)
- 증상: 렌더링/스크린샷에서 중문이 명조체로 바뀌고, 영문은 정상; 동일 컴포넌트가 때때로 정상이고 때로는 비정상 (운에 따라 다름).
- 원인: 세 가지 층, 마지막 층이 진짜 원인. ①
@remotion/google-fonts런타임에 gstatic에서 폰트를 가져오고, 국내 네트워크에서 가져올 수 없어 자동 폴백; ② 중문 웹폰트는 unicode-range로 분할되어, 로딩과 스크린샷 사이에 경쟁 상태 발생; ③ 트리 쉐이킹:package.json의sideEffects: ["*.css"]로 인해 사이드 이펙트로만 가져온fonts.ts가 프로덕션 번들링 시 전체 제거되어 폰트 CSS가 렌더링 번들에 없음 (document.fonts.size === 0) — Studio 개발 모드는 트리 쉐이킹하지 않으므로 'Studio 정상, 렌더링 실패'. - 수정법: ① 폰트는
@fontsource로컬 패키지 사용 (src/design/fonts.ts); ②package.json의sideEffects에 반드시"src/design/fonts.ts"포함; ③ 텍스트가 포함된 모든 합성에는<FontGuard/>를 적용: load→check 루프 검증, 동시에document.fonts.size > 0확인 (fonts.check()는 폰트 등록이 0일 때 빈 값으로 true 반환 가능), 타임아웃 시 즉시 cancelRender로 오류 보고, 절대 명조체 프레임을 묵인하지 않음. - 교훈: 'Studio 정상, 내보내기 실패'는 우선 프로덕션 번들링 차이(트리 쉐이킹/압축)를 의심, 미스터리한 경쟁 상태가 아님; 폰트 검수는 FontGuard 하드 게이트에 의존해야 하며, 사람 눈으로 썸네일을 믿을 수 없음.
#02 remotion still 출력 '○' = 이전 이미지 재사용
- 증상: 코드를 변경하고 다시 렌더링했지만 출력 파일이 전혀 변하지 않음; 명령줄에
+대신○표시. - 수정법: 렌더링 검수 전에 이전 출력 삭제 (또는 새 파일 이름으로 렌더링); 필요시
--bundle-cache=false추가.+= 실제 렌더링,○= 의심스러움. - 교훈: 비교 검수는 반드시 실제로 신선한 렌더링 결과물을 기반으로 해야 하며, 그렇지 않으면 '수정 무효'로 오진하게 됨 (이번에 이로 인해 두 바퀴를 더 돌았음).
#03 썸네일 비교 이미지는 속일 수 있음
- 증상: 나란히 비교한 작은 이미지에서 중문이 명조체처럼 보이지만, 원본은 실제로 정상.
- 수정법: 폰트/테두리 세부 사항을 판단할 때는 반드시 원본 해상도로 잘라서局部 확대하여 보며, 전체 프레임 썸네일로 결론 내리지 않음.
#04 JSX 속성 문자열이 \uXXXX 이스케이프를 해석하지 않음
- 증상:
<Chip icon="\u2705" />화면에 실제 ✅ 대신 문자 그대로\u2705표시. - 원인: JSX 속성의 문자열 리터럴은 HTML 방식 텍스트이며, JS 이스케이프 해석을 거치지 않음; JS 표현식 내의 문자열 (
icon={'\u2705'})만 이스케이프를 해석. 스크립트로 대량 TSX를 작성할 때 가장 쉽게 밟음. - 수정법: JSX 속성에서 이모지/특수 문자는 직접 실제 문자를 사용 (
icon="✅"); 이스케이프가 반드시 필요하면icon={'\u2705'}로 작성.
#06 backgroundClip: text 그라데이션 폰트 렌더링 어두움
- 증상: 큰 글자 제목에 backgroundImage 그라데이션 + WebkitBackgroundClip:'text' + WebkitTextFillColor:'transparent' 사용, Studio에서는 괜찮지만 렌더링 출력물에서 색상이 어둡고 탁해짐 (밝은 빨간색이 벽돌색으로 변함), 사용자가 단번에 거절.
- 수정법: 큰 글자 결론은 일률적으로 순수 의미론적 색상
COLOR[semantic]+ textShadow; 계층감을 원하면 그림자와 글자 두께로 구현, 그라데이션 채우기로 하지 않음. tokens.GRADIENT는 색상 블록/테두리류 용도에만 사용.
#08 완성 영상 MG 텍스트 가장자리 후광 효과, 칠한 듯한 느낌 ('MG 추가 시 화질 저하')(2026-07-16 · 0715-01 v3)
- 증상: 사용자가 완성 영상을 보고 화질이 나쁘다고 함; 확대하여 MG 텍스트 가장자리에 JPEG 모기 잡음/후광 효과가 있으며, 선명한 요소일수록 더 두드러짐. 소스 자체는 15 Mbps HEVC로 매우 깨끗함.
- 원인: Remotion 기본 파이프라인의 이중 압축 — 매 프레임을 품질 80의 JPEG 스크린샷으로 캡처한 후, CRF 18로 H264 압축. MG 큰 글자/가는 선은 고주파 신호로, 압축 아티팩트가 가장 먼저 나타남. MG 추가 전에는 아티팩트가 실제 촬영 텍스처에 숨어 눈에 띄지 않아 'MG가 화질을 나쁘게 한다'로 오진.
- 수정법:
remotion.config.ts에Config.setJpegQuality(100)+Config.setCrf(15)고정 (본 프로젝트 이미 설정됨, 되돌리지 마십시오). 용량 약 +20%, 렌더링 약간 느림, 그만한 가치가 있음. - 진단법: 동일 프레임을 소스/이전 완성 영상/새 파라미터 테스트 구간에서 각각 캡처하여 동일 MG 텍스트 영역을 잘라 확대하여 나란히 비교; 먼저 5초 테스트 구간을 렌더링하여 파라미터를 검증한 후 전체 영상 렌더링.
#09 긴 렌더링 도중 사라짐, mp4가 조각 파일로 남음 (2026-07-16 · 0715-01 v3)
- 증상: 렌더링이 오래 실행된 후 '프로세스는 살아 있지만' 결과물 파일이 오랫동안 크기가 증가하지 않음; 또는 렌더링이 소리 없이 사라져서 열 수 없는 mp4가 남음.
- 원인: ① 렌더링이 AI 세션의 하위 프로세스에 걸려 있어, 세션 재시작/종료 시 렌더링도 함께 종료됨 (이번에는 90%에서 종료됨); ② 프로세스 감지를 위해
pgrep -f "remotion render"사용 시 감지 스크립트 자체도 일치할 수 있음 (명령줄에 동일한 문자열이 포함되어 있어), '프로세스가 살아 있다'는 착각을 일으킴. - 수정법: ① 수 분 이상의 렌더링은 일률적으로
nohup npx remotion render … > /tmp/xx.log 2>&1 & disown으로 세션에서 분리; ② 완료 판단 기준은 로그 내+ 출력 파일 이름행 (+= 실제 렌더링 성공)으로 인지하며, 프로세스 존재 여부로 판단하지 않음; ③ 프로세스 감지는 자기 자신과의 일치를 배제 (CPU 점유율 확인 또는 정확한 PID 사용); ④ 다시 렌더링하기 전에 조각 파일 삭제. - 교훈: 조각 mp4 (재생 시간/용량이 일치하지 않음)는 절대 전달하지 않고, 먼저
ffprobe로 재생 시간과 오디오 트랙을 확인한 후 사용자에게 보여줌.