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 |
🔗 공식 리소스
- 공식 문서: https://midrender.com/revideo/docs/guide/performance/node-parent-reloading
- GitHub: https://github.com/midrender/revideo
상위 문서: ← Revideo 성능 & 최적화 출처: Revideo 공식 문서 — Isolating Frequently Changed Nodes 한글화 (2026-07-29) 공급사: Revideo (현 Midrender)
변경 이력
| 날짜 | 변경 |
|---|---|
| 2026-07-29 | 초안 작성 — Node 격리 패턴 + Before/After 측정 가이드 |
댓글
아직 댓글이 없습니다.
댓글을 작성하려면 로그인이 필요합니다.