The Front-end of Middle-earth

A walkthrough of multi-device development

HTML5 Rocks

"호빗 체험: 중간계로의 여정" 크롬 실험(Chrome Experiments)의 개발에 대한 첫번째 글에서 우리는 모바일 디바이스를 위한 WebGL 개발에 대해 중심을 두었습니다. 이 글에서 우리는 HTML5 프론트엔드를 개발하기 위한 나머지에서 마주치게 되는 도전들, 문제들 그리고 해결방법들에 대해 논의할 것입니다.

동일 사이트에 대한 3가지 버전들

이 실험을 데스크탑 컴퓨터와 모바일 디바이스에서 동작하기 하기 위한 적용하는 것에 대해 화면 사이트와 디바이스 역량 관점에서 가볍게 얘기하는 것으로 시작해보도록 하겠습니다.

모든 프로젝트는 영화로부터의 마법을 지켜줄 풍경 중심의 고정된 프레임을 통해 경험을 유지할 수 있도록 현명하게 디자인된 아주 "영화적인" 스타일에 기초하고 있습니다. 프로젝트의 커다란 부분들이 인터랙티브한 미니 "게임들"로 구성되어 있으므로 프레임이 오버플로를 일으킬 것이라는 걱정은 하지 않아도 되었습니다.

우리는 다른 크기의 디자인을 어떻게 적용할지에 대한 예제로써 랜딩 페이지를 택하기로 하였습니다.

독수리가 우리를 랜딩 페이지로 그냥 떨어뜨려 줍니다.

사이트는 데스크탑, 태블릿 그리고 모바일과 같은 각기 다른 3가지 모드를 가지고 있습니다. 우리는 그냥 레이아웃만 다루는 것이 아니라 런타임에 로딩되는 에셋(Asset)들을 다루고 다양한 성능 최적화를 더할 필요가 있었습니다. 데스크탑 컴퓨터나 랩탑보다 더 고해상도를 가지지만 휴대폰보다 더 나쁜 성능을 가지는 디바이스들을 가지고 궁극적인 규칙의 셋을 정하는 것은 쉬운 일이 아니었습니다.

우리는 모바일 디바이스 여부를 검사하고 (645px 이상의) 모바일 디바이스들 중에 태블릿을 특정하기 위한 뷰포트 크기 테스트를 위해 User-agent 데이터를 사용하고 있습니다. 레이아웃은 미디어쿼리(Mediaquery)에 기반하거나 자바스크립트로 relative/percentage 포지셔닝되므로 사실 각기 다른 모드는 모든 해상도를 렌더링할 수 있습니다.

이렇게 그리드나 규칙에 기반하지 않고 다른 섹션들과 꽤나 다른 경우를 디자인할 때 무엇을 중단점(Breakpoint)나 스타일로 사용할 것인지에 관해서는 특정한 엘리먼트나 시나리오에 정말 의존적입니다. 일단 훌륭하게 SASS 혼합하거나 미디어 쿼리를 가지고 완벽한 레이아웃을 설정하는 것보다는 더 많은 일이 발생할 것이고 그 후에도 마우스 위치에 기반한 효과나 동적인 객체들을 추가하는 것이 필요하고 이러한 모든 것을 자바스크립트 안에 재작성하는 것으로 마무리할 것입니다.

또한 현재의 모드를 가지는 클래스를 헤더 태그 안에 추가하여 (SCSS 내의) 이 예제에서처럼 우리의 스타일 안에서 그 정보를 다음과 같이 사용할 수 있습니다.

.loc-hobbit-logo {

  // 기본 값은 여기에 있습니다.

  .desktop & {
     // 데스크탑 모드는 여기에서만 적용됩니다.
  }

 .tablet &, .mobile & {

   // 모바일과 태블릿은 아마 에셋(Asset)이 다를 것입니다.

   @media screen and (max-height: 760px), (max-width: 760px) {
     // 중단점에-특정한 스타일들.
   }

   @media screen and (max-height: 570px), (max-width: 400px) {
     // 중단점에-특정한 스타일들.
   }
 }
}

