|

Claude Code 한 번의 세션으로 2.5D 패럴랙스 애니메이션 스튜디오 구축하기: 3개의 핵심 코드로 프레임 단위 결정론적 MP4 내보내기 구현

Claude Code 한 번의 세션으로 2.5D 패럴랙스 애니메이션 스튜디오 구축하기: 3개의 핵심 코드로 프레임 단위 결정론적 MP4 내보내기 구현

作者注:从프롬프트, 景深 보정 공식, Playwright+ffmpeg 프레임 단위 내보내기까지, Claude Code로 “내보내도 프레임이 안 빠지는” 2.5D 패럴랙스 애니메이션 스튜디오를 만드는 과정을 전부 풀어서 정리했어요.

아래는 올바른 번역입니다. 위 문장은 잘못 섞였으니 다시 정리할게요.

작성자 노트: 프롬프트부터 심도 보정 공식, Playwright+ffmpeg 프레임 단위 내보내기까지, Claude Code로 “내보내도 프레임이 빠지지 않는” 2.5D 패럴랙스 애니메이션 스튜디오를 만드는 과정을 하나하나 풀어서 정리했어요.

많은 분들이 AI 코딩 어시스턴트로 처음 애니메이션을 만들면, 브라우저 미리보기에서는 매끄럽게 잘 돌아가다가도 영상으로 내보내는 순간 끊김, 프레임 건너뜀, 길이 불일치 같은 문제를 겪어요. 원인은 대개 아키텍처에 있어요. 처음부터 “내보내기”를 설계의 일부로 생각하지 않았기 때문이죠. 이 글에서는 순수 함수 renderAt(t) + 프레임 단위 seek 캡처라는 핵심 줄기를 중심으로, Claude Code로 한 번의 세션 안에서 2.5D 패럴랙스 애니메이션 스튜디오를 만들고 MP4로 안정적으로 내보내는 방법을 설명해요.

이 글은 흔한 “AI한테 애니메이션 하나 짜달라고 하기” 데모가 아니에요. 심도 보정 공식을 어떻게 유도하는지, 아주 전형적인 오프셋 버그는 무엇인지, 그리고 실시간 재생과 프레임 단위 내보내기가 본질적으로 어떻게 다른지를 하나씩 뜯어볼 거예요.

핵심 가치: 이 글을 끝까지 읽으면 재사용할 수 있는 프롬프트 구조, 그대로 재현 가능한 내보내기 파이프라인, 그리고 다른 프로그래밍 방식 영상 프로젝트에도 옮겨 쓸 수 있는 검증 체크리스트를 얻게 돼요.

claude-code-2-5d-parallax-motion-studio-deterministic-mp4-export-ko-image-0


Claude Code 2.5D 시차 애니메이션 스튜디오 핵심 요약

참고 자료의 사례는 2026-11-09에 올라온 글에서 가져왔어요. 작성자는 Claude Code와 Opus 5.5를 사용해서 단 한 번의 세션으로 단일 파일 HTML 스튜디오를 만들었고, 여기에 25줄 정도의 Playwright 내보내기 스크립트를 더했어요. 작성자의 노트북에서는 6초짜리 720p 영상(180프레임)을 내보내는 데 약 20초가 걸렸어요. 하드웨어 사양은 공개되지 않았기 때문에 이 시간은 대략적인 규모를 가늠하는 참고용으로만 보시면 돼요.

핵심 요소 설명 가치
장면 그래프(Scene Graph) 각 레이어가 z 깊이, 크기, 위치, HTML 콘텐츠를 가짐 3D 모델 없이도 깊이감을 표현할 수 있음
타임라인(Timeline) 카메라와 레이어의 키프레임, 구간마다 이징 곡선 하나씩 지정 카메라 움직임을 편집하고 재사용할 수 있음
결정적 렌더러 renderAt(t)가 임의의 시각 t에 대해 항상 하나의 화면만 출력 내보내기 결과가 기기 성능과 무관함
깊이 보정 스케일링 크기와 오프셋에 모두 1 - z/perspective를 곱함 정지 상태에서는 작성한 그대로 보이고, 움직일 때는 시차가 자연스럽게 생김
프레임 단위 내보내기 파이프라인 Playwright가 i/fps 시점으로 seek해 스크린샷을 찍고, ffmpeg로 인코딩 어떤 기기에서도 같은 결과가 나오고 프레임이 빠지지 않음

