← 과제 목록

[과제] 3주차) ThorVG 활용사례 조사 조정민

@YoungB0
  • #과제
목차

ThorVG 공식 쇼케이스를 보면 Lottie Creator가 ThorVG로 Canvas 엔진을 돌린다고 소개되어 있습니다. 이게 실제로 그런지, 브라우저에서 직접 확인해봤습니다.

  • 대상: Lottie Creator (LottieFiles의 웹 기반 Lottie 편집기)
  • 방법: 크롬 개발자 도구 (Network, Console, Performance)
  • 조건: 로그인하지 않은 게스트 모드, Chrome, 데스크톱 image

왜 이 방법으로 조사했나

Lottie Creator는 소스코드가 공개되어 있지 않습니다. 그래서 코드를 읽는 대신, 브라우저가 실제로 무엇을 받아서 실행하는지를 관찰하는 쪽으로 접근했습니다.

먼저 밝혀둘 것이 있습니다. 이 글은 전부 밖에서 본 내용입니다. 어떤 파일이 로드되고 어디에 그려지는지까지는 확인할 수 있었지만, 그 안에서 어떤 구조로 동작하는지는 알 수 없었습니다. 확인한 것과 추측한 것을 구분해서 적었습니다.

ThorVG WASM이 실제로 로드됩니다

Network 탭에서 wasm으로 필터를 걸고 새로고침했더니 두 개가 잡혔습니다.

image
파일크기시간Initiator
thorvg_bg-BIwBujB_.wasm606 kB149 msvendor-BEpzInOD.js
dotlottie-player.wasm639 kB139 ms(다른 청크)

파일명에 thorvg가 그대로 남아 있어서 확인이 쉬웠습니다. 번들링 과정에서 해시가 붙긴 했지만 이름 자체는 뭉개지 않은 것 같습니다.

전체 URL은 콘솔로 확인했습니다.

performance.getEntriesByType('resource')
  .filter(r => r.name.includes('wasm'))
  .map(r => r.name)
['https://creator.lottiefiles.com/assets/thorvg_bg-BIwBujB_.wasm']

외부 CDN이나 npm이 아니라 자기 도메인의 /assets/ 아래에 직접 올려두고 있었습니다. 빌드 결과물을 그대로 배포에 포함시킨 것으로 보입니다.

눈에 띈 것은 WASM이 하나가 아니라 두 개라는 점이었습니다. ThorVG와 dotLottie 플레이어가 각각 따로 로드되고, Initiator도 서로 다릅니다. ThorVG는 vendor-BEpzInOD.js라는 공용 청크에서 요청되는데 dotLottie는 해시 이름의 다른 청크에서 옵니다. 로드 경로가 나뉘어 있다는 뜻인 것 같습니다.

파일명 thorvg_bg_bg 접미사도 궁금했습니다. 찾아보니 wasm-bindgen이 Rust 코드를 WASM으로 빌드할 때 붙이는 관례라고 합니다. ThorVG 자체는 C++인데, LottieFiles가 Rust로 만든 dotlottie-rs를 공개하고 있는 걸 보면 그쪽 경로를 거쳤을 가능성이 있어 보입니다. 다만 이건 이름만 보고 한 추측이고 확인은 못 했습니다.

어디에 그리는지 찾아보기

다음으로 캔버스를 찾아봤습니다. 콘솔에서 페이지 안의 <canvas>를 전부 뽑아봤습니다.

[...document.querySelectorAll('canvas')].map(c => ({
  w: c.width, h: c.height, id: c.id, cls: c.className
}))

7개가 나왔습니다.

#크기id
0~330 × 33(없음)
4249 × 124(없음)
5300 × 150canvas
60 × 590snap-canvas

0~4번은 크기로 봐서 사이드바의 작은 미리보기나 썸네일로 보였습니다. 6번 snap-canvas는 클래스에 pointer-events-none이 붙어 있어서 정렬 가이드를 그리는 오버레이인 것 같았습니다.

5번만 id="canvas"로 이름이 붙어 있었는데, 크기가 300×150이라 처음엔 이게 아닌가 싶었습니다. 나중에 찾아보니 300×150은 HTML <canvas>의 기본 크기였습니다. 크기를 지정하지 않으면 이 값이 됩니다. 제가 이 목록을 뽑은 시점이 편집기가 완전히 뜨기 전이어서 아직 크기가 안 잡힌 상태였던 것 같습니다.

편집기가 뜬 뒤에 다시 뽑아봤어야 했는데 그건 놓쳤습니다.

대신 다른 쪽에서 확인이 됐습니다. Performance 탭을 열어두고 캔버스의 별을 클릭하고 드래그해봤더니, Interactions 목록에 이렇게 기록됐습니다.

image
pointer    canvas#canvas.relative              32 ms
pointer    canvas#canvas.relative              16 ms
pointer    <node>                              16 ms
pointer    div#transform-controls-target-inner 48 ms

제 입력이 canvas#canvas로 들어갔다고 브라우저가 직접 알려준 셈입니다. 5번이 실제 편집 캔버스가 맞았습니다. 추측이 아닌 측정으로 확인된 부분이라 이게 확실한 근거입니다.

응답 시간은 16~32 ms였습니다. 60fps 한 프레임이 약 16.7 ms니까 대체로 한두 프레임 안에 반응한 것으로 보입니다. 다만 이 숫자는 제 PC 환경 하나에서 나온 값이라 일반화하긴 어렵습니다만