우리는 모든 크기를 실감형 웹 체험을 만들 때 꽤나 도전적일 수 있는 약 360x320으로 낮추어 지원할 수 있습니다. 우리는 여러분들이 가능한한 더 큰 뷰포트에서 사이트를 경험하기를 원했기 때문에 데스크탑 상에서 스크롤바를 보여주기 바로 직전의 크기를 가지고 있습니다. 모바일 디바이스 상에서 디바이스의 랜드스케이프 전환 여부를 확인하여 인터렉티브한 체험을 할 수 있도록 랜드스케이프(Landscape)와 포트레이트(Portrait) 모드를 모두 허용하기로 결정했습니다. 이에 대한 논쟁은 포트레이트 모드에서의 실감은 랜드스케이프만큼이 아니라는 것이었지만 사이트는 꽤 잘 확장되었으므로 그대로 진행하였습니다.

DeviceOrientation 이벤트 컨텐츠 레이아웃은 중단점들과 CSS에 의해 조절되지만 또한 게임-루프를 멈추고 올바른 상태를 유지하기 위해 자바스크립트에서 이벤트를 다룰 필요가 있습니다. window.orientation 내의 값은 표준이 아니며 디바이스마다 다양하기 때문에 이에 의존할 수 없음을 드러내게 됩니다. 이벤트를 리스닝하는 대신에 방향을 결정하기 위해 window.innerWidthwindow.innerHeight를 구해볼 수 있습니다.

레이아웃이 입력 형식(Input type), 디바이스 방향(Orientation), 센서들 등과 같은 기능 검출과 혼합될 수 없음을 주지하는 것은 중요합니다. 그러한 기능들은 이 모든 모드에서 존재할 수 있으며 지속될 수 있습니다. 마우스와 터치를 동시에 지원하는 것이 그 예 중의 한가지입니다. 레티나의 품질 이득은 모든 성능의 대부분과 또 다르고 가끔은 낮은 품질이 더 나을 수도 있습니다. 레티나 디스플레이 상의 WebGL 체험들에서 캔버스를 절반의 해상도가 그 예로써 그렇지 않으면 4배의 픽셀을 렌더링하여야 할 것입니다.

여러분은 크롬 개발자도구에서 디바이스의 에뮬레이션을 통해 브라우저에서 모든 디바이스의 크기를 쉽게 시도해볼 수 있습니다. 모바일, 태블릿 그리고 데스크탑 버전들에서 모드를 변경할 때 올바른 의존성들과 설정들을 사용하기 위해 새로고침을 해야만 할 것입니다.

우리는 개발 중에 개발자도구에서 에뮬레이터 도구를 종종 사용하며 특히 크롬 카나리는 새로운 개선된 기능들과 많은 프리셋들을 가지고 있습니다. 빠른 디자인 검증에 좋은 방법입니다. 우리는 여전히 실제 디바이스를 정규적으로 시험할 필요가 있습니다. 전체화면(Fullscreen)을 적용하고 있기 때문이라는 것이 한가지 이유였습니다. 스크롤 시에 대부분의 경우 세로로 스크롤되는 페이지들이 브라우저의 UI를 가리지만 (현재 iOS7의 사파리가 이 문제를 가지고 있습니다.) 그것과 별개로 모든 것을 맞추어야만 했습니다. 또한 에뮬레이터에서 프리셋을 사용하고나서 여백의 손실의 시뮬레이션하기 위해 화면 크기 설정을 변경해야 했습니다. 실 디바이스에서의 시험은 또한 메모리-사용과 성능의 모니터링에도 중요합니다.

상태 다루기

랜딩 페이지 후에 우리는 중간계의 지도에 착륙합니다. 여러분은 URL의 변경을 눈치채셨나요? 사이트는 라우팅(Routing)을 다루기 위해 History API를 사용하는 단일 페이지 어플리케이션(Single Page Application, SPA)입니다.

사이트의 각 섹션은 DOM 엘리먼트, 전환 효과(Transition), 에셋의 로딩, 배치 등과 같은 기능의 보일러플레이트를 상속하는 그 자신의 객체들입니다. 사이트의 다른 부분을 탐색할 때 섹션은 초기화되고 현재 로딩된 섹션에 대한 DOM과 에셋들로부터 엘리먼트들이 추가되거나 삭제됩니다.