2.5D 시차 애니메이션의 원리

2.5D는 평면적인 2D 소재를 3D 공간의 서로 다른 깊이에 배치한 다음, 가상 카메라가 그 사이를 지나가게 하는 방식이에요. 카메라와 가까운 레이어는 빠르게, 먼 레이어는 느리게 움직이고, 사람 눈은 이 속도 차이를 깊이로 받아들여요. 이것이 바로 시차(parallax)예요. 이 과정에는 모델링도, 조명도, 3D 엔진도 필요 없어요. 브라우저의 CSS perspective와 preserve-3d만으로 충분해요.

‘스튜디오’와 ‘일회성 애니메이션’을 가르는 기준은 세 가지 구성 요소가 모두 갖춰져 있는지예요. 바로 장면 그래프, 타임라인, 결정적 렌더러예요. 많은 튜토리얼이 세 번째를 건너뛰는데, 사실 내보낸 MP4가 끊기느냐 아니냐는 이 부분에서 갈려요. 그래서 첫 번째 프롬프트를 쓸 때부터 이것을 필수 요구사항으로 명시해야 해요.

claude-code-2-5d-parallax-motion-studio-deterministic-mp4-export-ko-image-1


Claude Code 2.5D 스튜디오의 환경 및 모델 설정

참고 자료에서는 첫 빌드를 Opus 5.5로 진행하라고 권해요. Anthropic 공식 모델 개요는 이 모델을 “장시간 실행되는 에이전트 코딩과 지식 업무”용 모델로 소개해요. 컨텍스트 윈도우는 1M 토큰이고, 최대 출력은 128K예요. 공식 가격은 100만 입력/출력 토큰당 각각 4달러/20달러인데, 실제 가격은 공식 페이지를 기준으로 확인해 주세요.

시작할 때 구체적인 모델 ID를 고정해 두는 것을 추천해요. 프로젝트 도중에 별칭(alias)이 바뀌어서 동작이 달라지는 일을 막을 수 있어요.

claude --model claude-opus-5-5 --effort high

Opus 5.5는 기본적으로 medium effort를 사용해요. 첫 빌드에서는 에이전트가 투영 수학, 키프레임 엔진, 내보내기 파이프라인을 한 번에 정확하게 작성해야 하니 high로 올리는 게 좋아요. 이후 키프레임 수치나 색상을 바꾸는 정도의 작은 수정은 medium으로 되돌려서 토큰을 아낄 수 있어요.

단계 권장 effort 대표 작업 이유
첫 빌드 high 투영 수학, 키프레임 엔진, 내보내기 스크립트 여러 하위 시스템을 한 번에 맞춰야 해요
반복 미세 조정 medium 키프레임 조정, 색상 변경, 레이어 추가 변경 범위가 작고 로직이 이미 안정적이에요
“카메라 설명” 인터페이스 low (시작 단계) 고정 스키마의 JSON 키프레임 반환 작업이 짧고 출력 구조가 고정돼 있어요

다른 모델로 같은 빌드를 했을 때 결과가 어떤지, 비용 차이는 얼마나 나는지에 대해서는 참고 자료에 비교 데이터가 없어요. 모델을 바꿔 보고 싶다면 같은 프롬프트로 각각 한 번씩 실행한 뒤, 뒤에서 소개할 정지 프레임 검증법으로 항목별로 비교해 보세요.


Claude Code로 2.5D 스튜디오를 만드는 프롬프트 구조

구체적으로 쓴 프롬프트 하나가 모호한 프롬프트 다섯 개보다 낫습니다. 참고 자료의 빌드 사양은 긴 프롬프트 한 덩어리로 되어 있는데, 원래 의도를 살린 버전은 아래와 같아요.

Build a 2.5D motion studio as one file, studio.html, with no dependencies.
- Scene: 6 layers (sky, moon, hills, city skyline, a title card "Ship it.",
  foreground foliage), each at its own z depth, using CSS perspective and preserve-3d.
- Camera: keyframes for x, y, z (dolly) and yaw (orbit around the card).
- Per-layer tracks: opacity, scale, y. Easings: linear, easeInOutCubic,
  easeInOutSine, easeOutBack.
- A timeline bar with keyframe markers, a playhead, click to scrub, space to play or pause.
- renderAt(t) must be pure in t. Expose window.__seek(t) that resolves after
  the frame paints, and a ?capture mode that hides the UI.
