PWA로 사용되는 산타 추적기

사이트 보기

요약

기존 장면 디자인 덕분에 산타 추적기가 2016년 연말연시에 오프라인 프로그레시브 웹 앱으로 빠르게 업그레이드되었습니다.

결과

  • 산타는 프로그레시브 웹 앱 (PWA)이며 홈 화면에 추가 (ATHS) 및 오프라인을 지원합니다.
  • 요건을 충족하는 세션의 10% 가 ATHS 아이콘을 통해 시작됨
  • 사용자의 75% 가 기본적으로 웹 구성요소의 두 가지 핵심 요소인 맞춤 요소와 Shadow DOM을 지원했습니다.
  • Lighthouse 점수 81점
  • 오프라인은 Service Worker API를 통한 지연 로드와 연결되어 방문한 장면만 캐시하고 새 릴리스에서 자동으로 업그레이드합니다.

배경

산타 추적기는 Google의 연말연시 전통입니다. 매년 12월 내내 게임과 교육 경험을 통해 연말연시를 즐길 수 있습니다. 산타가 잠시 쉬는 동안 엘프들은 산타 추적기를 Android 모두에서 오픈소스로 출시하기 위해 노력하고 있습니다.

웹상의 산타 추적기는 Polymer를 사용해 작성된 수많은 고유한 '장면'이 있는 대규모 대화형 사이트이며 대부분의 최신 브라우저를 지원합니다. 사용자의 브라우저가 '최신'인지에 관한 평가는 기능 감지를 통해 결정됩니다. 산타에는 무엇보다도 SetWeb Performance API가 필요합니다.

2016년 Google은 대부분의 장면에서 오프라인 환경을 지원하도록 산타 추적기 뒤에 있는 엔진을 업그레이드했습니다. YouTube 동영상에서 뒷받침되는 장면이나 산타의 실시간 위치를 다루는 장면은 제외됩니다. 물론 북극에 직접 연결된 경우에만 사용할 수 있습니다. 📶☃️

Android 기기의 산타 추적기
Android 기기의 산타 추적기

챌린지

산타는 스마트폰, 태블릿, 데스크톱에서 잘 작동하는 반응형 디자인이 도입되었습니다. 이 사이트는 스타일화된 영상미와 명절 테마 오디오 등 다양한 멀티미디어 콘텐츠를 제공하여 사용자에게 즐거움을 선사합니다. 그러나 산타 추적기의 일반적인 빌드는 수백 메가바이트입니다. 여기에는 몇 가지 이유가 있습니다.

  • 산타는 35개 이상의 언어로 지원되므로 많은 애셋을 복제해야 합니다.
  • 플랫폼에 따라 미디어 지원 방식 (예: mp3 및 ogg)이 다릅니다.
  • 멀티미디어 파일이 다양한 크기와 해상도로 제공되는 경우도 있습니다.

산타의 엘프들도 12월 내내 열심히 일하며 한 달 내내 새 주요 업데이트를 출시하기도 합니다. 즉, 사용자의 브라우저에서 이미 캐시한 애셋은 재방문 시 새로고침해야 할 수 있습니다.

당면 과제:

  • 다양한 '장면'을 위한 대규모 멀티미디어 리소스
  • 한 달 동안 적용되는 변경사항

나이가 많은 오프라인 전략에 걸림돌이 됩니다.

폴리머로 만든 산타

오프라인 PWA로 업그레이드하는 방법을 알아보기 전에 한 걸음 물러서서 산타의 전반적인 디자인에 대해 이야기하는 것이 좋습니다.

산타는 원래 Polymer 0.5로 작성된 단일 페이지 애플리케이션으로 지금은 Polymer 1.7로 업그레이드되었습니다. 산타는 라우터, 공유 탐색 애셋 등 공유 코드 집합으로 구성됩니다. 또한 산타클로스에는 고유한 '장면'도 많이 있습니다.

프리로더

각 장면은 다른 URL(/village.html, /codelab.html, /boatload.html)을 통해 액세스할 수 있으며 자체 웹 구성요소입니다. 사용자가 장면을 열면 필요한 모든 HTML과 애셋 (이미지, 오디오, CSS, js)을 미리 로드합니다. 이러한 HTML은 산타 추적기 저장소의 /scenes/[[sceneName]] 아래에 있습니다. 그 동안 사용자에게 진행 상황을 보여주는 친숙한 프리로더가 표시됩니다.

이 접근 방식을 사용하면 사용자에게 표시되지 않는 장면에 불필요한 애셋(많은 데이터)을 로드할 필요가 없습니다. 또한 모든 장면에 필요한 모든 애셋의 내부 '캐시 매니페스트'를 유지해야 합니다. 캐시 매니페스트는 파일 이름에서 콘텐츠의 MD5 해시로의 매핑을 저장하는 JSON 파일입니다.