언제라도 사용자가 브라우저의 뒤로 가기 버튼을 누르거나 메뉴를 통해 탐색할 수 있기 때문에 그 모든 것들은 어떠한 지점에서의 배치에 대한 필요를 만들 수 있습니다. 타임아웃과 애니메이션들은 멈추거나 폐기될 필요가 있거나 원치않는 동작, 에러 그리고 메모리 릭을 발생할 수 있습니다. 이는 언제나 쉬운 일이 아니며 가능한한 빠르게 모든 것을 지원할 필요가 있고 마감이 다가오고 있을 때는 더더욱 그렇습니다.

흥분하지 말고 저 이벤트 리스너들을 추가합시다. 모든 객체에 대한 배치(Dispose) 함수 추가의 사례를 만들어 봅시다. 타이머의 종료를 감시하고 뒤에서 트윈(Tween)을 수행해야 합니다. 만약 트위닝(Tweening)을 한다면 TweenMax.killTweensOf(foo)와 해당하는 것을 사용하거나 참조들을 저장한 뒤 콜백이 호출되면 그들을 멈추도록 합니다. 동적인 DOM 엘리먼트들의 추가를 제거하시기 바랍니다. 메모리 사용과 릭을 계속 지켜볼 수 있도록 정기적으로 프로파일링 도구를 사용하세요.

역주: 트윈(Tween)이란 애니메이션 시 특정한 시점들로 이루어진 키 프레임 사이의 연속적인 프레임을 생성하기 위해 중간 시간들에 대한 속성 정보를 계산하여 자연스럽게 애니메이션이 이어지게 하기 위한 방법입니다. 트위닝이 없으면 키프레임들을 아주 상세하게 (예를 들어 24fps를 원한다면 1초당 24개의 키프레임들을) 만드는 작업이 필요해집니다. 따라서 요점(Key)이 되는 프레임만을 지정하여 런타임에 사이의 프레임들을 생성하는 트위닝은 애니메이션의 데이터량과 편리성면에서 아주 중요한 기능입니다. 자세하게 알고 싶으신 분들은 보간(Interpolation)이나 CSS 타이밍 함수(Timing Function) 등에 대해서도 함께 찾아보시면 도움이 될 것입니다.

위치들의 강조

