← 포트폴리오
027-1 · Motion Studio

모션영상 레퍼런스 보드 Remotion데이터 모션그래픽학습 자료

발표자료 기반으로 그래프·픽토그램이 움직이는 영상을 코드로 생성하기 위한 학습·제작 레퍼런스. 프롬프트·프로젝트 코드 전문·개념별 실습·커리큘럼을 한 곳에 담았다. 아래 라이브 데모 자체가 원칙(이징·스태거·stroke 애니)을 시연한다.

목차

  1. 왜 코드로 만드는가 — 핵심 통찰
  2. 라이브 데모 (CSS 재현)
  3. 제작 워크플로 5단계
  4. 빠른 시작 — 설치 & 실행
  5. 프로젝트 코드 전문 (4파일)
  6. 핵심 개념 5 — 코드 & 실습
  7. 프롬프트 모음 (복사해서 바로 사용)
  8. 코드 스택 — visx · lucide · fonts
  9. 프레임워크 선택
  10. 디자인 기본기 — 배열(layout)
  11. 모션 디자인 원칙
  12. 학습 로드맵 / 커리큘럼
  13. 레퍼런스 라이브러리 (링크)

1 — 왜 코드로 만드는가 · 핵심 통찰

일반 영상 편집(컷·자막 싱크·트랜지션)은 Claude Code가 약하다. 반대로 데이터 기반 그래프·픽토그램 애니메이션은 강하다 — 이건 "편집"이 아니라 코드로 정의하는 영상이기 때문이다. 모델은 코드 생성에 강하므로, 애니메이션을 코드로 정의하는 프레임워크(Remotion)를 출력 타겟으로 삼는다. CapCut은 BGM·최종 컷 마무리 용도로만 남기는 하이브리드.
강점

코드 = 영상

숫자·데이터 → 화면 요소를 코드로 매핑. "숫자만 바꿔 양산"이 가능한 지점이 자동화의 핵심.

재현성

버전·재사용

영상이 텍스트(코드)라 diff·리뷰·재사용 가능. 템플릿 한 번 만들면 데이터만 갈아끼운다.

품질

이징이 가른다

기술보다 이징·스태거·타이밍이 "싸구려 vs 프로"를 결정. 이 보드가 그 원칙을 코드로 보여준다.

2 — Live · 스타터 예제 미리보기 (CSS 재현)

아래는 실제 BarRace.tsx(Remotion) 산출물을 순수 CSS로 재현한 것. 이징·스태거·stroke 애니가 그대로 보인다.

분기 성장 지표
42
1월
68
2월
91
3월
trending-up
bar-chart
check-circle

3 — 제작 워크플로 · 발표자료 → 영상

STEP 1

데이터 준비

PPT 수치·메시지를 숫자 배열/JSON으로 정리

STEP 2

컴포넌트 작성

Remotion에서 차트·픽토를 코드로. interpolate로 애니

STEP 3

미리보기

npm run studio로 타임라인 확인·수정

STEP 4

렌더

npm run render → mp4 (자체 ffmpeg)

STEP 5

마무리

CapCut에서 BGM·최종 컷·자막

4 — 빠른 시작 · 설치 & 실행

Node 18+ (권장 v20/v24), npm. Remotion은 자체 ffmpeg를 번들하므로 시스템 ffmpeg 불필요.

터미널 — 새 프로젝트 생성부터 렌더까지
# 1) 공식 템플릿으로 새 프로젝트 (대화형)
npx create-video@latest

# 2) 또는 우리 스타터 폴더에서 바로
cd motion_video_team/starter
npm install

# 3) 스튜디오(미리보기) — 타임라인을 눈으로 보며 수정
npm run studio        # = remotion studio

# 4) mp4 렌더 (out/starter.mp4 생성, 첫 실행 시 Headless Chrome 1회 다운로드)
npm run render        # = remotion render BarRace out/starter.mp4

# 5) 확장 라이브러리(차트/픽토/폰트)
npm i @visx/scale @visx/shape lucide-react @remotion/google-fonts
첫 렌더 산출물 기준: 1280×720 · 30fps · 4초(120프레임) → 약 207KB, 렌더 수초. 검증 완료됨(starter/out/starter.mp4).

