HTML5를 통한 Vyclone의 대화형 환경 구현
HTML5를 통한 Vyclone의 대화형 환경 구현
개발자들이 HTML5의 잠재력을 끄집어내면서 웹의 매력적인 기능과 생산성이 점차 커지고 있습니다. 이 게스트 블로그 글에서 Plain Concepts의 Anton Molleda는 HTML5 및 Internet Explorer 10과 같은 차세대 브라우저의 다양한 새 기능을 기반으로 하는 소셜 동영상 편집 환경인 Vcylone을 개발하면서 직접 경험하고 느낀 점을 전하고 있습니다. Vcyclone은 포인터 이벤트, 멀티 터치 동작, 하드웨어 가속 캔버스 및 CSS3와 같은 기능을 기반으로 앱과 같은 느낌의 웹 사이트를 만드는 기술입니다.
- Internet Explorer 그룹 프로그램 관리자, Rob Mauceri
안녕하세요,
저는 Plain Concepts에서 근무하는 Anton Molleda입니다. 지난 몇 달 동안 Internet Explorer 팀은 유능한 팀원들과 함께 새로운 소셜 동영상 프로그램인 Vyclone을 개발했습니다. 웹으로 실현 가능한 기능의 한계에 도전하는 것은 웹 개발자로서 제가 가진 열정 중 하나입니다. 운 좋게도 저는 이 프로젝트에 적극적으로 참여할 수 있는 기회를 얻었습니다. 그리고 오늘은 HTML5와 JavaScript만으로 Vyclone용 웹에서 동영상 편집기를 만들기 위해 협력하면서 얻은 몇 가지 교훈을 알려 드리고자 합니다.
Vyclone은 공유한 순간의 여러 장면을 손쉽게 공동으로 만들고 동기화하고 편집할 수 있는 소셜 동영상 플랫폼입니다.
Vyclone은 개발 초기에는 모바일 장치에만 중점을 두었는데, 곧 휴대폰이 녹화 환경은 뛰어나지만 동영상 편집 기능은 장치의 성능과 화면 크기 때문에 한계가 있다는 것을 깨닫게 되었고, 최근 몇 년간 최신 브라우저의 발전 덕분에 이 새로운 도구를 만드는 과정에서 HTML5가 실현 가능한 옵션이 되었습니다.
Vyclone 웹 편집기의 핵심은 다음 세 가지 부분입니다.
동영상 미리보기: 사용자가 만들고 있는 저화질 컷이 표시됩니다(왼쪽에 표시).
Vidgrid: 주어진 지점과 시점을 보여주는 사용 가능한 모든 원본이 사용자에게 제공됩니다(오른쪽에 표시).
시간 표시 막대: 동영상 과정에서 재생되는 원본의 선형 보기를 나타냅니다. 일정 시간 동안 재생되는 원본을 컷이라고 합니다(플레이어 컨트롤 위에 표시).
사용자가 동영상을 재생하고 새로운 컷을 시간 표시 막대에 추가하기 시작하면 새 원본이 동영상 미리보기에 반영되고, 선택된 동영상을 알 수 있도록 원본 파일의 모퉁이가 삼각형으로 강조 표시됩니다.
이 구현 과정에서 우리는 약간의 동영상 조작, 성능 및 사용자 경험으로 매우 흥미로운 도전을 해보았습니다. 웹에서 이를 구현하기 위해 어떤 작업을 수행했는지 자세히 살펴보겠습니다. 우리는 동영상, 캔버스 및 requestAnimationFrame(RAF)을 사용하고 있었습니다. 동영상이 백그라운드에서 재생되는 동안 각 RAF에서 활성 원본을 캔버스(동영상 미리보기)에 그려 보거나 해당 원본의 새 크기 및 위치를 vidgrid로 계산했습니다.
여기까지는 괜찮았지만 사용자가 상호 작용할 수 있도록 한 경우에는 어떻게 될까요? 예를 들어 사용자가 시간 표시 막대를 앞/뒤로 이동하거나 동영상 원본(컷)을 추가/제거하면 어떻게 될까요? 처음에 프로토타입을 만들기 시작했을 때 우리는 이벤트가 실행되는 즉시 표준 접근 방법으로 처리될 것이라 생각했습니다. 왜냐하면 그렇게 알고 있었기 때문입니다.
그러나 이러한 이벤트가 초당 수십 회 또는 수백 회 실행될 수 있는 경우에는 어떻게 될까요? 그리고 이러한 처리기에서 UI를 업데이트해야 하는 경우에는 어떻게 될까요? 변화량이 1픽셀보다 적은 경우에도 초당 130회의 레이아웃 새로 고침을 강제로 실행해야 할까요? 성능 저하에 대해 얘기해 보겠습니다.
컴퓨터에 8GB RAM의 i7이 탑재된 경우에는 이를 처리할 수 있는 충분한 컴퓨팅 성능이 있을 수 있습니다. 하지만 오래된 컴퓨터 또는 ARM 장치를 사용하는 경우에는 어떨까요? 이러한 사용자는 동일한 경험을 할 수 없으며 웹 사이트의 반응 시간이 점점 느려지는 것을 경험하게 될 것입니다.
처음 시도한 방법은 RAF에서 작업을 대기시키는 것이었지만 이 접근 방법에는 몇 가지 문제가 있었습니다. 동일한 "틱"에 대해 동일한 기능을 얻기 위해 RAF를 늘릴 수 있지만 이는 상황을 더욱 악화시킵니다. 이를 해결하기 위한 첫 번째 방법은 동작이 이미 대기 중인 경우 이를 알려 주는 변수를 지정하는 것이었습니다. 예를 들면 다음과 같습니다.
var queued = false; function myAction(){ //your awesome code here queued = false; } function onEvent(evt){ if(!queued){ queued = true; requestAnimationFrame(myAction); } }
이 코드도 나쁘지 않지만 여전히 몇 가지 문제가 있습니다. 이벤트 배치(마우스 또는 포인터) 및 델타와 관련된 작업을 할 경우 이 방법을 가지고 고심할 수 있습니다. 그래서 시간 표시 막대에서 우리가 사용한 해결 방법은 이벤트 값을 누적시키고 이를 myAction에서 처리하는 것입니다.
var deltaX = 0, queued = false; function myAction(){ //your awesome code here uses deltaX deltaX = 0; // we reset the deltaX so it can be incremented // next time onEvent is executed queued = false; } function onEvent(evt){ if(!queued){ queued = true; deltaX = evt.translationX; // in the case of a pointer, if you are // using a mouse you will have to do some // magic with pageX or similar :) requestAnimationFrame(myAction); }else{ deltaX += evt.translationX; } }
이 접근 방법을 사용하면 훨씬 더 준비된 상태로 다음 단계를 진행할 수 있습니다. 우리는 기능을 계속 추가하면서 몇 가지 새로운 문제가 발생하는 것을 알게 되었습니다.
각 requestAnimationFrame에서 이러한 이벤트를 처리하면 컴퓨팅 성능을 떨어뜨리지 않으면서 높은 수준의 응답성을 얻을 수 있었습니다. 그러나 requestAnimationFrame은 기능을 순서대로 실행하기 때문에 기능이 대기 상태에 놓여 있어 시간 표시 막대를 정리하거나 이동하기 전에 불필요하게 그려야 하는 경우가 있었으며 원하는 순서대로 실행하기 위해 번거롭게 코드를 많이 만들어야 했습니다.
이 코드는 다루기가 쉽지 않아 다른 작업이 수행되는 동안 대기 중인 일부 사이클을 놓치게 되므로 우리는 입력을 처리하는 방법을 다시 바꾸기로 했습니다. 이것을 일종의 게임 루프로 생각한 것이 바로 이때였습니다. 단순한 게임 구조도 잘 모른다면 이 게임 루프는 기본적으로 사용자 개입 여부와 상관없이 실행되며 다른 이벤트나 작업이 실행되어야 할 경우에는 따로 분리되는 연속 루프라고 생각하면 됩니다. 게임 프로그래밍 Wikipedia 문서에서 설명하는 유사 코드의 단순화된 게임 루프는 다음과 같을 수 있습니다.
while( user doesn't exit ) check for user input run AI move enemies resolve collisions draw graphics play sounds end while
이것이 바로 우리가 원했던 것이었습니다. RAF를 활용하여 우리는 연속으로 실행되는 틱 함수를 만들고 그 안에 이전 사용자 입력 또는 기타 요소를 바탕으로 수행해야 할 작업을 정했습니다.
vidgrid의 단순화된 틱은 다음과 같은 것입니다.
function tick(){ //we clean if we've changed the size of the quadrant if(needsClean){ cleanCanvas(); } // if we have to change the quadrant's frame because we are // the active one (or the opposite) if(newFrame){ drawFrame(); // we draw just the frame in a separate canvas so it // doesn't need to be calculated all the time, and it // is still faster than copying from an image } //we draw the new frame if we are playing or seeking if(dirty){ draw(); drawFrameInQuadrant(); } requestAnimationFrame(tick); }
needsClean, newFrame 및 더티 값은 이벤트 처리기에서 업데이트됩니다(사용자가 검색하거나 동영상을 재생할 때 등).
사용자 상호 작용에 대한 우리의 생각을 이렇게 게임 루프 방식으로 바꾸고 나서야 성능을 개선하고 편집기에서 코드를 단순화할 수 있었습니다.
요약하자면, 무언가를 구현하는 데 뛰어난 상호 작용이 필요하고 사용자 입력도 많은 경우라면 게임 루프를 통해 보다 쉽게 작업할 수 있는 방법이 없을지 생각해 보십시오. 분명 유익한 결과를 얻을 수 있을 것입니다. 혹시 Vyclone의 새로운 웹 편집기를 확인할 기회가 없었다면 지금 확인해 보십시오. Vyclone.com의 아무 동영상에서나 'Remix'를 클릭하면 웹 편집기가 나타납니다. 이 편집기는 마우스와 터치 입력 모두에서 원활하게 작동합니다. 개인적으로 저는 Surface Pro에서 이 기능을 사용할 것을 적극 권장합니다.
마음껏 즐기시고 궁금한 사항이 있으면 아래에 댓글을 남겨 주세요.
- Plain Concepts, Anton Molleda