편집기 화면에는 씬 크기가 512 × 512, FPS 30으로 표시됩니다. 별 하나짜리 아주 단순한 씬이었습니다.

div#transform-controls-target-inner도 같이 잡히는데, 도형을 감싸는 파란 조절 핸들은 캔버스에 그려진 게 아니라 별도의 DOM 요소인 것 같습니다. 캔버스가 그림을 그리고 UI는 그 위에 HTML로 얹는 구조로 보입니다.

로드 구조에서 보이는 것

필터를 지우고 전체 요청을 봤습니다.

image
108 requests | 7.4 MB transferred | 22.4 MB resources | DOMContentLoaded: 1.14 s

전송량 7.4 MB와 자원 크기 22.4 MB의 차이는 gzip 같은 압축 때문일 것입니다.

여기서 주의할 점이 하나 있었습니다. 목록에 FloatingActionButton.js, local-storage.js, google-docs-fte.js, express-fte.js 같은 파일들이 섞여 있는데, Initiator를 보면 content-script-utils입니다. 사이트가 아니라 제 브라우저에 깔린 확장 프로그램이 끼워넣은 것이었습니다. 처음엔 이것도 사이트 자원인 줄 알았습니다

그리고 하단의 Finish: 15.7 min도 로딩 시간이 아닙니다. 개발자 도구를 열어둔 채로 계속 만졌기 때문에 나온 값입니다. 실제 초기 로딩 지표는 DOMContentLoaded: 1.14 s 쪽입니다.

사이트 자체 자원 중 눈에 띈 것들입니다.

파일크기
vendor-BEpzInOD.js2,247 kB
index-DZKTzMOb.js891 kB
thorvg_bg-BIwBujB_.wasm606 kB
quickjs-emscripten-Dr2hb7_q.js10.7 kB

quickjs-emscripten이라는 이름이 흥미로웠습니다. QuickJS는 작은 자바스크립트 엔진인데, 이걸 왜 또 넣었을까 싶었습니다. Lottie에는 Expressions라는 스크립트 기능이 있어서 그것 때문일 수도 있겠다 싶었지만, 근거는 없습니다.

다만 파일 크기가 10.7 kB밖에 안 됩니다. 엔진 본체가 아니라 로더나 래퍼 정도인 것 같고, 실제 엔진은 따로 있거나 필요할 때 받아오는 구조일 수 있습니다. 이번 관찰에서는 그런 요청을 못 봤습니다.

data:font/ttf;base64...로 149 kB짜리 폰트가 들어오는 것도 보였는데, 텍스트 레이어용 기본 폰트를 JS 안에 인라인으로 넣어둔 것 아닐까 짐작만 했습니다.

아직 모르는 것

관찰로 확인되지 않아 남겨둔 것들입니다.

  • performance API로는 ThorVG 하나만 잡히고 dotlottie-player.wasm은 안 나옵니다. Network 탭에는 분명히 있는데 performance.getEntriesByType('resource') 결과에는 없었습니다. Worker 안에서 로드되거나 다른 컨텍스트에서 요청되면 이럴 수 있다고 하는데, 확인은 못 했습니다. 목록에 blob:https://creator.lottiefiles... 항목이 있어서 관련이 있을 수도 있겠다 싶었습니다.
  • ThorVG와 dotLottie가 각각 무슨 역할인지 모르겠습니다. 편집 캔버스는 ThorVG가, 완성된 애니메이션 재생은 dotLottie가 맡는 구조가 아닐까 싶었지만 근거가 없습니다. 둘 다 Lottie를 그릴 수 있는데 왜 나눠 뒀는지가 궁금합니다.
  • 렌더 백엔드가 SW인지 WebGL인지 확인 못 했습니다. canvas.getContext()를 호출하면 컨텍스트가 새로 생성되면서 실제 동작에 영향을 줄 수 있을 것 같아서 시도하지 않았습니다. 다른 방법이 있는지 아직 모르겠습니다.
  • 606 kB에 무엇이 들어갔는지 모릅니다. ThorVG 코어가 최소 150 kB 정도라고 하는데, 어떤 로더와 백엔드가 포함되어 이 크기가 됐는지는 파일만 봐서는 알 수 없었습니다.
  • 게스트 모드에서만 봤습니다. 로그인하면 다른 파일이 더 올 수도 있습니다.

마치며

웹 1주차 과제에서 @thorvg/webcanvas를 직접 빌드했었는데, 이 결과물이 thorvg.wasm이었는데, 그때는 그게 실제 서비스에서 어떤 모습으로 쓰이는지 감이 없었습니다.

이번에 Network 탭에서 thorvg_bg-BIwBujB_.wasm이 606 kB로 내려오는 걸 보니, 제가 빌드했던 것과 같은 종류의 파일이 실제 제품에서도 그대로 쓰이고 있다는 게 조금 실감이 났습니다.

한편으로는 밖에서 볼 수 있는 게 생각보다 제한적이라는 것도 느꼈습니다. 파일이 무엇이고 어디에 그려지는지까지는 알 수 있었지만, 그 안에서 어떻게 동작하는지는 당연하게도 알기가 어려운것같습니다.

댓글

Discussion 원문