Then write export.mjs: Playwright opens ?capture, seeks every frame at 30 fps,
screenshots it and pipes PNGs to ffmpeg as H.264.

이 프롬프트는 장면, 카메라, 트랙과 이징, 인터랙션 UI, 내보내기 규약까지 네 겹으로 나눠 볼 수 있어요. 그중 결과를 가장 크게 좌우하는 건 마지막 두 줄입니다. renderAt(t)는 t에 대한 순수 함수여야 하고, 프레임을 다 그린 뒤에야 반환하는 __seek를 노출해야 하며, UI를 숨기는 ?capture 모드도 있어야 한다고 요구하죠. 이렇게 하면 내보내기 기능이 아키텍처 제약이 되고, agent는 코드를 짤 때 이 제약에 맞춰 설계하게 돼요.

내 프로젝트에 가져다 쓴다면 이 구조를 템플릿으로 활용해 보세요. 앞부분에는 “무엇을 그릴지”를 분명히 적고, 마지막 두세 줄에는 “프레임을 어떻게 결정론적으로 가져올지”를 못 박아 두면 됩니다.


Claude Code가 생성한 2.5D 핵심 코드 해설

스튜디오 전체 코드는 약 150줄이고, 핵심은 아래 세 부분이에요.

키프레임 샘플링과 이징

각 트랙은 시간순으로 정렬된 키프레임 배열이에요. sample()은 먼저 t의 앞뒤에 있는 두 키프레임을 찾아요. 그다음 앞쪽 키프레임의 이징 함수로 진행도를 계산하고, 모든 숫자 필드를 보간해요.

function sample(keys, t) {
  if (t <= keys[0].t) return keys[0];
  for (let i = 0; i < keys.length - 1; i++) {
    const a = keys[i], b = keys[i + 1];
    if (t <= b.t) {
      const p = (easings[a.ease] || easings.linear)((t - a.t) / (b.t - a.t));
      const out = {};
      for (const k in b)
        if (typeof b[k] === 'number' && k !== 't') out[k] = a[k] + (b[k] - a[k]) * p;
      return out;
    }
  }
  return keys[keys.length - 1];
}

이 함수는 현재 시간을 읽지 않고, 이전 프레임의 상태에도 의존하지 않아요. 난수도 쓰지 않고요. 같은 t를 넣으면 항상 같은 값이 나오는데, renderAt(t)가 결정적으로 동작하는 이유가 바로 여기에 있어요.

심도 보정: 2.5D 시차의 핵심 공식

핵심 아이디어는 카메라는 가만히 두고, 월드 전체를 반대 방향으로 움직이는 거예요. 각 레이어는 z축으로 이동하는 것 외에도 보정 스케일을 한 번 더 곱해줘야 해요.

const PERSPECTIVE = 1200; // #viewport의 perspective와 반드시 같아야 해요
world.style.transform =
  `translate3d(${-cam.x}px, ${-cam.y}px, ${cam.z}px) rotateY(${-cam.yaw}deg)`;
const comp = 1 - L.z / PERSPECTIVE;
el.style.transform = `translate(-50%,-50%) ` +
  `translate3d(${x * comp}px, ${y * comp}px, ${L.z}px) scale(${comp * s})`;

유도 과정은 이래요. CSS 원근 거리가 p일 때, 깊이 z인 점(z가 음수면 관찰자에게서 멀어지는 쪽이에요)은 화면에 투영되면서 p / (p - z)배로 축소돼요. p = 1200, z = -900을 넣으면 1200 / 2100 ≈ 0.571이 나오고, 레이어가 원래 크기의 약 57%만 남는다는 뜻이에요.

이 축소를 상쇄하려면 역수인 (p - z) / p = 1 - z/p = 1 + 900/1200 = 1.75를 곱하면 돼요. 코드의 comp가 바로 이 값이에요. 0.571 × 1.75 = 1이라서, 카메라가 정지해 있을 때는 모든 레이어가 여러분이 지정한 크기와 위치 그대로 나타나요.

그럼 시차는 어떻게 생길까요? 카메라가 움직이면 world 전체가 똑같은 dx만큼 평행 이동하지만, 각 레이어가 화면에서 실제로 이동하는 거리에는 여전히 각자의 p/(p - z)가 곱해져요. 먼 레이어는 계수가 작아서 조금만 움직이고, 가까운 레이어는 계수가 커서 많이 움직여요. 보정은 정지 상태의 구도만 바로잡을 뿐 움직일 때의 속도 차이에는 영향을 주지 않아요. 2.5D 효과는 바로 이 점에 기대고 있어요.

