Progressive Web App 적용

study

Posted by MinHyun-Code on 2024.07.26 vue.js


PWA (Progressive Wep App)

모바일 기기에서 Native App과 같은 사용자 경험을 제공하는 웹 앱

앱을 다운로드하거나, 업데이트할 필요가 없고 오프라인에서도 동작한다는 장점.


npm install vite-plugin-pwa

npm install register-service-worker



1. Web App Manifest

역할 : 웹 앱이 어떻게 구동되고 있는지, 어떤 모양으로 보이는지를 설명하는 json 파일.

       브라우저가 PWA를 설치하는데 필요한 충분한 정보를 담고 있다.

경로 :  

파일 명 : manifest.webmanifest이 권장이라고는 하는데 ios 에서는 manifest.json 이름만 읽을 수 있는 것 같음.

추가 작업 : index.html 파일에 <link>


{
  "theme_color": "#3eaf7c",
  "background_color": "#3eaf7c",
  "display": "standalone",
  "scope": "/",
  "start_url": "/",
  "name": "Vue PWA",
  "short_name": "PWA",
  "orientation": "portrait",
  "description": "WorkDayAdmin PWA",
  "icons": [
    {
      "src": "icons/icon-192x192.png",
      "sizes": "192x192",
      "type": "image/png",
      "purpose": "any maskable"
    },
    {
      "src": "icons/icon-256x256.png",
      "sizes": "256x256",
      "type": "image/png"
    },
    {
      "src": "icons/icon-384x384.png",
      "sizes": "384x384",
      "type": "image/png"
    },
    {
      "src": "icons/icon-512x512.png",
      "sizes": "512x512",
      "type": "image/png"
    }
  ]
}


필수 속성

  • name : 앱 이름
  • start_url : 앱 실행 시 로딩되는 첫 페이지의 경로
  • display : 앱의 디스플레이 방식 정의 (fullscreen, standalone, minimal-ui, browser)
  • icons : 앱 대표 이미지


선택 속성

  • short_name : name이 너무 길어서 표시할 공간이 없을 때 사용되는 값, 15자 미만
  • description : browser가 app의 description 정보를 요구할 때 사용
  • background_color : 앱 화면 배경색
  • theme_color : 디스플레이(상태 바 등)에 나타나는 색
  • orientation : 화면 방향 (any, landscape, portrait, natural, primary, secondary)
  • lang : app의 main language를 지정



Service Worker


역할 : 애플리케이션, 브라우저 및 네트워크 사이에 있는 프록시 서버 역할

       네트워크 요청을 가로채서 미리 캐시 된 데이터를 먼저 내려주는 등의 작업 가능
         
       오프라인 및 백그라운드 작업을 지원하므로 기기의 인터넷이 느리거나 끊긴 경우,
       이전에 받은 데이터를 캐싱해 뒀다가 보여줌으로써 마치 앱처럼 동작이 가능

경로 :  /public/

파일 명 : serviceWorker.js

추가 작업 : 1. main.ts 파일에 
if ('serviceWorker' in navigator) {
    window.addEventListener('load', () => {
    const swUrl = `${import.meta.env.BASE_URL}serviceWorker.js`;
    navigator.serviceWorker.register(swUrl)
        .then((registration) => {
        console.log('Service Worker registered with scope:', registration.scope);
        })
        .catch((error) => {
        console.log('Service Worker registration failed:', error);
        });
    });
}

추가


    var CACHE_NAME = 'pwa-manager'; 
    var urlsToCache = [
        '/index.html', 
        '/common.js',
        '/style.css'
    ];

    // Install a service worker
    self.addEventListener('install', event => {
        // Perform install steps
        event.waitUntil(
            caches.open(CACHE_NAME)
                .then(function(cache) {
                    console.log('Opened cache');
                    return cache.addAll(urlsToCache);
                })
        );
    });
    // Cache and return requests
    self.addEventListener('fetch', event => {
        event.respondWith(
            caches.match(event.request)
                .then(function(response) {
                    // Cache hit - return response
                    if (response) {
                        return response;
                    }
                    return fetch(event.request);
                })
        );
    });
    // Update a service worker
    self.addEventListener('activate', event => {
        var cacheWhitelist = ['pwa-manager'];
        event.waitUntil(
            caches.keys().then(cacheNames => {
                return Promise.all(
                    cacheNames.map(cacheName => {
                        if (cacheWhitelist.indexOf(cacheName) === -1) {
                            return caches.delete(cacheName);
                        }
                    })
                );
            })
        );
    });



