service worker 를 이용한 offline web application 구현

34
eBrain Lab Service Worker 를 이용한 Offline Web Application 구현

Upload: -

Post on 18-Jul-2015

414 views

Category:

Software


6 download

TRANSCRIPT

eBrain Lab

정 병 태

Service Worker 를 이용한 Offline Web Application 구현

Speaker

정 병 태 eBrain Lab

- Web Developer

- OKKY.KR Contributor

- https://github.com/1angerhans - http://okky.kr/user/info/26138 - [email protected]

내용• Service Worker

• Service Worker 란?

• Service Worker 로 할 수 있는(있을) 것들

• 지원 현황

• 기본 사용 방법

•Offline Web Application 구현하기

• Cache 를 이용한 서비스 구현

• ‘Offline 우선’ 서비스 구현

Service Worker

Service Worker 란?

• Offline 상태에서, 웹 어플리케이션의 준비 단계를 가로채는 방법을 제공하고, 지속적인 background 처리를 지원.

• 문서 및 관련 자원에 대한 설치, 버전, 업그레이드를 관리 할 수 있는 event-driven Web Worker.

• 웹 플랫폼을 확장 하는 다른 사양들의 background 처리에 대한 시작점 역할.

출처 : https://slightlyoff.github.io/ServiceWorker/spec/service_worker/

Service Worker 란?• Network Proxy : 응답을 가로채고, 조작이 가능

• Dom Thread 와는 별개의 Thread 로 동작하므로, Dom 및 Global Scope (window) 접근은 불가능함.

• postMessage 를 이용한 양방향 데이터 교환 가능.

• Page 단위로 동작되는 것이 아니기 때문에, register 이후에는 Background 에서 동작 함. (새 탭을 열어도 동일한 Worker 이용)

• Service Worker Thread 는 사용되지 않을 때는 종료되고, 필요할 때 재시작 되기 때문에 전역상태를 유지할 수 없음.

Service Worker 란?

Server

HTTP/Cache

Page

Server

HTTP/Cache

Page

ServiceWorker Cache API

•Offline Cache

•Task Scheduler

•Background Sync

•Push notification

•Geofencing

할 수 있는(있을) 것들

Q: 그건 그렇고, IE 에서 돼?

A: ……

Chrome (40+)

Opera (28+)

Firefox (Nightly Build)

Internet Explorer (지원 고려중)

Sapari (지원 안함)

지원 현황

출처 : https://jakearchibald.github.io/isserviceworkerready/

Service Worker 기본 사용 방법

Requirements•HTTPS: 중간자공격(Man-in-the-middle Attack) 방지* localhost 에서는 http로 가능

•Cache API Polyfill: https://github.com/coonsta/cache-polyfill

•Promise: 비동기 작업에 대해 순차적인 프로그래밍을 할 수 있도록 도와주는 패턴.

if('serviceWorker' in navigator) { navigator.serviceWorker.register(‘/service-worker.js’,{ scope: ‘/'

}).then(function() { console.log('Service worker resisted'); }).catch(function(error) { console.log('Service worker resistration faild'); }); }

register• Service Worker 를 최초로 등록

• Origin relativity

scope: ‘/‘

service-worker.js

self.addEventListener('install', function(event) { console.log('Service worker installed'); });

self.addEventListener('active', function(event) { console.log(‘Service worker activated’); }); self.addEventListener('fetch', function(event) { console.log(‘Fetching…’); });

• Service Worker 의 동작을 intall / active / fetch Event 등 를 통해 정의

Offline Web Application

잠깐

Q: 지금 우리 AppCache 무시하셈?

A: 명세를 다 꽤차고 계시다면, 계속 AppCache를 쓰셔도 좋습니다.

아니면 읽고 또 읽으세요. 피눈물 날 때까지.

출처 : https://www.youtube.com/watch?t=119&v=4uQMl7mFB6g

•Manifest - 동작을 완벽히 이해하기 위해서는 복잡한 명세를 숙달

•온라인 상태에서도 항상 캐시에서 호출

•캐시 되지 않은 리소스는 캐시된 페이지에서 로드 되지 않음: http://appcache-demo.s3-website-us-east-1.amazonaws.com/without-network/