레이어 z 투영 스케일 p/(p−z) 보정 계수 comp 카메라 이동 시 상대 속도
0 (타이틀 카드 평면) 1.000 1.000 기준
-300 0.800 1.250 비교적 느림
-900 0.571 1.750 확연히 느림
-1800 0.400 2.500 거의 정지한 배경 수준

(표의 수치는 p = 1200 기준으로 계산했고, -300과 -1800 행은 예시로 유도한 값이에요.)

기억해 둘 만한 버그: 크기만 보정하고 오프셋은 보정하지 않았다

첫 번째 버전 코드는 레이어에 scale(comp)만 곱했고, x/y 오프셋에는 comp를 곱하지 않았어요. 그 결과 먼 곳에 있는 산언덕의 오프셋이 원근 효과 때문에 압축되면서 구도 전체가 어긋났고, 산언덕이 계속 높아져서 하늘의 약 3분의 2를 덮어 버렸어요. 해결 방법은 간단해요. x와 y에도 comp를 곱하면 돼요. 원근은 위치와 크기를 같은 계수로 스케일링하기 때문이에요.

더 눈여겨볼 점은 이 버그를 어떻게 발견했느냐예요. 작성자는 렌더링 결과 한 프레임을 보자마자 문제를 알아챘고, 코드를 읽을 때는 알아차리지 못했어요. 그러니 어떤 카메라 움직임이든 믿기 전에, 먼저 agent에게 시작·중간·끝 지점의 정지 프레임 세 장을 렌더링하게 하세요.

claude-code-2-5d-parallax-motion-studio-deterministic-mp4-export-ko-image-2


2.5D 시차 애니메이션을 프레임 단위로 결정론적으로 MP4로 내보내기

실시간 재생과 프레임 단위 내보내기의 본질적인 차이

실시간 미리보기는 requestAnimationFrame을 쓰기 때문에 기기가 바빠지면 프레임이 누락돼요. 미리보기 단계에서는 이 정도는 괜찮아요. 하지만 내보내기에서는 프레임이 누락되면 안 돼요. 화면 녹화를 쓰면 “실제 시간에 화면에 마침 표시된 것”만 녹화되기 때문에, 한 프레임만 느려져도 중복 프레임이나 누락 프레임이 생겨요.

항목 실시간 재생 (rAF / 화면 녹화) 프레임 단위 seek 내보내기
시간 기준 시스템 시계 프레임 번호 i / fps
기기가 바쁠 때 프레임 누락, 중복 프레임 속도만 느려질 뿐 화면은 그대로
기기 간 일관성 일관되지 않음 어떤 기기에서도 동일한 결과물 출력
프레임 수 제어 불가 정확히 duration × fps와 일치
적합한 상황 편집 미리보기, 타임라인 드래그 최종 영상, CI 자동 영상 생성

최소 내보내기 스크립트

내보내기 스크립트의 시간은 프레임 번호로 구동돼요. 프레임마다 먼저 seek하고, 화면이 다 그려질 때까지 기다린 다음 스크린샷을 찍어서 PNG를 ffmpeg의 표준 입력에 써 넣어요.

import { chromium } from 'playwright';
import { spawn } from 'node:child_process';
import { pathToFileURL } from 'node:url';

const out = process.argv[2] || 'out.mp4';
const browser = await chromium.launch();
const page = await browser.newPage({ viewport: { width: 1280, height: 720 } });
await page.goto(pathToFileURL('studio.html').href + '?capture');

const { duration, fps } = await page.evaluate(() => window.__scene);
const ffmpeg = spawn('ffmpeg', ['-y', '-f', 'image2pipe', '-framerate', String(fps),
  '-i', '-', '-c:v', 'libx264', '-pix_fmt', 'yuv420p', '-crf', '18', out],
  { stdio: ['pipe', 'ignore', 'inherit'] });

const frames = Math.round(duration * fps);
for (let i = 0; i < frames; i++) {
  await page.evaluate(t => window.__seek(t), i / fps);
  ffmpeg.stdin.write(await page.screenshot({ type: 'png' }));
}
ffmpeg.stdin.end();
await new Promise(r => ffmpeg.on('close', r));
await browser.close();