중간계의 아름다운 설정들과 캐릭터들을 뽐내기 위해 우리는 드래그(Drag)하거나 수평으로 쓸어볼(Swipe) 수 있는 이미지와 텍스트 컴포넌트의 모듈화 시스템을 구축했습니다. 클립이 끝마칠 때까지 옆으로의 움직임을 멈춘 이미지 시퀀스에서처럼 우리는 각기 다른 범위에서 각기 다른 속도를 가지기를 원했기 때문에 여기서 스크롤바를 활성화하지 않았습니다.
스크롤바는 사이트의 행동에 대한 기대 사항을 정의합니다. 웹사이트가 이 조작을 장악할 때 그것은 나쁜 사용자 경험이 될 수 있습니다.
스란듀일의 홀(Thranduil's Hall) 타임라

타임라인

개발을 시작했을 때 우리는 각 위치를 위한 모듈의 컨텐츠를 알지 못했습니다. 우리가 아는 것은 다른 형태의 미디어와 정보를 여섯번이나 모든 것을 다시 빌드하지 않아도 6개의 다른 위치를 보여줄 수 있는 자유를 주는 수평적인 타임라인에서 보여줄 템플릿화된 방법을 원한다는 것이었습니다. 이를 관리하기 위해 설정에 기반하여 모듈들의 패닝과 모듈의 행동들을 다루는 타임라인 컨트롤러를 생성했습니다.

모듈과 행위(Behaviour) 컴포넌트

우리가 추가적으로 지원한 각기 다른 모듈들은 이미지-시퀀스, 스틸 이미지, 패럴렉스 씬, 포커스-쉬프트 씬 그리고 텍스트였습니다. 패럴렉스 씬(Parallax scene) 모듈은 정확한 위치들을 위해 뷰포트 진행을 리스닝하고 있는 커스텀 레이어들로 이루어진 투명한 배경을 가지고 있습니다. 포커스-쉬프트 씬(Focus-shift scene)은 팰럴렉스 버킷의 변종으로, 추가적으로 포커스의 변경을 시뮬레이션하기 위해 페이드인/아웃을 하는 각 레이어를 위해 2개의 이미지를 사용하고 있습니다. 블러(Blur) 필터를 사용하려고 하였으나 여전히 비싸므로 이를 위한 CSS 쉐이더를 기다릴 것입니다. 텍스트 모듈 내의 컨텐츠는 TweenMax 플러그인인 Draggable로 드래그가 가능합니다. 세로 스크롤을 위해 스크롤휠이나 2손가락 쓸기(Swipe) 역시도 사용할 수 있습니다. 스와이프나 릴리즈 시에 내던지는 듯한 형태(Fling-style)의 물리를 추가하는 throw-props-plugin에 주의하시기 바랍니다. 모듈은 또한 컴포넌트의 집합과 같이 추가된 각기 다른 동작을 가질 수 있습니다. 그들 모두는 그들 자신의 목적 셀렉터들과 설정을 가집니다. 엘리먼트를 움직이기 위한 Translate, 줌을 위한 Scale, 정보의 오버레이를 위한 핫스팟, 시각적인 테스팅을 위한 디버그 메트릭스, 시작-타이틀 오버레이, 플레어 레이어 그리고 몇몇가지 것들. 이들은 DOM에 추가되거나 모듈 내의 그들의 대상 엘리먼트을 조작할 것입니다. 이와 함께 어떠한 에셋들이 로딩될지와 다른 종류의 모듈과 컴포넌트를 설치를 정의하는 설정 파일만으로 각기 다른 위치들을 생성할 수 있습니다.

이미지 순서

성능과 다운로드 크기의 관점에서 모듈에 있어 가장 커다란 도전은 이미지의 순서(Sequence)입니다. 이 주제에 대해 읽을만한 많은 것들이 있습니다. 모바일과 태블릿 상에서 이를 스틸 이미지로 대치했습니다. 모바일에서 괜찮은 품질을 원한다면 데이터가 너무 많아 디코딩을 할 수 없고 메모리에 저장을 할 수가 없습니다. 다음고 같은 여러가지 대체 솔루션들을 시도했습니다. 먼저 배경 이미지와 스프라이트 시트를 사용하였으나 메모리 문제와 GPU가 스프라이트시트를 교체할 필요가 있을 때 발생하는 랙으로 이어졌습니다. 그 후에는 이미지 엘리먼트를 교체하는 것을 시도하였으나 그것 또한 너무 느렸습니다. 스프라이트시트로부터 프레임을 캔버스에 그리는 것은 가장 성능이 좋았으므로 우리는 그를 최적화하기 시작했습니다. 각 프레임에 대한 연산 시간을 절약하기 위해 임시 캔버스를 통해 미리 처리된 이미지 데이터를 캔버스에 썼으며 putImageData()를 이용하여 배열에 저장하고 디코딩하여 사용할 수 있도록 준비했습니다. 원본 스프라이트시트는 그후에 가비지 콜렉션이 될 수 있으므로 메모리에 필요한 최소한의 데이터만을 저장했습니다. 아마도 디코딩되지 않은 이미지들을 저장하는 것이 실제적으로 더 작았겠지만 이 방식으로 시퀀스를 문지르는 동안에도 더 나은 성능을 가질 수 있었습니다. 프레임은 불과 640x400으로 꽤 작았지만 문질러지는 동안 보여지기만 할 것입니다. (문지르는 것을) 멈췄을 떄 고해상도 이미지를 로딩하고 빠르게 페이드인 처리를 할 것입니다.

var canvas = document.createElement('canvas');
canvas.width = imageWidth;
canvas.height = imageHeight;

var ctx = canvas.getContext('2d');
ctx.drawImage(sheet, 0, 0);

var tilesX = imageWidth / tileWidth;
var tilesY = imageHeight / tileHeight;

var canvasPaste = canvas.cloneNode(false);
canvasPaste.width = tileWidth;
canvasPaste.height = tileHeight;

var i, j, canvasPasteTemp, imgData,
var currentIndex = 0;
var startIndex = index * 16;
for (i = 0; i < tilesY; i++) {
  for (j = 0; j < tilesX; j++) {
    // Store the image data of each tile in the array.
    canvasPasteTemp = canvasPaste.cloneNode(false);
    imgData = ctx.getImageData(j * tileWidth, i * tileHeight, tileWidth, tileHeight);
    canvasPasteTemp.getContext('2d').putImageData(imgData, 0, 0);

    list[ startIndex + currentIndex ] = imgData;

    currentIndex++;
  }
}

스프라이트시트는 Imagemagick을 사용하여 생성할 수 있습니다. 여기 어떻게 폴더 내의 모든 이미지에 대한 스프라이트시트를 생성하는지를 보여주는 간단한 GitHub의 예제가 있습니다.

모듈 애니메이션하기

타임라인 상에 모듈들을 위치시키기 위해서는 타림라인의 숨겨진 표현, 오프스크린 출력, ‘playhead’과 타임라인 폭의 추적을 유지하여야 합니다. 이들은 그냥 코드로도 할 수 있지만 개발과 디버깅 시 시간적인 표현을 이용하는 것이 좋습니다. 실제로도 실행 시 해상도를 설정하기 위해 크기만 갱신했습니다. 몇 모듈들은 뷰포트를 채우고 몇몇은 그들만의 비율을 가지고 있으므로 모든 해상도에 대한 스케일과 위치를 모두 진행하는 것은 약간 트릭에 가까우며 모든 것이 많이 잘리지 않은 상태로 잘 보이게 됩니다. 각 모듈은 2개의 진행 표시들을 가지고 있는데 하나는 스크린 상의 표시 위치를 위한 것이고 하나는 모듈 그 자체의 재생 시간(Duration)을 위한 것입니다. 패럴랙스 이동(Parallax movement)의 제작 시 뷰 안에서 원하는 위치와 동기화를 하기 위해 객체의 시작과 끝 위치를 계산하는 것은 종종 괴롭습니다. 언제 뷰에 진입하고 언제 내부적인 타임라인을 재생할지 그리고 언제 그것을 다시 뷰 밖으로 움직일지를 정확하게 아는 것는 좋은 일입니다.

각 모듈은 자신의 투명도를 조정하기 위한 최상위의 미묘한 검정 레이어를 가지고 있으므로 그것이 중앙에 위치할 때 완전히 투명해집니다. 이는 여러분이 체험을 개선할 수 있도록 한번에 하나의 모듈에 집중할 수 있도록 해줍니다.

페이지 성능

기능적인 프로토타입에서 멈칫거리지 않는(jank-free) 릴리즈 버전으로 이동하는 것은 브라우저에서 무엇이 일어나는지에 대한 아는 것을 추측하는 것으로부터 시작하는 것을 의미합니다. 여기 여러분의 가장 좋은 친구가 되어줄 크롬 개발자도구가 있습니다. 우리는 사이트를 최적화하는데 꽤 많은 시간을 소모합니다. 물론 부드러운 애니메이션을 얻기 위해 하드웨어 가속을 강제하는 것은 가장 중요한 도구 중의 하나입니다. 그러나 화려한 컬럼들과 크롬 개발자도구의 붉은 사각형을 사냥하는 것 또한 그렇습니다. 이 주제에 관한 많은 좋은 글들이 있으며 그것들을 전부 읽어보셔야 할 것입니다. 생략되는 프레임을 제거하는 것에 대한 보상은 즉각적입니다만 그러므로 그것들이 다시 되돌아올 때는 좌절하게 됩니다. 그리고 그렇게 될 것입니다. 이는 반복이 필요한 프로세스의 진행이라고 할 수 있습니다.

(카나리에서만 되는) 레이어 패널과 크롬 개발자도구의 "paint rectagles"를 살펴보시기 바랍니다. 예를 들어 만약 자식 엘리먼트가 프레임마다 업데이트되어야하고 페인트되어야 한다면 가능한한 많이 페인팅이 필요한 영역을 최소화하기 위해 레이어를 재배치하여 더 빨라질 수 있는지에 대해 확인하여야 합니다.

저는 속성, 트랜스폼 그리고 CSS의 트위닝(Tweening)을 위해 Greensock의 TweeenMax를 사용하는 것을 좋아합니다. 새로 추가된 레이어와 같은 구조를 시각화하는 컨테이너에 대해 생각해보겠습니다. 존재하는 트랜스폼은 새로운 트랜스폼에 의해 덮어씌워질 수 있다는 것을 염두에 두어야 합니다. CSS 클래스에서 하드웨어 가속을 강제하는 translateZ(0)는 만약 2D 값만을 트위닝한다면 2D 매트릭스로 대치될 수 있습니다. 저러한 경우에서 레이어를 가속 모드에 유지하기 위해서는 트윈(Tween)에서 2D 매트릭스 대신 3D 매트릭스를 생성하는 “force3D:true” 속성을 사용하여야 합니다. 스타일을 설정하기 위해 여러분이 CSS와 자바스크립트 트윈을 결합할 때 잊어버리기 쉽습니다.

불필요한 곳에서 하드웨어 가속을 강제하지 마시기 바랍니다. GPU 메모리가 빠르게 차버릴 수 있고 많은 컨테이너를 하드웨어로 가속하고 싶을 때 원치않는 결과를 발생할 수 있으며 특히 많은 메모리 제한을 가지는 iOS에서는 더 그렇습니다. 모바일 모드에서 더 작은 에셋들을 로딩하고 CSS로 그것들을 스케일링하고 몇가지 효과를 중지하는 것은 거대한 향상을 만들어낼 수 있습니다.

메모리 릭은 우리의 스킬을 개선할 필요가 있는 또다른 필드입니다. 각기 다른 WebGL들에서 탐색이 일어날 때 대량의 객체들, 재질(Material)들, 텍스쳐, 기하정보(Geometry)들이 생성됩니다. 만약 여러분이 탐색을 멀리해서 섹션이 제거될 때 그러한 것들이 가비지 콜렉션을 준비하지 않았다면 아마도 잠시 뒤 메모리가 부족할 때 디바이스에서 실행이 강제종료될 것입니다.

배치함수의 실패로 인해 날아간 섹션
훨씬 낫습니다!

타임라인을 기록하고 힙의 스냅샷을 캡춰하는 개발자도구는 메모리 릭을 발견하기 위한 상당히 직관적인 워크플로우를 제공합니다. 3D 기하정보(Geometry)나 특정한 라이브러리와 같은 객체를 특정할 수 있다면 더 쉽게 이를 가려낼 수 있습니다. 위의 예제에서 3D 장면은 여전히 주위에서 맴돌고 있으며 또한 삭제되지 않은 기하정보가 저장된 배열이 있습니다. 만약 살아 있는 객체에 지정하는 것이 어렵다는 것을 발견한다면 retaining paths라고 불리는 것을 통해 이를 볼 수 있도록하는 훌륭한 기능이 있습니다. 그저 힙 스냅샷에서 감시하기를 원하는 객체를 그저 클릭하고 아래 패널에서 정보를 얻을 수 있습니다. 작은 객체들로 이루어진 좋은 구조를 사용하는 것은 참조들을 지정하는데 도움이 될 것입니다.

장면은 EffectComposer에서 참조됩니다.

일반적으로 DOM을 조작하기 전에 두배로 생각하는 것이 좋습니다. 조작을 할 때 효율성에 대해 생각해보아야 합니다. 만약 그리할 수 있다면 게임 루프 내에서 DOM을 조작하지 마시기 바랍니다. 재사용을 위한 변수에 참조들을 저장하시기 바랍니다. 만약 여러분이 엘리먼트를 찾을 필요가 있다면 전략적인 컨테이너들에 대한 참조의 저장과 가장 가까운 조상 엘리먼트 내에서 찾는 방법에 최단 패스를 사용할 수 있습니다.

새로 추가된 엘리먼트들의 해상도를 읽거나 클래스를 추가/제거할 때 레이아웃의 버그를 경험한다면 지연을 시키도록 하시기 바랍니다. 혹은 레이아웃의 발생 여부를 확실하게 만드시기 바랍니다. 때때로 브라우저 배치는 스타일을 변경하고 다음 레이아웃의 발생 뒤에 업데이트하지 않을 것입니다. 이는 때때로는 정말 큰 문제가 될 수 있지만 거기에는 이유가 있으므로 장면 뒤에서 어떠한 동작하는지를 배워야 합며 여기에서 많은 것을 얻을 수 있을 것입니다.

풀스크린

가능한 경우, 메뉴에서 Fullscreen API를 통해 풀스크린 모드로 사이트를 실행할 수 있는 옵션이 있습니다. 그러나 또한 디바이스 상에서 풀스크린으로 진입하기 위한 브라우저의 결정 사항이 존재합니다. iOS 상의 사파리는 그를 조작할 수 있도록하는 이전의 핵(Hack)을 가지고 있었습니다만 더 이상은 가능하지 않으므로 스크롤되지 않는 페이지를 만들 때 이것 없이 동작하는 디자인을 준비하여야 합니다. 많은 웹앱을 깨뜨릴 수 있으므로 미래의 업데이트에서 이에 대한 업데이트를 원할 것입니다.

에셋(Assets)

실험들을 위한 애니메이션 설명들.

우리는 사이트를 통털어 많은 다른 형태의 에셋들을 가지고 있고 이미지(PNG와 JPEG), SVG(인라인과 배경), 스프라이트시트(PNG), 커스텀 아이콘 폰트와 어도비 엣지(Adobe Edge)를 사용합니다. 벡터에 기반하지 않은 엘리먼트에서 (스프라이트시트) 애니메이션과 에셋들을 위해 PNG들을 사용합니다. 즉, 가능한한 SVG를 많이 사용하려 하였습니다.

벡터 포맷은 확대/축소 시의 무손실을 의미하지 않습니다. 모든 디바이스들을 위한 단 하나의 파일을 의미합니다.

  • 작은 파일 크기.
  • 분할된 각 파트를 애니메이션할 수 있습니다. (개선된 애니메이션으로 완벽합니다.) 이에 대한 예를 들자면 호빗 로고가 축소될 때 "부제" (스마우그의 폐허)를 감추었습니다.
  • SVG HTML 태그로써 내장될 수 있거나 추가적인 로딩없이 배경이미지로써 사용될 수 있습니다. (이는 HTML 페이지와 같은 시간에 로딩됩니다.)

아이콘 타입페이스는 확장성이 필요할 때 SVG와 같은 장점을 가지고 있으며 오로지 (호버, 활성화 등의) 색상의 변경하는 것만 필요한 아이콘과 같은 작은 엘리먼트에 대해 SVG 대신 사용됩니다. 아이콘은 또한 재사용하기 매우 쉬우므로 엘리먼트의 CSS "content" 속성을 설정하기만 하면 됩니다.

애니메이션

몇몇 경우에 코드를 이용한 SVG 엘리먼트의 애니메이션은 아주 빠르게 시간을 소모하며 디자인 단계에서 많은 것을 변경해야 하는 애니메이션에서는 더욱 그렇습니다. 디자이너와 개발자들 사이의 작업흐름을 개선하기 위해 몇몇 애니메이션(게임 전의 설명들)에서 어도비 엣지(Adobe Edge)를 사용하였습니다. 애니메이션 작업흐름은 Flash와 아주 비슷하고 팀의 조력이 되었습니다만 몇가지 문제점이 있었으며 특히 에셋 로딩 프로세스에서 Edge 애니메이션을 통합하는 로더와 구현 로직 시에는 더욱 그렇습니다.

저는 에셋을 핸들링하고 웹 상의 수작업 애니메이션들을 위한 완전한 작업흐름을 가지기 전까지 여전히 먼 길을 가야할 것으로 느껴집니다. 어떻게 Edge가 혁신되는 것과 같이 도구를 확인하는 것을 찾고 있습니다. 다른 애니메이션 도구들과 워크플로우들이 있다면 코멘트에 제안을 추가하시는 것을 편하게 생각하셨으면 합니다.

결론

이제 프로젝트의 모든 부분이 릴리즈되었고 최종 결과를 보게 되면서 저는 모던 모바일 브라우저의 상태가 꽤 인상적이었다는 것을 꼭 얘기하고 싶습니다. 이 프로젝트를 막 시작했을 때 우리는 얼마나 심리스(Seamless)하지, 우리가 만들 수 있는 것이 얼마나 통합되고 성능을 보여줄지에 대한 아주 낮은 기대들을 가지고 있었습니다. 이는 모던 브라우저들이 어떻게 동작하는 지에 대한 우리의 이해를 개선하는데 (아주 많은) 반복과 테스팅을 하면 모든 시간을 보냈으며 우리에게 매우 큰 배움의 기회였습니다. 그리고 만약 우리가 이러한 형태의 프로젝트에 대해 더 짧은 생산시간을 원한다면 알아야 하는 것들을 예측하는 것으로부터 시작해야 할 것입니다.

Comments

0