PWA(Progressive Web App)
- 웹 사이트를 안드로이드/iOS 모바일 앱처럼 사용할 수 있게 만드는 일종의 웹 개발 기술
- React를 이용해 만든 웹 사이트를 모바일 앱으로 발행해서 쓰는데, iOS/안드로이드 앱을 발행하는 게 아니라 웹 사이트 자체를 스마트폰 홈 화면에 설치하는 것
PWA 장점
1. 스마트폰, 태블릿 바탕화면에 웹 사이트 설치가 가능하다.
- 설치된 앱 누르면 상단 URL바가 제거된 크롬 브라우저가 뜬다. 일반 사용자는 앱이랑 구분 못 함.
2. 오프라인에서도 동작할 수 있다.
- serice-worker.js라는 파일과 브라우저의 Cache stroage로 오프라인에서도 동작할 수 있다. 그래서 자바스크립트로 게임 만들 때 유용하다.
3. 설치 유도 비용이 매우 적다.
- 앱 설치를 유도하는 마케팅 비용이 적게 들어간다.
- 앱 스토어에 방문해서 앱 설치하도록 유도하는 건 매우 높은 마케팅 비용이 들지만, PWA는 웹 사이트 방문자들에게 간단한 팝업을 띄워서 설치 유도를 할 수 있어 훨씬 적은 마케팅 비용이 든다.
PWA 만들기
파일 2개만 사이트 로컬 경로에 있으면 브라우저가 PWA로 인식한다. (그리고 HTTPS 사이트여야 한다.)
manifest.json, service-worker.js라는 이름의 파일 2개를 만들면 된다.
하지만 기본 프로젝트를 npm build / yarn build 했을 경우 manifest.json만 생성해 준다.
service-worker.js까지 자동으로 생성하기를 원한다면 프로젝트를 처음 만들 때 PWA도 설치해 줘야 한다.
npx create-react-app 프로젝트명 --template cra-template-pwa
이렇게 터미널에 입력하여 설치하면 service-worker.js까지 자동으로 생성된다.
프로젝트를 생성하고 나면 index.js 하단에 있는
serviceWorkerRegistration.unregister();
이 부분을
serviceWorkerRegistration.register();
이렇게 수정해야 한다.
그리고 터미널에서 npm run build / yarn build 했을 때 manifest.json과 service-worker.js 파일이 자동으로 생성된다.
PWA 발행은 이렇게 끝이다.
manifes.json, service-worker.js 파일 살펴보기
build를 하고 나면 build 폴더 내에 manifiest.json과 service-worker.js 파일들이 있다.
manifes.json
- 웹 앱의 아이콘, 이름, 테마색 등을 결정하는 파일
{
"version" : "앱의 버전",
"short_name" : "설치 후 앱 런처나 바탕화면에 표시할 짧은 12자 이름",
"name" : "기본 이름",
"icons" : { 여러가지 사이즈별 아이콘 이미지 경로 },
"start_url" : "앱 아이콘 눌렀을 시 보여줄 메인페이지 경로",
"display" : "standalone 아니면 fullscreen",
"background_color" : "앱 처음 실행시 잠깐 뜨는 splashscreen의 배경색",
"theme_color" : "상단 탭색상 등 원하는 테마색상",
}
등 여러가지를 결정할 수 있다.
그리고 이 파일은 웹 앱에서 사용하는 모든 html 안에 이런 식으로 집어넣어야 하는데
<link rel="manifest" href="/manifest.webmanifest">
다행히 리액트가 알아서 처리해 줬기 때문에 더 건드릴 게 없다.
service-worker.js
앱을 설치하고 구동할 때 필요한 이미지, 데이터들이 전부 하드에 설치된다. 그리고 앱을 실행하면 앱 로고 같은 데이터를 앱 서버에 요청하는 게 아니라 하드에 이미 설치되어 있는 걸 가져와서 사용한다. 이것을 흉내내도록 도와주는 파일이 service-worker.js 팔이이다.
이 파일에 설정을 해 주면 웹 앱을 설치했을 때 어떤 css, js, html, 이미지 파일이 하드에 설치될지를 결정할 수 있다. 그러고나면 앱을 켤 때마다 서버에 요청하는 게 아니라 Cache Storage에 저장되어 있는 css, js, html 파일을 사용하게 된다. 그러면 이제 오프라인에서도 사용이 가능해진다.
그런데 React가 알아서 해 주기 때문에 설정은 이미 되어 있다.
모든 html, css, js 파일을 cache storage에 저장하도록 기본 세팅이 되어 있는데, 간혹 저장해 두기 싫거나 자주 변하는 파일들은 하단 튜토리얼을 참고해서 수정해보면 된다.
(공식 튜토리얼)
https://developers.google.com/web/fundamentals/primers/service-workers
(샘플)
https://googlechrome.github.io/samples/service-worker/basic/
그리고 build를 할 때마다 html, css, js 파일의 이름과 경로가 무작위로 바뀐다. 사이트에 필요한 html, css, js 파일명이 바뀌면 하드에 있는 게 아니라 서버에서 요청해 새로 받아온다. 파일을 서버에 올려서 배포할 때마다 유저는 새로운 파일을 보게 된다.
개발자 도구로 PWA 디버깅하기
build 했던 프로젝트가 PWA인지 아닌지 살펴보고 싶으면 2가지 방법이 있다.
- 사이트를 호스팅 받아 올리기(Github page 이런 것도 가능)
- VS code의 extension 중에 live server을 설치하고, build 폴더의 index.html 파일을 live server로 띄우기
그런 다음 크롬 개발자 도구의 Application이라는 탭에서 PWA와 관련된 모든 걸 살펴볼 수 있다.
Manifiest 메뉴에서는 manifest.json 내용들을 확인할 수 있고,
Service Worker 메뉴에서는 service-worker 파일이 잘 있는지, 오프라인에서 잘 동작하는지 테스트 가능하고 푸시 알림 기능을 개발해 뒀다면 푸시 알림도 샘플로 전송해 볼 수 있다.
Cach Storage 메뉴에선 service-worker 덕분에 하드에 설치된 html, css, js 파일들을 확인할 수 있으며 캐시된 파일 제거도 가능하다.
PWA를 커스터마이징하려면
지금 PWA 발행이 쉽고 간단한 이유는 구글의 workbox라는 라이브러리가 create-react-app 설치할 때 함께 설치되었기 때문이다.
그래서 PWA 발행 방식 같은 걸 커스터마이징 하고 싶으면 workbox 사용법을 익혀야 하는데 , 구글의 개발 문서를 보면 매우 불친절하고 어려우므로 빠르게 커스터마이징 방법 하나만 알아보자.
하드에 설치할 파일 중에 html을 제외하고 싶다면?
html 파일은 너무 자주 변해서 하드에 저장해 놓기 싫다면 여기를 수정하면 된다. (그런데 그렇게 하면 앱 실행시 아무것도 뜨지 않을 것이고 모바일 앱의 장점이 사라진다는 것을 알고 있자.)
프로젝트 폴더 내의 node_modules/react-scripts/config/webpack.config.js 파일의 하단 쯤에 이런 코드가 있다.
new WorkboxWebpackPlugin.GenerateSW({
clientsClaim: true,
exclude: [/\.map$/, /asset-manifest\.json$/],
})
(▲구버전)
new WorkboxWebpackPlugin.InjectManifest({
swSrc,
dontCacheBustURLsMatching: /\.[0-9a-f]{8}\./,
exclude: [/\.map$/, /asset-manifest\.json$/, /LICENSE/],
(▲신버전)
여기의 exclude라는 항목이 어떤 파일을 캐싱하지 않을 건지 결정하는 부분이다.
정규식으로 작성하는데 정규식과 일치하는 파일명을 제외한다. 그래서 원하는 html 파일을 여기에 등록하면 된다.
new WorkboxWebpackPlugin.GenerateSW({
clientsClaim: true,
exclude: [/\.map$/, /asset-manifest\.json$/, /index\.html/],
})
이것 말고도 ".css로 끝나는 모든 파일", "a라는 글자로 시작하는 파일" 등 이런 식으로 정규식으로 작성할 수도 있다.
그런데 만드는 사이트가 페이스북, 인스타, 유튜브처럼 입장과 동시에 Ajax로 초기 데이터들을 전부 받아오는 사이트라면 굳이 html 파일을 저렇게 할 필요는 없다.
아무튼 위처럼 코드를 추가하면 build 할 때 index.html 파일을 캐싱 목록에서 제외 시켜 준다.
* 이 포스팅은 코딩애플 강의를 토대로 작성하였습니다.