몇 가지 짚고 넘어갈 부분이 있어요. window.__seek(t)는 애니메이션 프레임 두 개를 기다린 뒤에 resolve되어야 해요. 그래야 스크린샷에 항상 새 transform이 반영돼요. image2pipe는 ffmpeg가 stdin에서 PNG 시퀀스를 읽게 해 줘요. yuv420p는 생성된 파일이 브라우저에서 문제없이 재생되도록 보장해요. Playwright에 브라우저가 아직 설치되어 있지 않다면 npx playwright install chromium을 먼저 한 번 실행하세요.

__seek 및 정지 프레임 검증 참고 구현 보기 (예시 코드)
// studio.html 내부: 결정론적 seek, 두 프레임을 그린 뒤 반환
window.__seek = (t) => new Promise(resolve => {
  renderAt(t);                       // 순수 함수: t에만 의존
  requestAnimationFrame(() =>
    requestAnimationFrame(resolve)); // 스타일이 반영되고 그려졌는지 확인
});
// stills.mjs: 시작 / 중간 / 끝 세 장의 정지 프레임을 렌더링, 이미지를 먼저 확인한 뒤 샷을 신뢰
import { chromium } from 'playwright';
import { pathToFileURL } from 'node:url';

const browser = await chromium.launch();
const page = await browser.newPage({ viewport: { width: 1280, height: 720 } });
await page.goto(pathToFileURL('studio.html').href + '?capture');
const { duration } = await page.evaluate(() => window.__scene);

for (const [name, t] of [['start', 0], ['mid', duration / 2], ['end', duration - 1e-3]]) {
  await page.evaluate(t => window.__seek(t), t);
  await page.screenshot({ path: `still-${name}.png` });
}
await browser.close();

위 두 코드는 참고 자료의 아이디어를 바탕으로 작성한 예시 구현이에요. 실제로는 agent가 여러분의 프로젝트에서 생성한 코드를 기준으로 하세요.

작성자의 실측 결과예요. 180프레임, 1280×720, 30 fps, 길이 6.0초이고, 출력 MP4는 약 420 KB, 총 소요 시간은 약 20초였어요. 화면 속 도시 타워의 이동량은 어두운 전경 언덕보다 작고, 전경 언덕은 마지막에 화면 밖으로 완전히 빠져나가요. 이게 바로 시차(parallax) 효과예요.

claude-code-2-5d-parallax-motion-studio-deterministic-mp4-export-ko-image-3


2.5D 스튜디오에 “샷 설명” 기능 추가하기

이제 작가가 샷 설명을 한 줄 입력하면 모델이 키프레임 JSON을 반환하게 만들 수 있어요. 참고 자료에서는 Anthropic Messages API를 직접 호출해요.

curl https://api.anthropic.com/v1/messages \
  -H "x-api-key: $ANTHROPIC_API_KEY" \
  -H "anthropic-version: 2026-10-21" \
  -H "content-type: application/json" \
  -d '{
    "model": "claude-opus-5-5",
    "max_tokens": 4096,
    "output_config": { "effort": "low" },
    "system": "Return only JSON: {\"camera\": [{\"t\",\"x\",\"y\",\"z\",\"yaw\",\"ease\"}], \"tracks\": {}}. Times in seconds, 0 to 6.",
    "messages": [{ "role": "user", "content": "Slow push-in, slight orbit right, title fades up in the first second." }]
  }'

여기서 쉽게 걸려 넘어지는 함정이 두 가지 있어요. 첫째, effort는 output_config.effort 안에 써야 해요. 둘째, Opus 5.5는 항상 적응형 사고(adaptive thinking)를 사용하기 때문에 thinking: {"type": "disabled"}를 전달하면 400 에러가 반환돼요. 게다가 사고 토큰도 max_tokens에 포함돼요. max_tokens를 너무 낮게 잡으면 JSON이 배열 중간에서 잘리고, stop_reason이 "max_tokens"로 나와요.

잘렸거나 불필요한 문장이 섞인 응답은 렌더링할 때 sample()에서 오류를 일으켜요. 그래서 이 호출에는 계약 테스트(contract test)를 붙여 두는 게 좋아요. 참고 자료에서는 Apidog CLI로 같은 Claude Code 세션에서 테스트를 만들고 실행해요. 검증 항목은 다음과 같아요.

  • 상태 코드가 200인지
  • stop_reason이 "max_tokens"가 아닌지
  • 반환된 텍스트가 JSON으로 파싱되는지
  • camera 배열의 t가 0부터 6까지 증가하는지