5 — 프로젝트 코드 전문 · 4파일, 그대로 복사해 동작

스타터 프로젝트 전체. 각 파일의 [개념N] 주석이 아래 6번 개념 섹션과 연결된다.

package.json
{
  "name": "motion-starter",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "studio": "remotion studio",
    "render": "remotion render BarRace out/starter.mp4"
  },
  "dependencies": {
    "react": "18.3.1",
    "react-dom": "18.3.1",
    "remotion": "^4.0.0"
  },
  "devDependencies": {
    "@remotion/cli": "^4.0.0",
    "@types/react": "^18.3.0",
    "@types/react-dom": "^18.3.0",
    "typescript": "^5.4.0"
  }
}
src/index.ts — Remotion 진입점
// Remotion 진입점: 루트 컴포넌트를 등록한다. (렌더러/스튜디오가 여기서 시작)
import { registerRoot } from "remotion";
import { RemotionRoot } from "./Root";

registerRoot(RemotionRoot);
src/Root.tsx — 컴포지션 등록 · 데이터 진입점
import { Composition } from "remotion";
import { BarRace } from "./BarRace";

// [개념4 · 데이터매핑] defaultProps의 data 배열만 바꾸면 영상이 바뀐다.
// 여기가 "숫자만 바꿔서 영상 양산"의 진입점.
export const RemotionRoot: React.FC = () => {
  return (
    <Composition
      id="BarRace"
      component={BarRace}
      durationInFrames={120} // [개념1] 30fps × 4초 = 120프레임
      fps={30}
      width={1280}
      height={720}
      defaultProps={{
        title: "분기 성장 지표",
        data: [
          { label: "1월", value: 42 },
          { label: "2월", value: 68 },
          { label: "3월", value: 91 },
        ],
      }}
    />
  );
};
src/BarRace.tsx — 교재형 본체 (개념 1~5 전부 여기 있음)
import { AbsoluteFill, interpolate, Easing, useCurrentFrame } from "remotion";

/**
 * 모션영상팀 스타터 예제 — 교재용.
 * 발표자료형 데이터 모션그래픽의 5개 핵심 개념을 한 화면에서 보여준다.
 * 각 개념이 코드 어디에 있는지 [개념N] 주석으로 표시했다.
 */

// [개념4 · 데이터매핑] 화면에 그려질 데이터. 이 배열만 바꾸면 영상이 바뀐다.
type Datum = { label: string; value: number };
type Props = { title: string; data: Datum[] };

// ── 디자인 토큰 (배열 기본기) ─────────────────────────────
// [색 60-30-10] 배경=BG(60), 축/보조=SUB(30), 강조=ACCENT(10, 딱 하나)
const BG = "#0f172a";
const SUB = "#334155";
const TEXT = "#e2e8f0";
const ACCENT = "#38bdf8";

// [안전영역] 화면 가장자리에서 8~10% 안쪽에만 요소를 둔다.
const W = 1280;
const H = 720;
const MARGIN_X = 160; // 12.5%
const BASELINE_Y = 600; // 바가 서는 바닥선
const MAX_BAR_H = 380; // value=100일 때 최대 높이
const MAX_VALUE = 100;