사용하는 항목 로드

이 모델은 전체 사이트를 한 번에 미리 로드하는 대신 사용자가 방문하는 장면에 필요한 리소스만 제공하여 대역폭을 절약합니다. 산타 추적기는 로드 시간이 아닌 런타임에 맞춤 요소를 업그레이드하는 Polymer 기능을 활용합니다. 다음 코드를 참조하세요.

<lazy-pages id="lazypages" selected-item="&#123;{selectedScene}}" ... >
    <dorf-scene id="village" route="village" icon="1f384" permanent
        mode$="[[mode]]"
        path$="scenes/dorf/dorf-scene_[[language]].html"
        class="santa-scene" allow-page-scrolling></dorf-scene>

    <boatload-scene route="boatload" icon="26f5"
        path$="scenes/boatload/boatload-scene_[[language]].html"
        loading-bg-color="#8fd7f7"
        loading-src="scenes/boatload/img/loading.svg"
        logo="scenes/boatload/img/logo.svg"
        class="santa-scene"></boatload-scene>

산타 추적기는 다음 단계를 따라 장면을 로드합니다(예: boatload-scene:

  1. 모든 장면 요소 (<boatload-scene> 포함)는 처음에는 알 수 없으며 모두 몇 가지 추가 속성이 있는 HTMLUnknownElement로 처리됩니다.
  2. 선택한 장면이 변경되면 <lazy-pages> 요소에 알림이 전송됩니다.
  3. <lazy-pages> 요소는 장면의 요소와 path 속성을 결정하여 HTML 가져오기 scenes/boatload/boatload-scene_en.html를 로드합니다. 여기에는 폴리머 요소와 그 종속 요소가 포함됩니다.
  4. 친숙한 프리로더가 표시됩니다.
  5. HTML 가져오기가 로드되고 실행되면 <boatload-scene>가 실제 Polymer 요소로 투명하게 업그레이드되어 즐거운 연말연시를 보낼 수 있습니다. 🎄🎉

이 접근 방식에는 단점이 있습니다. 예를 들어 중복된 웹 구성요소는 포함하지 않아야 합니다. 두 장면에서 공통 요소를 사용하는 경우(예: paper-button의 경우 빌드 프로세스의 일부로 제거하여 산타의 공유 코드에 포함합니다.

오프라인 디자인

산타 추적기는 Polymer와 lazy-pages를 활용하여 이미 장면으로 깔끔하게 세분화되어 있으며 장면마다 자체 디렉터리가 있습니다. Google에서는 공유 코드와 '장면'의 차이를 인식할 수 있도록 사용자의 브라우저에서 실행되는 오프라인 실행을 가능하게 하는 핵심 요소인 산타 추적기의 서비스 워커를 설계했습니다.

서비스 워커의 이면에 있는 이론은 무엇인가요? 지원되는 브라우저의 사용자가 사이트를 로드하면 프런트엔드 HTML에서 서비스 워커 설치를 요청할 수 있습니다. 산타 추적기의 경우 서비스 워커는 /sw.js에 있습니다. 그러면 산타의 공유 코드를 모두 미리 캐시하는 install 이벤트가 실행되므로 런타임에 가져올 필요가 없습니다.

SW 흐름도

설치된 서비스 워커는 모든 HTTP 요청을 가로챌 수 있습니다. 산타 추적기의 경우 간소화된 의사결정 흐름은 다음과 같습니다.

  1. 요청이 이미 캐시되었나요?
    • 좋습니다. 캐시된 응답을 반환합니다.
  2. 요청이 장면 디렉터리(예: 'Scene/pagesload/boardingload-scene_en.html')와 일치하나요?
    • 네트워크 요청을 수행하고 사용자에게 반환하기 전에 결과를 캐시에 저장합니다.
  3. 그 외의 경우에는 일반 네트워크 요청을 수행합니다.

흐름과 install 이벤트를 통해 사용자가 오프라인 상태일 때도 산타 추적기를 로드할 수 있습니다. 하지만 사용자가 이전에 로드한 장면만 이용할 수 있습니다. 게임을 다시 플레이하고 최고 점수를 달성하는 데 안성맞춤입니다.

예리한 관찰자는 Google의 캐싱 전략이 콘텐츠의 변경을 허용하지 않는다는 것을 알아차릴 수도 있습니다. 사용자의 브라우저에 저장된 파일은 변경되지 않습니다. 이에 관한 설명은 나중에 자세히 다룹니다.

라이브로 진행

앞서 언급했듯이 산타의 엘프는 12월 내내 열심히 일하며 한 달 내내 새 업데이트를 출시해야 하는 경우가 많습니다. 산타 추적기 출시가 빌드되면 고유한 라벨(예: v20161204112055: 출시 타임스탬프 (2016년 12월 4일의 11:20:55)입니다.

라벨이 지정된 이 버전의 경우 모든 파일의 MD5 해시를 생성하여 '캐시 매니페스트'에 저장합니다. 최신 솔리드 스테이트 디스크에서는 이 작업이 빌드 프로세스에 몇 초밖에 걸리지 않습니다.

각 출시 버전은 Google 정적 캐싱 서버의 고유 경로에 배포됩니다. 즉, 이전 출시 버전은 삭제되지 않습니다. 즉, 새 버전이 출시되고 나면 모든 애셋의 URL은 변경되지 않으며, 브라우저 또는 서비스 워커에서 캐시한 모든 내용은 추가 작업을 하지 않는 한 쓸모가 없습니다.

또한 'prod' 리소스, 즉 산타의 색인 HTML 및 서비스 워커라고 하는 새로운 버전의 리소스를 배포합니다. 이 리소스는 https://santatracker.google.com/에 있습니다. 이렇게 하면 이전 버전을 덮어씁니다.

정적 다이어그램

산타 추적기가 로드될 때마다 브라우저는 업데이트된 서비스 워커를 확인하고 사용 가능한 경우 서비스 워커를 가져옵니다. 여기서는 각 출시에서 바이트가 다른 코드를 생성합니다. 브라우저는 이를 업그레이드로 간주하고 새 install 이벤트를 실행합니다.

이 시점에서 사용자의 브라우저는 새 '캐시 매니페스트'를 살펴봅니다. 이는 사용자의 기존 캐시와 비교되며, 애셋의 MD5 해시가 다른 경우 캐시에서 애셋을 삭제하고 브라우저에 다시 가져오도록 요청합니다. 하지만 대부분의 경우 캐시된 콘텐츠는 대체로 동일하거나 미미한 차이만 있습니다.

캐시 다이어그램

산타 추적기에서 서비스 워커를 업그레이드하면 사용자의 브라우저가 즉시 새로고침됩니다.

오프라인 탐색 환경

물론 오프라인 환경을 지원하고 웹사이트가 오프라인에서 작동할 것으로 예상하지 못한 사용자도 이 기능을 더 쉽게 이해할 수 있도록 UI를 일부 변경해야 했습니다.

오프라인으로 탐색 중임을 알리는 작은 배너가 표시됩니다. 캐시되지 않은 모든 장면은 '정지'되어 클릭할 수 없습니다. 이렇게 하면 사용자는 사용할 수 없는 콘텐츠에 액세스할 수 없습니다.

오프라인

산타 추적기는 산타의 API에 정기적으로 요청합니다. 이러한 요청이 실패하거나 시간이 초과되면 사용자가 오프라인 상태라고 가정합니다. 브라우저의 내장 navigator.onLine 속성이 아닌 이 API를 사용합니다. 이 속성은 사용자가 온라인 상태인지만 알려줍니다. 이를 Lie-Fi라고도 합니다.

국제적 소통

사용자 대부분은 영어 (일본어, 포르투갈어, 스페인어, 프랑스어)를 사용하지만 산타는 35개 이상의 언어로 제작되어 출시됩니다.

사용자가 산타 추적기를 로드하면 Google에서 브라우저의 언어와 기타 신호를 사용하여 제공할 언어를 선택합니다. 대부분의 사용자는 이 언어를 덮어쓰지 않습니다. 그러나 사용자가 선택 도구를 통해 새 언어를 선택하면 Google에서는 새 버전의 산타 추적기가 제공되었을 때와 마찬가지로 업그레이드를 이용할 수 있는 것으로 간주합니다.

언어

즉, 서비스 워커를 위한 산타 추적기의 현재 버전은 실제로 (build,language)의 튜플입니다.

홈 화면에 추가

산타는 오프라인으로 작업하고 서비스 워커를 제공하므로 자격요건을 충족하는 사용자에게 홈 화면에 산타를 설치하라는 메시지가 표시됩니다. 2016년에는 요건을 충족하는 로드의 약 10% 가 홈 화면 아이콘에서 발생했습니다.

결론

Polymer 및 웹 구성요소를 기존에 사용한 덕분에 쉽게 만들 수 있었던 기존의 장면 디자인 덕분에 산타 추적기를 오프라인 PWA로 빠르게 변환할 수 있었으며, 이를 통해 안정적이고 매력적인 환경을 조성할 수 있었습니다. 또한 빌드 시스템을 활용하여 효율적인 업그레이드를 수행하고 변경된 애셋만 무효화합니다.

산타는 대부분 맞춤 제작된 솔루션이지만, 대부분의 원칙은 Polymer Project의 App Toolbox에서 확인할 수 있습니다. 새 PWA를 처음부터 빌드하는 경우 확인하는 것이 좋습니다. 프레임워크에 구애받지 않는 접근 방식을 찾고 있다면 작업 상자 라이브러리를 사용해 보세요.