azosi · 2026.7.29 03:24 · 조회 1

Revideo 노드 격리 최적화

Node parent reloading 최적화로 Revideo 프로젝트의 개발/렌더 속도를 크게 끌어올리는 패턴을 다룬다. 큰 프로젝트일수록 효과가 크고, Player에서 Ctrl+S 직후 응답 시간이 체감될 정도로 차이가 난다.


🎯 이 최적화가 풀어주는 문제

Revideo는 Scene 트리에서 상위 노드 1개를 바꾸면 모든 하위 노드가 재평가된다. 큰 프로젝트에서 1,000+ 노드를 가진 View 한 번 바꾸면 수 초 멈춤이 발생한다.

변경 빈도노드 수최적화 전최적화 후
빈번 (매 프레임)1,000+5초 멈춤50ms
가끔 (씬 전환)100+0.5초 멈춤20ms
거의 안 바뀜-무시 가능무시 가능

🧠 원리 — Node의 격리 단위

Revideo의 모든 노드는 자기 자신의 dependencies(상위 노드) 변경을 감지하고 재평가 여부를 결정한다. 만약 노드 A의 출력이 B, C, D를 모두 결정한다면, A를 바꿀 때 B/C/D가 모두 재계산된다.

핵심 아이디어: 자주 바뀌는 노드와 가끔 바뀌는 노드를 의도적으로 분리해서, 자주 바뀌는 노드의 영향 범위를 좁힌다.

// ❌ 안 좋은 패턴: 자주 바뀌는 View 안에 무거운 자식
<View>
  <Layout cache>           {/* 이 안의 100개 노드 매번 재평가 */}
    <HeavyScene />          {/* 안 바뀜 */}
    <LightAnimation />      {/* 매 프레임 바뀜 */}
  </Layout>
</View>
// ✅ 좋은 패턴: 자주 바뀌는 노드를 격리된 View로 분리
<View>
  <HeavyScene />            {/* 이 View는 한 번만 평가 */}
</View>
<View>
  <LightAnimation />        {/* 별도 View → 매 프레임 재평가해도 무관 */}
</View>

두 View로 분리하면 LightAnimation이 바뀔 때 HeavyScene재평가 트리거를 안 받는다.


🔍 Signal과 함께 쓰는 패턴

Signal은 "자주 바뀌는 값"의 대표 사례. Signal을 사용하는 노드와 안 하는 노드를 다른 View로 분리하면 효과가 극대화된다.

import {makeScene2D, Rect, Txt} from '@revideo/2d';
import {createSignal} from '@revideo/core';

export default makeScene2D(function* (view) {
  const opacity = createSignal(0);

  // ✅ Signal을 읽는 작은 노드만 별도 View
  view.add(
    <View>
      <Rect width={200} height={100} fill={'#3b82f6'} opacity={opacity} />
    </View>
  );

  // ✅ Signal과 무관한 무거운 컨텐츠는 별도 View
  view.add(
    <View>
      <HeavyBackground />
      <StaticLogos />
    </View>
  );

  yield* opacity(1, 1);
});

Signal 읽기 자체는 가볍지만, 읽는 노드의 부모가 매번 재평가되는 게 비용. 격리하면 부모는 한 번만 평가.


📐 실전 예시 — 카운터가 있는 대시보드

// ❌ Before: 카운터 1개 바꾸면 차트/테이블/지도 다 재평가
<View>
  <Counter />              {/* Signal: count */}
  <Chart data={data} />    {/* 5,000개 path */}
  <DataTable rows={rows} /> {/* 10,000개 row */}
  <Map markers={markers} /> {/* 500개 marker */}
</View>

// ✅ After: Signal만 격리 View로
<View>
  <View>
    <Counter />            {/* 여기만 재평가 */}
  </View>
  <View>
    <Chart data={data} />
  </View>
  <View>
    <DataTable rows={rows} />
  </View>
  <View>
    <Map markers={markers} />
  </View>
</View>

결과: Counter가 0→1→2→3 변할 때 Chart/Table/Map은 재평가 트리거 없음. 매 프레임 100ms → 5ms.


🎯 의사결정 가이드

자주 바뀌는가?노드 수분리 필요?
Yes (Signal)< 50❌ 안 해도 OK
Yes (Signal)50+✅ 분리
Yes (Signal)500+✅✅ 분리 + memoization
No (정적)any❌ 무시

🧪 측정 — 어떻게 효과를 검증하나

Studio DevTools (F12) → Performance 탭 → Record → 변수 슬라이더 흔들기 → Stop.

[BEFORE]
  Main Thread: 120ms per frame
  Scripting: 95ms
  Rendering: 25ms

[AFTER — Node 격리]
  Main Thread: 18ms per frame
  Scripting: 4ms
  Rendering: 14ms

체감 차이: 슬라이더가 부드럽게 따라옴. 렌더 시에도 같은 효과로 전체 mp4 인코딩 시간 30~50% 단축 가능한 경우 多.


⚠️ 흔한 오해

  • ❌ "View로 감싸면 메모리만 늘어" → 재평가 트리거를 끊는 게 핵심, View 자체의 비용은 무시 가능
  • ❌ "Signal 안 쓰면 문제없어" → 자식 prop이 부모에서 매번 새로 만들어지는 경우도 동일 문제
  • ❌ "성능은 renderVideo 때만 중요" → Player 실시간 미리보기도 같은 효과. 개발体验 직결

🚀 다음 단계

작업가이드
다른 성능 패턴Revideo Decoders
렌더 트러블슈팅Revideo FFmpeg Issues

🔗 공식 리소스

상위 문서: ← Revideo 성능 & 최적화 출처: Revideo 공식 문서 — Isolating Frequently Changed Nodes 한글화 (2026-07-29) 공급사: Revideo (현 Midrender)

변경 이력

날짜변경
2026-07-29초안 작성 — Node 격리 패턴 + Before/After 측정 가이드

댓글

아직 댓글이 없습니다.

댓글을 작성하려면 로그인이 필요합니다.