export const BarRace: React.FC<Props> = ({ title, data }) => {
  // [개념1 · 타임라인] 지금 몇 번째 프레임인지. 모든 애니의 시간 기준.
  const frame = useCurrentFrame();

  const slotW = (W - MARGIN_X * 2) / data.length; // 바 하나가 차지하는 가로 폭
  const barW = 120;

  // [개념3 · SVG stroke 애니] 제목 옆 "상승 화살표"가 그려지듯 등장.
  // pathLength=100으로 경로 길이를 100으로 정규화 → dashoffset 100→0 이면 "그려짐".
  const drawProgress = interpolate(frame, [10, 40], [100, 0], {
    extrapolateLeft: "clamp",
    extrapolateRight: "clamp",
    easing: Easing.out(Easing.cubic), // [개념2 · 이징]
  });

  return (
    <AbsoluteFill style={{ backgroundColor: BG, fontFamily: "sans-serif" }}>
      {/* 제목 — [시각적 위계] 가장 큰 텍스트 = 주인공 */}
      <div
        style={{
          position: "absolute", top: 70, left: MARGIN_X,
          color: TEXT, fontSize: 56, fontWeight: 700,
          display: "flex", alignItems: "center", gap: 20,
        }}
      >
        {title}
        {/* 자기 자신을 그리는 상승 화살표 */}
        <svg width={90} height={70} viewBox="0 0 90 70">
          <polyline
            points="10,55 35,35 55,45 80,15"
            fill="none" stroke={ACCENT} strokeWidth={6}
            strokeLinecap="round" strokeLinejoin="round"
            pathLength={100} strokeDasharray={100} strokeDashoffset={drawProgress}
          />
          <polyline
            points="80,15 80,32 63,15 80,15"
            fill={ACCENT} stroke={ACCENT} strokeWidth={2}
            opacity={interpolate(frame, [38, 46], [0, 1], {
              extrapolateLeft: "clamp", extrapolateRight: "clamp",
            })}
          />
        </svg>
      </div>

      <svg width={W} height={H} style={{ position: "absolute", inset: 0 }}>
        {/* 바닥 축선 — [보조색 30] */}
        <line x1={MARGIN_X - 20} y1={BASELINE_Y} x2={W - MARGIN_X + 20} y2={BASELINE_Y}
          stroke={SUB} strokeWidth={2} />

        {data.map((d, i) => {
          const cx = MARGIN_X + slotW * i + slotW / 2; // 슬롯 중앙 정렬

          // [스태거] 바마다 등장을 3프레임(0.1초)씩 뒤로 민다 → 순차 등장.
          const delay = 20 + i * 3;

          // [개념1+2] 0→1 성장 진행도에 이징 적용 (등속 금지).
          const grow = interpolate(frame, [delay, delay + 22], [0, 1], {
            extrapolateLeft: "clamp", extrapolateRight: "clamp",
            easing: Easing.out(Easing.cubic),
          });

          const fullH = (d.value / MAX_VALUE) * MAX_BAR_H;
          const barH = fullH * grow; // 실제 그려질 높이
          const y = BASELINE_Y - barH;

          return (
            <g key={d.label}>
              <rect x={cx - barW / 2} y={y} width={barW} height={barH} rx={10} fill={ACCENT} />
              {/* 수치 — [게슈탈트 근접] 바 바로 위에 붙여 한 덩어리로 */}
              <text x={cx} y={y - 16} fill={TEXT} fontSize={34} fontWeight={700}
                textAnchor="middle" opacity={grow}>
                {Math.round(d.value * grow)}
              </text>
              {/* 라벨 — 바 아래, 축과 근접 */}
              <text x={cx} y={BASELINE_Y + 44} fill={TEXT} fontSize={30} textAnchor="middle">
                {d.label}
              </text>
            </g>
          );
        })}
      </svg>
    </AbsoluteFill>
  );
};

6 — 핵심 개념 5 · 코드 & 직접 바꿔볼 것

각 개념은 "동작 원리 → 코드 위치 → 직접 바꿔볼 것" 3단. 레버리지(가성비) 순서.

개념 1

타임라인 & 보간(interpolate)

프레임/fps가 시간 축. interpolate(frame, [시작,끝], [값0,값1])은 frame이 시작→끝으로 갈 때 값0→값1로 선형 변환. extrapolate…:"clamp"로 범위 밖을 고정한다.

보간 기본형
const frame = useCurrentFrame();          // 0,1,2,… (30fps면 1초=30)
const opacity = interpolate(frame, [0, 20], [0, 1], {
  extrapolateRight: "clamp",               // 20프레임 뒤엔 1로 고정
});                                          // 0→20프레임(≈0.66초) 동안 서서히 등장
바꿔볼 것 · 성장 구간 [delay, delay+22]2240으로 늘리면 바가 더 천천히 자란다. fps로 나눠 "몇 초"인지 감을 잡자(22/30 ≈ 0.73초).
개념 2 · 가성비 1위

이징(easing) & spring

선형(linear)은 싸구려로 보인다. 위 보간값에 easing: Easing.out(Easing.cubic)를 얹으면 "빠르게 시작→부드럽게 감속". 물리 기반 등장은 spring().

이징 적용 · spring 비교
// (A) 이징 얹기
const grow = interpolate(frame, [20, 42], [0, 1], {
  easing: Easing.out(Easing.cubic), extrapolateRight: "clamp",
});

