brunch

You can make anything
by writing

C.S.Lewis

by 웰콤반 Jun 30. 2016

Progressive Web App

App shell & Service Worker 

google developers summit 에서 중점적으로 progressive web app - app shell, serviceworker 에 대해 다뤘다.

# Progressive Web App ? 

Progressive Web App 은 Google 개발자 Alex Russell 이 2015년 6월 처음으로 제안한 아이디어라고 한다. (참고) Progressive Web App 의 설명에서 가장 빈번히 들리는 단어는 'App like' 와 'Natively' 이다. 이전의 Hybrid App 보다는 간편히 설치, 개발 할 수 있고, 링크로 공유 가능한 웹 페이지여서 보안에 강하면서도 '네이티브 앱처럼' Offline Access 와 Notification 을 지원한다.


구글은 이런 간편하고 빠른 웹 앱을 만들기 위한 도구로 Application Shell Archirecture 와 Service Worker 두 가지를 내놓았다.  Google Chorme Summit 2015 에 이어 올해 한국에서 열린 Google Developsers Summit Korea 2016 에서도 웹 세션에서 가장 집중한 부분은 이 두가지의 서비스였다.


#Progressive Web App 이라면,

- Insatant Loading : 네트워크 환경이 안좋은 상황에서라도 심지어 오프라인이더라도 유저는 항상 빠르게 앱 로딩을 할 수 있어야 한다.

- Add to HomeScreen : 브라우저에서 바로, 빠르고 간결한 동작으로 홈스크린에 앱을 설치할 수 있어야 한다. 

- Push Notification : 브라우저가 닫혀 있더라도, 푸시를 제공 할 수 있어야 한다. 이는 웹앱 재방문율을 높일 수 있다.

(https://developers.google.com/web/progressive-web-apps/ 참고)



# App Shell

 앱 쉘은 Progressive Web App 을 제공하기 위해 갖춰야 하는 최소한으로 요구되는 HTML, CSS, Javascript 다. 간단한 예제 실행에 필요한 파일들은 구글의 다양한 사이트에서 제공한다. 예제 다운로드 (출처 : google developers - starter kit)

 앱 쉘은 스피드에 포커싱된 구조이다. 앱 같이 보여주고, 빠른 로딩을 돕는다. 말 그대로 앱 같이 보여주는  웹 앱의 껍데기 이고, 관련된 파일만 instantly 하게 로컬 캐쉬에 저장해서 컨텐트만 그때 그때 로딩하도록 한다. 


Add to Homescreen 

json 형태의 Menifests 파일을 활용하여 웹 페이지를 HomeScreen 에 넣을 때 아이콘 설정이나 Full Screen 으로 Launching 하는 것을 쉽게 해결 할 수 있다. json 파일로 설정하는 것은 크롬-안드로이드에서만 지원 하지만 safari-ios에서는 다음과 같은 meta 태그를 통해 설정 가능하다.

<!-- Add to home screen for Safari on iOS -->
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<meta name="apple-mobile-web-app-title" content="Weather App">
<link rel="apple-touch-icon" href="images/icons/icon-152x152.png">
json 형태의 web app manifests 설정 - google developers summit korea

# Instant Loading ( Fast First Load ) 

Instant Loading 을 위해 App Shell 을 구성하는 html, css, script, png 파일 등을 크롬 브라우저의 Cache Storage 에 저장 하고, 브라우저 local storage 에 데이터를 저장한다. 


 ⁃ https://weather-pwa-sample.firebaseapp.com/step-05/  

 해당 예제를 예로 들면, 웹 앱 (웹 페이지) 가 처음 실행 될 때 또는 버전이 업데이트 되었을 때 Cache Storage 에 브라우저 동작을 위한 html, css, ,scrpit, png 파일을 저장 해 두고 다음 로딩 부터는 캐싱된 파일을 사용하여 App Shell 영역 로딩 비율을 줄인다. Cache Storage는 브라우저 내부 캐시이므로 오프라인 지원에 있어서도 사용 될 수 있다. Browser Locae Storage 에는 데이터를 저장한다. 

예제에서는 간단히 '[{"key":"newyork","label":"New York, NY"},{"key":"austin","label":"Austin, TX"}]' 이런 식으로 key 값 정도를 저장하고 Cache Storage 에 저장된 스크립트에서 뷰를 그리는 방식을 사용한다. 

처음 웹 실행 시 또는 버젼 업데이트 시 각각의 storage 영역에 파일을 업데이트 하는 데 서비스 워커를 활용한다.



Service Woker

Progressive Web App 이 되려면 빠르고, 설치할 수 있어야 한다.(Installable) 어떠한 환경에서도, 같이 적용되어야 한다. (online, offline, intermittent, slow connections...). 그래서 빠르고 신뢰도 높은 서비스를 위해 app shell 을 서비스 워커를 통해 캐싱한다. 그럼 (지원하는 브라우저에 한해) 네트워크가 끊겼을 때도 간단한 뷰를 제공할 수 있다. 


 서비스워커는 브라우저에서 백그라운드로 활동하는 일종의 워커여서, 등록/ 해제하여 사용한다. 내 크롬 브라우저에 적용된 서비스워커는 chrome://serviceworker-internals/ 에서 확인 할 수 있다.

 서비스 워커 flow 참고 


# register service worker 

- service-worker.js 스크립트 파일을 프로젝트 루트 폴더에 만든다. 서비스 워커의 scope 는 스크립트 파일이 포함된 디렉토리의 위치에 따라 결정되므로, 루트를 권장한다.

- Check if the browser supports service workers : 서비스 워커는 지원하는 브라우저에 한해 사용할 수 있으므로 서비스 워커를 등록하기 전 스크립트에서 지원하는 브라우저인지 확인 한 후, 지원한다면 등록하여 사용한다. 

if('serviceWorker' in navigator) {   
      navigator.serviceWorker
            .register('/service-worker.js')
            .then(function() { console.log('Service Worker Registered'); });  
}


set event listener 

install : 페이지를 처음 방문 했을 때 호출되는 이벤트다. 이벤트 핸들러를 통해 install 이벤트에서 캐시를 오픈하고, 캐싱할 파일을 inject 한다.

cache open 시 parameter 로 cache Name 을 넣는다 : 버젼 관리에 용이

cache open 되면 cache.addAll() 로 파일을 캐싱한다. 

activate : new cache (cache name 에 version 을 붙여서 판단) 가 있을 때 delete old cache and get all of the cache keys 


# serve the app shell from the cache

fetch event 는 페이지로부터 네트워크 요청이나 메세지가 생성될 때 발생한다.

fetch event 에 trigger 된 caches.match() 는 캐시된 버젼으로 응답할 지 네트워크로부터 copy를 얻기 위해 fetch 를 사용 할 지 request 를 평가하고 캐시가 유효한지 체크한다. 

self.addEventListener('fetch', function(e) {  
   console.log('[ServiceWorker] Fetch', e.request.url);  
   e.respondWith(  
      caches.match(e.request).then(function(response)
          return response || fetch(e.request);
      })  
    );  
});


# 참고

Web server for Chrome : 웹 서버를 간편하게 띄울 수 있는 프로그램


매거진의 이전글 Deview 2016 day2 Review
브런치는 최신 브라우저에 최적화 되어있습니다. IE chrome safari