•캐시는 Manifest 를 변경할 때만 업데이트 됨

•Manifest 에 대한 캐시 문제

AppCache 의 한계

참고 : Application Cache is a Douchebag - by Jake Archibald

Cache를 이용한 서비스 구현

index.html

<!DOCTYPE html> <html><head lang="en"> <meta charset="UTF-8"> <title></title> <link rel="stylesheet" href=“/assets/app.css"> <script src="/assets/jquery-1.11.2.min.js"></script> <script src="/assets/app.js"></script></head><body><div id="feeds"></div></body></html>

register

if('serviceWorker' in navigator) { navigator.serviceWorker.register('/sw.js', {scope: '/'}) .then(function() { console.log('Service worker resisted'); }) .catch(function(error) { console.log('Service worker faild'); }); }

app.js var getFeeds = function() { return $.get('data/feeds.json'); }; var setPage = function(feeds) { return $.Deferred(function(deferred) { $('#feeds').html(''); $(feeds).each(function(i, feed) { // View 처리 }); return deferred.resolve(); }); }; getFeeds() .done(setPage);

sw.js - installimportScripts(‘/assets/serviceworker-cache-polyfill.js'); var CACHE_NAME = 'cache-v1'; self.version = 1; self.addEventListener('install', function(event) { event.waitUntil( caches.open(CACHE_NAME) .then(function(cache) { return cache.addAll([ '/', '/index.html', '/assets/jquery-1.11.2.min.js', '/assets/app.js', '/assets/app.css', ‘/data/feeds.json’ ]); }) ); });

sw.js - fetch

self.addEventListener('fetch', function(event) { event.respondWith( caches.match(event.request).then(function(response) { return response; }) ); });

Cache 동기화 / Offline 우선 서비스 구현

app.js var getFeeds = function() { return $.get('data/feeds.json'); }; var setPage = function(feeds) { return $.Deferred(function(deferred) { $('#feeds').html(''); $(feeds).each(function(i, feed) { // View 처리 }); return deferred.resolve(); }); }; var showingLiveFeeds = false; getFeeds() .done(function() { showingLiveFeeds = true; }) .done(setPage);

app.jsvar getCachedFeeds = function() { return $.Deferred(function (deferred) { if('serviceWorker' in navigator) { $.ajax('data/feeds.json',{ headers: {'x-use-cache': 'true'} }).then(function (data) { deferred.resolve(data); }); } else { deferred.reject(); } }); }; getCachedFeeds() .done(function(feeds) { if(!showingLiveFeeds) { return setPage(feeds) } });

sw.js - installimportScripts(‘/assets/serviceworker-cache-polyfill.js'); var CACHE_NAME = 'cache-v1'; self.version = 1; self.addEventListener('install', function(event) { event.waitUntil( caches.open(CACHE_NAME) .then(function(cache) { return cache.addAll([ '/', '/index.html', '/assets/jquery-1.11.2.min.js', '/assets/app.js', '/assets/app.css', ‘/data/feeds.json’ ]); }) ); });

sw.js - fetchvar feedsResponse = function(request) { if(request.headers.has('x-use-cache')) { return caches.match(request).then(function(response) { console.log(response); return response; }); } else { return fetch(request.clone()).then(function(response) { console.log(response); if(response.status == 200) { return caches.delete(request).then(function () { return caches.open(CACHE_NAME) }).then(function (feedsCache) { feedsCache.add("/data/feeds.json"); return response; }); } else { return Promise.reject(Error('400')); } }); } };

sw.js - fetch

self.addEventListener('fetch', function(event) { var requestURL = new URL(event.request.url); if(requestURL.pathname.indexOf("/data/feeds.json") > -1) { event.respondWith(feedsResponse(event.request)); } else { event.respondWith( caches.match(event.request).then(function(response) { return response; }) ); } });

참고 자료

• Service Worker Specificationhttps://slightlyoff.github.io/ServiceWorker/spec/service_worker/

• ServiceWorker.orghttp://www.serviceworker.org

• Introduction to Service Worker (HTML5ROCKS)http://www.html5rocks.com/ko/tutorials/service-worker/introduction/

• Application Cache is a Douchebaghttp://alistapart.com/article/application-cache-is-a-douchebag

감사합니다.