// (B) 스프링 — 통통 튀는 자연스러운 등장
const s = spring({ frame, fps: 30, config: { damping: 12 } }); // 0→1
바꿔볼 것 · easing 줄을 지우고 렌더해 등속과 비교해보라. 한 줄 차이로 "프로 vs 아마추어"가 갈린다.
개념 3

SVG stroke 애니 — 픽토그램의 핵심

pathLength={100}으로 경로 길이를 100으로 정규화하고, strokeDasharray={100} + strokeDashoffset를 100→0으로 보간하면 선이 "그려진다". Lucide 아이콘 대부분이 stroke path라 이 기법이 바로 먹힌다.

self-drawing path
const draw = interpolate(frame, [10, 40], [100, 0], { extrapolateRight: "clamp" });
<polyline points="10,55 35,35 55,45 80,15" fill="none" stroke={ACCENT} strokeWidth={6}
  pathLength={100} strokeDasharray={100} strokeDashoffset={draw} />
바꿔볼 것 · points를 다른 폴리라인(예: 체크마크 "20,50 40,70 80,25")으로 바꾸면 다른 아이콘이 그려진다.
개념 4

데이터 → 시각화 매핑

value / MAX_VALUE * MAX_BAR_H로 수치를 픽셀 높이로 환산. Root.tsxdata 배열이 유일한 입력이다. 여기가 "숫자만 바꿔 양산"의 진입점.

수치 → 픽셀
const fullH = (d.value / MAX_VALUE) * MAX_BAR_H;  // 91 → 345.8px
const barH  = fullH * grow;                        // 성장 진행도(0→1) 곱
바꿔볼 것 · data{label:"4월", value:77}를 추가하면 바가 자동으로 하나 늘고 slotW가 재계산돼 배치가 맞춰진다.
개념 5

렌더 파이프라인

remotion render <컴포지션ID> <출력경로>로 mp4 출력. Remotion이 자체 ffmpeg를 번들해 시스템 설치가 불필요. CapCut은 BGM·최종 컷 마무리용.

렌더 옵션
npx remotion render BarRace out/starter.mp4
npx remotion render BarRace out/hd.mp4 --scale=1.5      # 해상도 1.5배
npx remotion render BarRace out/clip.mp4 --frames=0-60   # 구간만
바꿔볼 것 · --frames=0-60으로 앞 2초만 뽑아 빠르게 확인. 최종은 전체 렌더.

7 — 프롬프트 모음 · 복사해서 바로 사용

Claude Code(또는 아무 Claude 세션)에 붙여넣어 팀을 세우고 영상을 만드는 실전 프롬프트. <…> 부분만 네 데이터로 바꾸면 된다.

🎬 팀 호출 — 이 역할팀을 세션에 세운다
너는 "모션영상 스튜디오" 팀이다. 발표자료 기반 데이터 모션그래픽 영상을
GUI 편집이 아니라 코드(Remotion)로 만들고, 그 과정을 나에게 가르친다.

[고정 스택] Remotion(React/TS) + visx(차트) + lucide-react(픽토) + @remotion/google-fonts
[핵심 API] useCurrentFrame() · interpolate() · spring()
[역할] 디렉터(총괄) · 비주얼라이저(데이터→도형) · 모션디자이너(움직임+배열) ·
       렌더엔지니어(mp4/ffmpeg/CapCut) · 튜터(개념 설명)

[불변 규칙]
1. 데이터는 내가 준 실제 값만 쓴다 — 수치를 지어내지 않는다.
2. 모든 애니는 이징 필수(등속 금지) · 스태거 0.1초 · 전환 0.3~0.6초.
3. 색 60-30-10(강조색 하나) · 폰트 최대 2종 · 가장자리 8~10% 안전영역.
4. 새 애니/배열에는 "어떤 원칙을 적용했는지" 한 줄 주석을 남긴다(학습용).
5. 완료 전 실제 렌더를 1회 실행하고 산출 경로·용량을 보고한다. 못 하면 "미검증"이라 쓴다.

