PWA(Progressive Web App)은 HTML, CSS, JavaScript를 포함한 일반적인 웹 기술을 사용하여 개발된 응용 프로그램 소프트웨어다. 표준적인 웹 브라우저를 포함한 모든 플랫폼에서 작동한다. 이렇게 봐서는 일반적인 웹 애플리케이션과 무슨 차이가 있느냐 하겠지만, 오프라인 작업, 푸시 알람, 데스크톱 및 모바일로의 설치(네이티브 응용 프로그램과 유사한 사용자 환경)가 가능하다. 웹 애플리케이션이기 때문에 App Store, Google Play와 같은 배포시스템이 필요 없다.
웹 애플리케이션은 물론 모바일 장치에서도 (웹 브라우저를 이용해서) 접근 할 수 있었지만 느리고, 기능이 부족하며, 찾기가 힘들었기 때문에 사용성이 떨어지는 측면이 있다. 하지만 오프라인에서 작업이 가능하고 모바일 장치에서 직접 실행되는 PWA의 기능을 이용해서 네이티브 앱과의 격차를 해소 할 수 있다.
PC에서 시작한 인터넷 환경은 모바일 디바이스로 이동하고 있으며 이에 따라 모바일 웹과 네이티브 앱으로 불리는 두 가지 종류의 앱이 경쟁하고 있다. 아래 정보는 미국 기준이다.
2018년 기준 모바일 기기의 사용시간은 평균 3시간 35분이며, 연간 11분 이상 증가할 것으로 예상하고 있다.
2019년 기준 사용자는 스마트 폰에서 90% 이상의 시간을 앱으로 소비했다.
앱의 주요 활동은 디지털 오디오이며, 50분 이상을 오디오를 듣는데 소비한다.
소셜 네트워킹은 40분 그 다음으로 모바일 비디오와 게임, 메시징이 있다.
앱은 웹에 비해서 기능적인 장점도 가지고 있다.
카메라, 마이크 등 모바일 기기에서 제공하는 기능/기술을 사용 할 수 있다. : Capability가 뛰어나다.
스마트폰에 설치가 되기 때문에, 느린 네트워크에서도 작동한다.
부드럽고 빠른 화면 전환, 애니메이션을 보여줄 수 있다.
기능과 성능상의 이점, 절대적인 사용시간으로 웹 사용이 줄어들 것으로 예상되지만 그럴 것 같지는 않다. 고유의 장점이 있기 때문이다.
50% 이상의 유저가 한달 동안 한 건의 앱도 다운로드 받지 않는다.
특정 3개의 앱에서 사용시간의 77%를 보내고 있다. 이 중 하나의 앱이 49%를 점유한다.
반면, 모바일 사용자들은 한 달에 평균 100개 이상의 웹 사이트를 방문한다.
웹 사이트에 접근하기 위해서는 URL 링크만 클릭하면 된다. 다른 어떠한 준비 작업도 필요 없다.
웹의 문제는 재방문율의 문제라고 할 수 있을 것이다. 홈 화면에 아이콘이 설치되고 클릭만 하면 되는 앱에 비해서, 웹의 경우 URL을 기억해야 해서 재 방문하기가 쉽지 않다. 북마크라는 도구가 있기는 하지만 앱의 편리함에 비교할 바가 아니다. 스마트폰에서 북마크를 이용해서 웹에 접근하는 경우를 본 적이 없다.
PWA는 아래와 같은 해법을 제시하고 있다.
웹의 도달성은 그대로 제공하자.
스마트폰 홈 화면에 아이콘을 배치하자 : 앱처림 직관적으로 실행 할 수 있다.
리소스의 일부를 스마트폰에 설치하자 : 느린 네트워크 혹은 오프라인에서도 작동 할 수 있다.
PWA는 웹 애플리케이션이다. HTTPS를 기본으로 하고 있기 때문에, 적당한 개발환경을 만들어줘야 한다. 나는 S3의 static wab hosting을 이용해서 PWA를 테스트하기로 했다. 서비스 도메인은 pwa.joinc.co.kr이다.
S3에 pwa.joinc.co.kr bucket를 만든다. S3 버킷을 static web hosting 하면, AWS 도메인이 만들어진다. 이 도메인으로는 서비스 할 수 없으므로 퍼블릭 도메인과 연결해야 하는데, 반드시 도메인이름과 버킷이름이 일치해야 한다.
버킷 이름은 pwa.joinc.co.kr로 한다.
S3 버킷은 기본설정이 Public Access을 막는다. Block all public access설정을 풀어서 인터넷에서 접근 가능하도록 한다.
Static website hosting 설정을 한다.
"Use this bucket to host a website"를 체크하면 Static website hosting을 활성화 할 수 있다. index document 와 Error document는 옵션이다. Endpoint 주소로 접근 할 수 있다.
테스트를 위해서 S3 버킷에 파일을 올렸다.
PWA는 SSL을 필요로 한다. S3 Static webserver hosting은 SSL을 지원하지 않는다. 클라우드프론트(CloudFront)를 이용해서 HTTPS를 서비스 하기로 했다.(왠지 배보다 배꼽이 더 커진 것 같다..)
joinc.co.kr 도메인에 대한 SSL을 ACM으로 관리하고 있으므로 연동만 시켜주면 될 것 같지만 그렇지 않다. ACM은 리전단위 서비스인데, 클라우드프론트를 위한 ACM은 버지니아 리전(us-eas-1)에 있는 것만을 사용 할 수(이 것 때문에 꽤나 헷갈렸다) 있다. 버지니아 리전 ACM을 이용해서 pwa.joinc.co.kr 인증서를 만들었다.
CloudFront > Create Distribution을 선택한다.
중요 설정만 설명한다.
Price Class : 배포범위를 설정한다. 넓은 지역에 배포 할 수록 더 많은 비용이 나간다. Use All Edge Locations를 선택했다.
Alternate Domain Names(CNAMEs) : 외부에 공개될 도메인 이름이다. pwa.joinc.co.kr로 설정한다.
SSL Certificate : pwa.joinc.co.kr도메인에 대한 SSL을 설정해야 한다. 버지니아 리전에 등록한 인증서를 선택한다. 자동으로 리스트가 나오기 때문에 쉽게 설정 할 수 있다.
Default Root Object : URL에 페이지를 명시하지 않았을 경우 기본으로 호출할 페이지다. index.html을 설정했다.
Yes, Edit를 눌러서 저장한다. 저장을 끝내면 "xxxx.cloudfront.net" 패턴의 CloudFront 도메인 이름이 나온다. 이 이름을 pwa.joinc.co.kr 레코드의 CNAME으로 설정한다.
curl로 테스트해보자.
코드를 분석하기 전에 작동을 먼저 확힌해보자.
영상을 만들기 쉬워서 안드로이드 애뮬레이터로 테스트를 했다. https://pwa.joinc.co.kr 로 접근하면 페이지 하단에 애플리케이션을 홈에 설치 할 것인지를 묻는다. 설치하고 나면 홈 화면에 앱 아이콘이 생긴다. 실행화면도 네이티브 앱과 비슷하다.
PWA는 데스크탑에도 설치 할 수 있다. 리눅스 운영체제에서 설치해 봤다.
홈 스크린, app launcher, task switcher, 스플래시 화면 등에서 사용 할 아이콘을 정의 할 수 있다. 하나 이상의 아이콘을 설정 할 수 있으며, 각 아이콘은 크기와 이미지 타입 속성을 포함한다. 안드로이드 적응형 아이콘 기능을 사용하려면 icon 속성에 "purpose":"any maskable"를 추가한다.
크롬의 경우 최소한 192x192 와 512x512 픽셀 크기의 아이콘을 제공해야 한다. 이 두 아이콘만 설저오딜 경우, 크롬이 기기에 맞게 아이콘 크기를 조정한다. 기기에 맞는 깔끔한 아이콘이 필요하다면 48dp 단위로 아이콘을 만들면 된다.
Chrome Dev 툴의 Application패널에서 manifest가 제대로 작성됐는지를 확인 할 수 있다.
pwa.joinc.co.kr의 manifest 정보다. 이 시점에서는 경고가 하나 있었다. 아이콘의 크기를 실수로 511x512로 해서 발생한 경고였다. 실행에는 문제가 없다.
서비스 워커 등록을 시도하면 사용자 에이전트는 스크립트 구문을 분석한다. 구문 분석에 성공하면(HTTPS를 비롯한 요구 사항이 충족되면) 서비스 워커 등록 객체에 액세스 할 수 있다. 여기에는 서비스 워커의 상태와 scope와 같은 정보가 포함된다. 예제의 js/main.js코드를 살펴보자.
브라우저가 Service worker API를 지원한다면 ServiceWorkerContainer.register()메서드를 이용해서 사이트에 등록한다. 서비스 워커의 실제 코드는 sw.js에 있으며, 등록이 성공한 후 실행된다. 이게 서비스 워커를 등록하기 위한 전부다. 나머지 다른 것들은 sw.js에 있다. sw.js 파일의 내용을 보자.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
var cacheName = 'hello-pwa';
var filesToCache = [
'/',
'/index.html',
'/css/style.css',
'/js/main.js'
];
/* Start the service worker and cache all of the app's content */
서비스 워커는 주요 이벤트에 대한 이벤트 리스터를 제공한다. 첫번째 이벤트는 install 이벤트다. install 리스너에서 캐시를 초기화하고 오프라인 사용을 위한 파일들을 다운로드 할 수 있다.
캐시를 저장할 변수를 생성하고, 캐시 목록을 정의한다. 위 예제에서 캐시 변수는 cacheName이고, 캐시할 페이지 목록은 fileToCache에 저장했다. 이제 캐시할 파일을 모두 저장 할 때까지 기다리게(waitUntil)된다. 캐시가 모두 끝나면 install 이 끝난다.
패치응답 처리를 위한 fetch이벤트도 설정했다. 이는 앱이 HTTP 요청을 할 때 발생을 한다. fetch로 요청을 가로채서 응답을 만들 수 있어서 매우 유용하다.
Contents
1. PWA에 대해서
1.1. 도입 사례
2. 테스트 전에
3. 테스트 환경
4. ACM(SSL) 연동
5. 디렉토리 구성
6. 코드 분석
7. manifest.json
7.1. short_name & name
7.2. icon
7.3. start_url
7.4. background_color
7.5. display
7.6. scope
7.7. manifest를 웹에 추가하기
7.8. manifest 테스트하기
8. service worker
8.1. 서비스 워커의 라이프사이클
8.2. Parsed & Installing
9. 정리
10. 참고
1. PWA에 대해서
1.1. 도입 사례
2. 테스트 전에
3. 테스트 환경
4. ACM(SSL) 연동
5. 디렉토리 구성
6. 코드 분석
7. manifest.json
7.1. short_name & name
7.2. icon
7.3. start_url
7.4. background_color
7.5. display
7.6. scope
7.7. manifest를 웹에 추가하기
7.8. manifest 테스트하기
8. service worker
8.1. 서비스 워커의 라이프사이클
8.2. Parsed & Installing
9. 정리
10. 참고
Recent Posts
Archive Posts
Tags