다른 API 테스트 도구나 직접 작성한 검증 스크립트로도 같은 목적을 달성할 수 있어요. system prompt나 effort를 바꾼 뒤에는 둘 다 반환 내용에 영향을 주기 때문에 반드시 테스트를 다시 실행해 주세요.


자주 묻는 질문 FAQ

Q1: 2.5D 시차 애니메이션과 진짜 3D 애니메이션은 뭐가 다른가요?

2.5D는 평평한 2D 소재를 서로 다른 깊이에 배치한 뒤, 움직이는 카메라로 촬영해서 속도 차이로 원근감을 만들어요. 3D 모델이나 조명, 3D 엔진이 필요 없고 브라우저 CSS만으로 구현할 수 있어요. 대신 카메라가 레이어 뒤쪽으로 크게 돌아갈 수는 없어요.

Q2: 화면 녹화를 하지 않고 프레임마다 seek해서 스크린샷을 찍는 이유가 뭔가요?

화면 녹화는 실제 시간을 따라가기 때문에 어느 한 프레임이 느려지면 프레임 드롭이나 중복 프레임이 생겨요. 반면 `i / fps` 위치로 seek한 뒤 스크린샷을 찍으면 각 프레임의 내용이 프레임 번호만으로 결정돼요. 그래서 어떤 기기에서 실행해도 결과가 똑같아요.

Q3: 보정 계수 1.75는 어떻게 계산한 값인가요?

원근 거리가 1200이고 깊이가 -900이면 투영 배율은 1200/2100 ≈ 0.571이에요. 보정값은 이 값의 역수인 `1 – z/p = 1 + 900/1200 = 1.75`로 잡아요. 두 값을 곱하면 1이 되니까, 카메라가 멈춰 있을 때 레이어가 설계한 크기와 위치로 돌아와요.

Q4: 처음 빌드할 때 Opus 5.5와 high effort를 권장하는 이유가 뭔가요?

처음 빌드할 때는 한 세션 안에서 투영 수학, 키프레임 엔진, 내보내기 파이프라인을 모두 작성해야 해요. 참고 자료에서는 프롬프트 한 번에 수정 한 번만으로 쓸 만한 스튜디오가 나왔어요. 이후의 사소한 수정은 medium 이하로도 충분해요. 다른 모델에서의 결과는 아직 공개된 비교 데이터가 없으니 직접 테스트해 보세요.

Q5: API 키 없이도 이 스튜디오를 쓸 수 있나요?

네, 쓸 수 있어요. 스튜디오 자체와 MP4 내보내기는 모두 로컬에서 실행되기 때문에 키가 필요 없어요. “샷 설명” 기능만 Messages API를 호출하므로 본인의 Anthropic API 키가 필요해요. Claude Code로 빌드할 때 소비하는 토큰은 사용 중인 계정의 요금 방식에 따라 정산돼요.

Q6: 이 방법에 알려진 한계가 있나요?

프레임마다 PNG 스크린샷을 찍는 속도는 해상도와 페이지 복잡도에 영향을 받아요. 참고 자료의 20초라는 소요 시간도 노트북 한 대에서 한 번 측정한 결과일 뿐이에요. 또 CSS 3D는 큰 각도의 yaw나 반투명 레이어 중첩을 렌더링할 때 브라우저 버전에 따라 차이가 날 수 있어요. 모델 ID, API 버전 헤더, effort 파라미터는 시간이 지나면 바뀔 수 있으니 사용하기 전에 공식 문서를 꼭 확인하세요.

Q7: “결정론적 렌더링 + 정지 프레임 검증”을 다른 프로그래밍 방식 영상 프로젝트에 적용하려면 어떻게 해야 하나요?

아래 체크리스트를 하나씩 확인해 보세요.