준비되면 "무슨 데이터를 영상으로 만들까?"라고 먼저 물어라.
📊 영상 1개 만들기 — 발표자료 수치 → 애니 바차트
아래 데이터로 4초(30fps·1280×720) 바차트 모션 영상을 Remotion으로 만들어줘.

제목: "<제목 예: 2026 상반기 매출>"
데이터:
  - <라벨1>: <값1>
  - <라벨2>: <값2>
  - <라벨3>: <값3>
강조 메시지: "<한 문장 예: 3분기 연속 성장>"

요구사항:
- 바는 바닥에서 목표 높이로 easeOut 성장, 0.1초씩 스태거 등장
- 각 바 위에 실시간으로 올라가는 수치 표시
- 제목 옆 상승 화살표를 stroke로 그려지듯 등장(pathLength 트릭)
- 색은 60-30-10, 강조색 하나. 안전영역 지킬 것
- data 배열만 바꾸면 재사용되도록 Root.tsx에 분리
끝나면 npm run render로 mp4 뽑고 경로 알려줘.
🧱 프로젝트 원샷 스캐폴딩 — 빈 폴더에서 시작
빈 폴더에 Remotion 스타터 프로젝트를 만들어줘. 파일 4개만:
package.json / src/index.ts / src/Root.tsx / src/BarRace.tsx

- BarRace: props로 title과 {label,value}[] 데이터를 받는 바차트 컴포넌트
- 개념 1~5(보간·이징·SVG stroke·데이터매핑·렌더)를 각각 [개념N] 주석으로 표시
- Root.tsx에 defaultProps로 샘플 데이터 3개
- scripts: "studio": "remotion studio", "render": "remotion render BarRace out/starter.mp4"
- 의존성: react/react-dom 18, remotion ^4, @remotion/cli, typescript

만든 뒤 npm install → npm run render로 out/starter.mp4까지 검증하고
각 파일이 무슨 역할인지 3줄로 설명해줘.
✨ 모션 리뷰 — 싸구려 교정
이 컴포넌트의 움직임을 모션 디자이너 관점에서 리뷰해줘.
- linear 이징이 있으면 easeOut/spring으로 교정
- 동시 등장을 0.1초 스태거로
- 전환이 0.3~0.6초 밖이면 조정
- "한 번에 하나씩" 위반 지점 지적
바꾼 부분마다 어떤 원칙을 적용했는지 한 줄 주석을 남겨줘.
📈 차트 확장 — visx로 라인/도넛
지금 순수 SVG 바차트를 visx(@visx/scale,@visx/shape)로 바꿔줘.
- scaleLinear로 값→픽셀, scaleBand로 x배치
- 라이브러리 자체 애니는 끄고(isAnimationActive 개념), 움직임은
  전부 Remotion interpolate로 프레임 제어
- 같은 data props 형태 유지(호환)
라인차트 버전도 하나 더 만들어서 stroke self-draw로 그려지게 해줘.
튜터용 한 줄 프롬프트: "방금 그 코드에서 interpolate가 정확히 뭘 하는지, 이 프로젝트 코드 위치를 짚어가며 초보자에게 설명하고, 내가 직접 바꿔볼 것 3개를 줘."

8 — 코드 스택 · visx · lucide · fonts

원칙: 차트 라이브러리로는 "모양"만 그리고, 움직임은 Remotion interpolate로. 바 높이·라인 길이를 프레임값에 매핑한다. (라이브러리 자체 애니는 끈다)
lucide-react — 픽토를 stroke로
import { TrendingUp } from "lucide-react";
// Lucide 아이콘은 내부가 stroke path → dashoffset 트릭이 바로 먹힘
const draw = interpolate(frame, [0, 25], [1, 0], { extrapolateRight: "clamp" });
<TrendingUp color={ACCENT} size={64} strokeWidth={2.5}
  style={{ strokeDasharray: 120, strokeDashoffset: 120 * draw }} />
@remotion/google-fonts
import { loadFont } from "@remotion/google-fonts/Pretendard";
const { fontFamily } = loadFont();
// style={{ fontFamily }} — 렌더 시 폰트 누락 방지(안정적 로드)
visx — 값→픽셀 스케일 (모양만, 움직임은 interpolate)
import { scaleLinear, scaleBand } from "@visx/scale";