Service worker event listeners 종류와 특징

  • Install : 서비스 워커가 최초로 등록될 때 발생하는 이벤트. 주로 캐시에 필요한 파일을 저장하거나 초기 설정 수행
  • Fetch : 네트워크 요청이 발생할 때 발생하는 이벤트. 이를 통해 네트워크 요청을 가로채거나 캐시된 데이터를 반환하여 오프라인 및 캐싱 전략 구현 가능
  • Activate : 새로운 서비스 워커가 활성화될 때 발생하는 이벤트. 이전 버전의 서비스 워커와 관련된 리소스를 정리하고 업데이트된 서비스 워커의 활성화 처리
  • Push : 서버로부터 푸시 알림을 수신할 때 호출. 이를 사용하여 사용자에게 푸시 알림을 표시하거나 사용자 상호작용 유도 가능
  • Sync : Background Sync 를 통해 오프라인 상태에서 동기화 작업을 수행할 때 발생하는 이벤트. 동기화 작업을 수행하고 결과로 서버 업로드 가능
  • Message : 서비스 워커와 웹 페이지 간의 메시지 통신을 처리하기 위한 이벤트. 이를 사용하여 데이터를 주고받고 다양한 작업 수행 가능
  • Error : 서비스 워커 내에서 에러가 발생할 때 처리하는 이벤트. 에러 핸들링 및 오류 디버깅에 사용



HTTPS 프로토콜



개발 이슈 사항


1. PC화면에서는 잘 되지만, f12 모바일 화면에서 오류날 경우

이 경우는 serviceWoker 소스상 오류 또는 serviceWorker 설정이 offline으로 되어있을 경우 발생

필자의 경우 offline 설정



2. serviceWorker.js console.log를 찍었는데 안보일 경우 (크롬)

serviceWorker.js에서의 콘솔은 개발자 도구 -> serviceWorker -> 상세보기 탭에서 확인할 수 있다.



3. 이벤트 (beforeinstallprompt)가 즉시 실행되지 않는 현상

beforeinstallprompt 이벤트를 직접적으로 제어할 수 있는 방법은 없다.

이는 브라우저의 보안 정책과 사용자 경험을 보호하기 위한 설정

따라서 사용자의 상호작용으로 정책 여건이 충족된다면 이벤트가 발생하므로 각각 다르게 실행되는 것 같음.



⭐ Vite PWD ⭐

참고 : Vite PWD 공식 사이트


Vite PWD로 바꾼 이유


만약 수정 -> 빌드 -> 배포 작업이 발생한다면, 새로고침을 해야함

Vite PWD에서 변경된 파일만 서버에서 가져오고,

변경되지 않은 파일은 캐시에서 가져오며,

업데이트 주기를 설정할 수 있어 수정사항을 새로고침 없이 반영할 수 있다.



진행 방법


1. 크롬 인스펙트로 모바일 기기 연동

  • 안드로이드 폰을 노트북과 USB로 연결
  • 폰 개발자 모드 및 USB 디버깅 설정, PTP 연결로 변경
  • chrome://inspect/#devices로 접속하여 Device 연결
  • 만약 안될 경우, USB가 데이터 공유 가능한 USB인지 확인 또는 드라이버가 최신인지 확인


2. https 인증서 작업

  • PWD가 localhost 또는 HTTPS 프로토콜만 사용 가능함, 모바일 연동하려면 IP로 접속해야하여 localhost가 안됨
  • 임시 인증서를 발급받아 셋팅하려고 했으나, 상무님께서 해주심.


3. Simple WebServer 사용하여 웹 서버 생성

  • Simple WebServer 설치
  • 경로는 build 파일이 저장되는 dist, 나머지는 아래 이미지 참고

aspect


이후 작업은 공식 문서 참조, 처음부터 천천히 따라하면 쉽게 할 수 있음.



참고 링크

https://shallwestudy.tistory.com/19