hbc studio › 제작기 › hbc studio

꿀이 흘러내리는 첫 화면을 휴대폰에서 부드럽게: 20fps에서 60fps까지

honeybeecook.com의 첫 화면은 스크롤을 내리면 꿀이 흘러내리는 애니메이션이에요. 사실은 영상이 아니라 150장의 이미지예요. 스크롤 위치에 맞는 장을 캔버스에 그려서 움직이는 것처럼 보이게 해요. 컴퓨터에서는 부드러웠는데, 휴대폰에서는 아니었어요.

먼저 재기

휴대폰처럼 느린 환경(빠른 4G, CPU 4배 느리게)을 만들어 재 봤어요. 스크롤 애니메이션이 초당 약 20프레임이었고, 100밀리초가 넘게 멈추는 프레임이 다섯 번 있었어요. 원인은 세 가지였어요.

  • 150장의 풀HD 이미지를 한꺼번에 요청해서, 무작위 순서로 도착했어요.
  • 이미지를 그리는 순간에 화면 스레드에서 디코딩하고 있었어요.
  • 그 와중에 1.75MB짜리 한글 폰트가 같은 대역폭을 나눠 쓰고 있었어요.

꿀만 남기고 자르기

프레임은 1920×1080으로 렌더링됐지만, 꿀은 가운데에만 있고 나머지는 전부 투명했어요. 그래서 꿀이 있는 576×1040 영역만 잘라 냈어요. 픽셀 수가 3.5배 줄었어요. 그리는 코드는 여전히 원래 크기의 프레임인 것처럼 위치를 계산해서, 화면에 보이는 그림은 똑같아요(픽셀 평균 차이 약 1/255).

성긴 것부터 촘촘하게 받기

모든 프레임을 한꺼번에 받는 대신, 첫 장을 받고, 16장마다 한 장, 8장마다, 4장마다, 2장마다, 그리고 나머지 순서로 받아요. 한 번에 6장씩이요. 이렇게 하면 다 받기 전에 스크롤을 시작해도, 군데군데 비어 있는 게 아니라 고르게 듬성듬성한 프레임이 있어서 꿀이 멈췄다가 튀지 않아요.

이 단계에서 폰트를 줄이는 일도 함께 했어요(한글 폰트를 26KB로 줄인 이야기). 결과는 전체 다운로드 7.75MB → 5.6MB, 폰트 준비 6초 → 0.6초, 애니메이션 약 31fps에 100밀리초 넘는 멈춤 없음.

디코딩을 화면 밖으로

31fps도 부족했어요. 페이지를 열자마자 스크롤하는 상황을 기록해 보니, 화면 스레드에서 30~50밀리초짜리 이미지 디코딩이 31~37번 일어나고 있었어요. 이미지를 캔버스에 그리면 브라우저가 그 순간 디코딩을 하는데, 미리 디코딩을 요청해 둬도 마찬가지였어요.

그래서 프레임을 이미지가 아니라 바이트로 받아서 ImageBitmap으로 바꿨어요. ImageBitmap은 화면 스레드 밖에서 디코딩되고, 그릴 때는 바로 그려져요. 대신 한 장이 메모리에서 약 2.4MB를 차지해서, 지금 스크롤이 가리키는 프레임 앞뒤 10장만 디코딩해 두고 16장보다 먼 건 놓아줘요.

같은 측정에서 화면 스레드 디코딩은 0번이 됐고, 애니메이션은 거의 60fps(4초 동안 239프레임, 50밀리초 넘는 프레임 없음)를 유지했어요. 캔버스에 그려진 결과는 픽셀 단위로 같아요. 덤으로, 아무 데서도 쓰지 않던 7.4MB짜리 영상 파일도 지웠어요.

정리하면

  • 느린 휴대폰을 흉내 내서 먼저 재고, 숫자로 고친 걸 확인했어요.
  • 투명한 부분은 받을 필요가 없어요. 그리는 쪽에서 원래 위치만 기억하면 돼요.
  • 스크롤에 맞춰 보여 줄 거라면, 받는 순서도 스크롤에 맞춰야 해요.
  • 그리는 순간의 디코딩이 멈춤의 큰 원인이었어요. ImageBitmap으로 화면 밖으로 옮겼어요.

hbc studio(허니비와 요리사)는 아이디어를 완성된 웹과 앱으로 만드는 스튜디오예요. 지금까지 만든 서비스는 서비스 소개에서 볼 수 있어요.

다른 제작기

제작기 전체 보기