const x = scaleBand({ domain: data.map(d => d.label), range: [MARGIN_X, W - MARGIN_X], padding: 0.4 });
const y = scaleLinear({ domain: [0, MAX_VALUE], range: [BASELINE_Y, 100] });

// 모양은 visx 스케일로, 성장(0→1)은 Remotion interpolate로 곱한다
const grow = interpolate(frame, [delay, delay + 22], [0, 1], { easing: Easing.out(Easing.cubic), extrapolateRight: "clamp" });
const barH = (BASELINE_Y - y(d.value)) * grow;

9 — 프레임워크 선택

프레임워크언어강점추천 대상
Remotion ★ 채택React/TS발표자료형 슬라이드+차트+픽토, 웹 기술 그대로 → mp4슬라이드 느낌 영상 (본 프로젝트)
Motion CanvasTypeScript순수 모션그래픽, 다이어그램·화살표·강조기술 설명 영상
ManimPython수식·그래프 애니(3Blue1Brown 스타일)그래프 중심, 파이썬 선호

"발표자료 기반 + 그래프/픽토그램"이면 Remotion이 최적. HTML/CSS/SVG를 그대로 쓰므로 슬라이드 레이아웃이 자연스럽고 mp4로 렌더된다.

10 — 디자인 기본기 · 배열(layout)

배열이 어색한 건 감이 아니라 원칙 부재. 4개만 잡으면 된다.

구조 4원칙

그리드 · 위계 · 여백 · 게슈탈트

① 그리드·정렬 여백 8~10% 안전영역, 선에 맞춤(눈대중 금지). ② 시각적 위계 크기·굵기·색으로 서열, 주인공 하나. ③ 여백 다 채우지 말 것, 8px 배수. ④ 게슈탈트 근접·유사 라벨-수치 묶기.

색 · 타이포 규칙 (암기)

60-30-10 · 폰트 2종

색 60-30-10 배경60 / 보조30 / 강조10, 강조색 딱 하나(이 보드는 하나). 폰트 최대 2종, 배수 스케일(16→24→36→54). 영상 특화: 폰트 크게 + 가장자리 세이프영역.

11 — 모션 디자인 원칙 · 싸구려 방지 5

1 · 가성비 최고

이징 필수

등속(linear) 금지. easeInOut/spring 기본. 이거 하나로 결과물이 프로처럼.

2

스태거(순차)

바 5개 동시 등장 = 촌스러움. 0.1초씩 밀어 순차 등장.

3

한 번에 하나씩

시선 유도. 동시에 여러 개가 움직이면 정신없다.

4

타이밍 0.3~0.6s

대부분 전환은 이 구간. 너무 빠르면 안 읽히고 느리면 지루.

5

입·퇴장 일관성

왼쪽에서 들어오면 왼쪽으로 나간다. 규칙 통일.

이론 보강

Disney 12원칙

이 중 slow in/out(이징)·스태거·anticipation 3개가 데이터 모션의 핵심.

12 — 학습 로드맵 / 커리큘럼

레버리지(가성비) 순서. 각 단계는 "개념 → 코드 위치 → 바꿔볼 것" 3단.

단계배우는 것코드 위치 · 실습상태
1타임라인 & 보간useCurrentFrame·interpolate / 성장 구간 늘려보기✅ 실습
2이징 (가성비 최고)Easing.out(cubic)·spring / 이징 빼고 비교✅ 실습
3SVG 기초 (stroke)화살표 self-draw / points 바꿔보기✅ 실습
4데이터 → 시각화 매핑Root.tsxdata / 항목 추가✅ 순수 SVG · ⏭ visx 확장
5렌더 파이프라인remotion render / 구간 렌더✅ mp4 검증
다음 반복(아직 안 함): ① Remotion 공식 Agent Skill(2026-01) 설치·시연 → 자체구현 비교 · ② visx 라인/도넛/racing bar 확장 · ③ 공통 토큰(팔레트·타이포 스케일) 고정 · ④ 실제 발표자료 1건으로 첫 실전 영상 + CapCut 마무리.

13 — 레퍼런스 라이브러리 (링크)

⭐ 즉시 쓸 것 — Claude Code × Remotion

공식 · 차트

픽토그램 · 폰트

이징 · 색 · 타이포 도구

스타일 타겟 (영감)

복사됨