미리보기와 렌더의 일치

생성형 AI
미리보기와 렌더의 일치
2026.06.07 · 3분 읽기
내보낸 영상이 편집기에서 보던 것과 달랐다. 자막이 반 박자 늦게 뜨고, 배경 영상이 채 뜨기 전에 장면이 넘어갔다. 타임라인 편집기에서 가장 먼저 풀어야 할 문제는 효과의 화려함이 아니라 미리보기와 최종 결과의 일치였다.
미리보기와 렌더는 두 번 그린다
타임라인 편집기는 같은 영상을 두 번 그린다. 편집 중의 실시간 미리보기, 그리고 내보낼 때의 최종 렌더다. 두 경로를 별도 코드로 구현하면 불일치가 구조적으로 생긴다. 그래서 두 경로가 같은 렌더링 컴포넌트와 같은 입력 데이터를 공유하게 했다. 편집기가 그리는 컴포넌트를 렌더 경로가 프레임 단위로 똑같이 실행한다.
타임라인 데이터 모델은 단순하다. 영상은 장면과 객체의 트리고, 각 객체는 시작 시각과 지속 시간, 변형, 효과를 가진다. 미리보기와 렌더는 모두 이 단일 JSON을 입력으로 받는다.
시간이 다르면 결과도 달라진다
컴포넌트를 공유해도 타이밍은 어긋난다. 재생은 흐르는 시계지만, 렌더는 결정적 함수다. 미리보기는 리소스 로딩이 늦으면 화면이 잠깐 비었다가 채워지지만, 최종 렌더는 같은 프레임을 언제 렌더해도 똑같아야 한다.
실제 불일치는 대부분 이미지·비디오 로딩 지연과 애니메이션 타이밍에서 나왔다. 그래서 세 가지 원칙으로 맞췄다. 리소스가 모두 로드된 뒤에 해당 프레임을 캡처하고, 애니메이션 상태는 실시간 시계가 아니라 프레임 번호의 함수로 정의하고, 재생 시각과 렌더 시각을 하나의 변환 규칙으로 통일했다.
운영 가능한 인프라를 택했다
렌더 인프라는 자체 구축과 관리형 사이에서 선택해야 했다. 자체 구축은 제어권이 크지만 운영 부담이 컸고, 관리형은 제약이 있는 대신 운영 비용이 훨씬 작았다. 설계 문서까지 마쳤던 자체 구축을 접은 결정 요인은 기술이 아니라 운영이었다. 작은 팀에게 중요한 건 "만들 수 있는가"보다 "계속 운영할 수 있는가"였다.
긴 영상은 나눠서 그렸다
관리형으로 옮긴 뒤에도 제약이 남았다. 긴 영상은 단일 렌더의 실행 시간 제한에 걸리고, 사용자에게는 결과를 빠르게 전달해야 했다. 그래서 긴 영상을 여러 청크로 나눠 병렬로 렌더하고, 마지막에 하나로 합쳤다. 총 렌더 시간은 가장 느린 청크 하나 수준으로 줄고 실행 시간 제한도 피했다. 대신 분할·결합 오버헤드와 동시 실행 비용을 얻었다.
정리
미리보기와 렌더가 달라지는 이유는 대부분 서로 다른 경로를 쓰기 때문이다. 이번 설계의 핵심은 두 경로를 하나로 만들고, 그 구조를 운영 가능한 수준으로 단순하게 유지하는 것이었다. 영상처럼 무거운 작업일수록, 무엇을 직접 만들지 않을지가 안정성과 전달 속도를 결정한다.
다음에 읽을 글
전체 글 보기
긴 영상을 한 번에 렌더하지 않은 이유
서버리스 렌더에는 약 10분의 실행 시간 제한이 있다. 긴 영상은 프레임을 청크로 나눠 병렬로 렌더하고 하나로 결합했다. 총 시간은 가장 느린 청크 수준으로 줄었고, 이 병렬성은 렌더를 프레임 번호의 결정적 함수로 설계해 둔 데서 공짜로 얻었다.

리그가 없는 그림을 웹캠 포즈로 움직이기
사용자가 그린 그림에는 본도 가중치도 없다. 랜드마크를 관절로 축약하고, 신뢰도에 따라 스무딩을 조절하고, 가려진 관절은 약한 추론으로 메워 웹캠 포즈를 실시간으로 입혔다. 파이프라인을 관통한 원칙은 하나, 불확실성을 버리지 않고 신뢰도로 들고 다니는 것이었다.

잘 돌아가던 렌더러를 갈아엎은 이유
손그림 캐릭터를 실시간으로 움직이는 렌더러는 잘 돌아갔다. 문제는 캔버스 2D 벡터 엔진이라 GPU를 적극 활용하기 어렵다는 점이었다. 코어를 테스트로 고정하고 새 WebGL 엔진을 옆에서 키운 뒤 구 라이브러리를 걷어냈다. 잘 돌아가는 코드를 버린 이유는 고장이 아니라 구조의 한계 때문이었다.