– 렌더링 함수는 t만 입력으로 받고, 시스템 시계를 읽지 않으며, 이전 프레임의 상태에 의존하지 않고, 시드가 고정되지 않은 난수도 쓰지 않아요
– “그리기가 끝난 뒤에 반환”하는 seek 인터페이스를 제공해요
– UI를 숨기는 capture 모드와 고정된 뷰포트 크기를 제공해요
– 내보내는 프레임 수가 정확히 `round(duration × fps)`와 같아야 해요
– 샷을 바꾼 뒤에는 시작, 중간, 끝 정지 프레임 세 장을 먼저 렌더링해서 확인한 다음 전체 영상을 내보내요
– 모델이 생성한 JSON 키프레임에는 계약 테스트를 추가해요. 파싱이 가능한지, 시간이 단조 증가하는지, 중간에 잘리지 않았는지를 확인해요


Claude Code 2.5D 시차 애니메이션 핵심 요약 Key Takeaways

  • 내보내기도 설계의 일부예요: 프롬프트 마지막 몇 줄에 순수 함수 renderAt(t)와 seek 규약을 명시해 두세요
  • 심도 보정 공식: comp = 1 − z/perspective이고, 크기와 x/y 오프셋 모두에 곱해요
  • 시차는 어디서 생길까요?: 보정은 정지된 구도만 바로잡아 줘요. 움직일 때는 각 레이어가 깊이에 따라 서로 다른 속도로 보여요
  • 카메라 워크를 믿기 전에 정지 프레임부터 확인하세요: 시작, 중간, 끝 이렇게 세 장의 이미지를 보면 코드만 읽어서는 찾기 어려운 버그가 드러나요
  • 프레임 번호로 시간을 구동하세요: Playwright의 seek와 스크린샷으로 프레임을 뽑고, ffmpeg image2pipe로 H.264 인코딩해요
  • effort는 단계별로 조정하세요: 처음 만들 때는 high, 미세 조정은 medium, 구조화된 JSON 인터페이스는 low부터 시작해요
  • 모델 출력에는 계약 테스트를 추가하세요: max_tokens 때문에 출력이 잘려 키프레임 파싱이 실패하는 일을 막아 줘요

마무리

Claude Code로 2.5D 시차 애니메이션 스튜디오를 만들 때 핵심은 세 가지예요.

  1. 아키텍처: 장면 그래프, 타임라인, 결정론적 렌더러 이렇게 세 요소로 구성되고, 완성 영상의 품질은 세 번째인 렌더러가 좌우해요
  2. 수학: 원근 보정 계수 1 - z/p가 크기와 오프셋에 동시에 적용돼요. 그래서 정지 상태에서는 구도가 정확하고, 움직일 때는 시차가 자연스럽게 생겨요
  3. 파이프라인: i/fps 기준으로 프레임마다 seek하고 스크린샷을 찍은 뒤 ffmpeg에 넘겨 인코딩하면, 머신 성능과 상관없이 같은 결과물이 나와요

먼저 이 글의 프롬프트 구조를 그대로 따라 6초짜리 샘플을 한 번 끝까지 만들어 보세요. 그리고 “카메라 워크를 바꾸기 전에 정지 프레임 세 장부터 본다”는 습관을 들이길 권해요. 그다음에는 레이어를 추가하거나 “장면 설명” 인터페이스를 연결해 보세요. 같은 결정론적 접근을 Remotion 같은 다른 프로그래밍 방식 영상 솔루션으로 옮겨 봐도 좋아요.


📚 참고 자료

  1. How to Build a 2.5D Motion Studio With Opus 5.5: 이 글에서 따라 해 본 실습의 원문이에요
  2. 링크: apidog.com/blog/build-2-5d-motion-studio-opus-5-5
  3. 설명: 전체 프롬프트, 스튜디오 코드, 내보내기 스크립트, “장면 설명(describe shot)” 인터페이스 예제가 들어 있어요

  4. Anthropic 모델 및 effort 문서: 모델 포지셔닝, 컨텍스트, 가격, effort 파라미터 설명

  5. 링크: docs.anthropic.com
  6. 설명: claude-opus-5-5의 모델 ID, API 버전 헤더, output_config 사용법을 확인할 수 있어요

  7. ffmpeg 포맷 문서: image2pipe 등 입력 포맷 설명

  8. 링크: ffmpeg.org/ffmpeg-formats.html
  9. 설명: stdin으로 PNG 시퀀스를 읽는 방식과 H.264 인코딩 파라미터를 이해하는 데 도움이 돼요

  10. Playwright 문서: 브라우저 자동화 및 스크린샷 API

  11. 링크: playwright.dev
  12. 설명: page.evaluate, page.screenshot, 브라우저 설치 명령어를 확인할 수 있어요

관련 글

Similar Posts