티스토리 뷰

이전 게시글이 선행되면 좋습니다 

 

사이트를 모바일 웹앱으로 실행되도록 하는 방법 (feat.apple-meta-tag)

사이트를 모바일 웹앱으로 실행되도록 하는 방법 1. html의 header에 다음과 같이 넣어주면 됩니다 // 홈 화면에 추가했을 때 보여질 앱의 이름 // 모바일에서 전체화면으로 보이게 할 지 여부 // 상

hell-of-company-builder.tistory.com

 

프로그레시브 웹 앱(PWA)이란

프로그레시브 웹 앱은 웹 기술을 사용하여 개발된 애플리케이션으로, 사용자가 웹 브라우저에서 접속할 수 있으며 모바일 앱과 비슷한 사용자 경험을 제공합니다. 이러한 웹 앱은 오프라인에서도 작동할 수 있으며, 푸시 알림을 받을 수 있고, 홈 화면에 아이콘을 추가하여 쉽게 접근할 수 있습니다. 프로그레시브 웹 앱은 기기 또는 운영체제에 구애받지 않고 모든 플랫폼에서 동작할 수 있습니다.


PWA의 이점

  • 스마트폰 사용자의 50%는 앱 다운로드를 원하지 않기 때문에 검색하거나 쇼핑할 때 회사의 모바일 사이트를 사용할 가능성이 더 큽니다
  • 앱을 제거하는 가장 큰 이유 중 하나는 제한된 저장 공간입니다 (설치된 PWA는 일반적으로 1MB 미만 사용).
  • 스마트폰 사용자는 제품에 대한 관련 추천을 제공하는 모바일 사이트에서 구매할 가능성이 더 높으며 스마트폰 사용자의 85%는 모바일 알림이 유용하다고 말합니다.

PWA를 충족시키는 조건

beforeinstallprompt 이벤트를 실행하고 브라우저 내 설치 프로모션을 표시하기 전에 다음 기준을 충족해야 합니다.

  • 웹 앱이 아직 설치되지 않음
  • HTTPS를 통해 제공

또한 다음을 포함하는 웹 앱 매니페스트가 있어야 합니다.

  • short_name 또는 name
  • icons - 192px 및 512px 아이콘을 포함해야 합니다.
  • start_url
  • display fullscreen , standalone 또는 minimal-ui 중 하나여야 합니다.
  • prefer_related_applications이 존재하거나 false여서는 안 됩니다.

앱 설치를 유도하는 디자인 종류


보투게더에서 사용한 설치를 묻는 디자인

IOS에서 보이는 설치 화면

안드로이드에서 보이는 설치 화면

데스크톱 브라우저 상단에서 설치할 수 있는 버튼


PWA를 지원하는 브라우저 및 디바이스 종류

데스크톱에서:

  • Firefox와 Safari는 어떤 데스크톱 운영 체제에서도 PWA를 설치하는 것을 지원하지 않습니다.
  • Chrome과 Edge는 Linux, Windows, macOS 및 Chromebook에서 PWA를 설치하는 것을 지원합니다.

모바일에서:

  • Android에서는 Firefox, Chrome, Edge, Opera 및 Samsung Internet Browser가 모두 PWA를 설치하는 것을 지원합니다.
  • iOS 16.3 이전 버전에서는 PWA를 Safari만을 통해서만 설치할 수 있습니다.
  • iOS 16.4 이후 버전에서는 PWA를 Safari, Chrome, Edge, Firefox 및 Orion의 공유 메뉴를 통해 설치할 수 있습니다.

홈 화면에 추가하는 것을 묻는 코드 예시

manifest.json 설정

  • short_name 또는 name
  • icons - 192px 및 512px 아이콘을 포함해야 합니다.
  • start_url
  • display fullscreen , standalone 또는 minimal-ui 중 하나여야 합니다.
  • prefer_related_applications이 존재하거나 false여서는 안 됩니다.
{
  "name": "VoTogether",
  "short_name": "VoTogether",
  "icons": [
    {
      "src": "./android-icon-36x36.png",
      "sizes": "36x36",
      "type": "image/png",
      "density": "0.75",
      "purpose": "any maskable"
    },
    {
      "src": "./android-icon-48x48.png",
      "sizes": "48x48",
      "type": "image/png",
      "density": "1.0",
      "purpose": "any maskable"
    },
    {
      "src": "./android-icon-72x72.png",
      "sizes": "72x72",
      "type": "image/png",
      "density": "1.5",
      "purpose": "any maskable"
    },
    {
      "src": "./android-icon-96x96.png",
      "sizes": "96x96",
      "type": "image/png",
      "density": "2.0",
      "purpose": "any maskable"
    },
    {
      "src": "./android-icon-144x144.png",
      "sizes": "144x144",
      "type": "image/png",
      "density": "3.0",
      "purpose": "any maskable"
    },
    {
      "src": "./android-icon-192x192.png",
      "sizes": "192x192",
      "type": "image/png",
      "density": "4.0",
      "purpose": "any maskable"
    },
    {
      "src": "/images/android-icon-512x512.png",
      "type": "image/png",
      "sizes": "512x512",
      "density": "5.0",
      "purpose": "any maskable"
    }
  ],
  "start_url": "/",
  "display": "standalone",
  "background_color": "#ffffff",
  "theme_color": "#ffffff"
}

구글의 LightHouse에서 PWA을 얼마나 충족하고 있는지 확인해볼수 있습니다

 


beforeinstallprompt 이벤트를 이용해서 홈 화면에서 설치하는 것을 물어볼 수 있습니다

beforeinstallprompt는 Progressive Web App (PWA)를 설치하기 전에 사용자에게 설치 프롬프트를 제공하기 위한 이벤트입니다. 이 이벤트는 웹 앱이 PWA로서 설치 가능한지 여부를 확인한 후, 설치할 것인지 묻는 팝업 창을 사용자에게 보여줄 수 있습니다. 사용자가 설치 프롬프트를 수락하면 매니페스트 파일에서 정의한 설치 프로세스가 시작되며, 웹 앱이 사용자의 기기에 설치됩니다.


beforeinstallprompt의 브라우저 호환성

beforeinstallprompt은 실험적인 기술이며, 특정 브라우저에서 예상대로 작동하지 않을 수 있습니다.


beforeinstallprompt은 IOS에서는 사용할 수 없습니다


예시 코드

  1. ios에서 사이트를 이용하고 있다면 safari 브라우저에서 책갈피를 통해 홈 화면에 추가하라고 알려야 하기에 조건문으로 컴포넌트가 보이도록 설정합니다

isDeviceIOS가 true라면 defaultBeforeInstallPromptEvent을 deferredPrompt의 초기값으로 설정하여 컴포넌트가 보이도록 합니다. 사용자가 프롬프트를 보고 닫기를 눌렀을 경우 로컬스토리지에 localStorage.setItem('iosInstalled', 'false');을 설정해주고 사용자가 페이지 이동 후 다시 보여질수도 있기 때문에 const isActive = JSON.parse(localStorage.getItem('iosInstalled') || 'true');와 같은 코드로 보이지 않도록 설정해줍니다.

const defaultBeforeInstallPromptEvent: BeforeInstallPromptEvent = {
  platforms: [],
  userChoice: Promise.resolve({ outcome: 'dismissed', platform: '' }),
  prompt: () => Promise.resolve(),
  preventDefault: () => {},
};

const isIOSPromptActive = () => {
  const isActive = JSON.parse(localStorage.getItem('iosInstalled') || 'true');

  if (isActive) {
    return defaultBeforeInstallPromptEvent;
  }

  return null;
};

export default function AppInstallPrompt() {
  const isDeviceIOS = /iPad|iPhone|iPod/.test(window.navigator.userAgent);
  const [deferredPrompt, setDeferredPrompt] = useState<BeforeInstallPromptEvent | null>(
    isDeviceIOS ? isIOSPromptActive() : null
  );
  
 
    const handleCancelClick = () => {
    localStorage.setItem('iosInstalled', 'false');
    setDeferredPrompt(null);
  };

  1. beforeinstallprompt 이벤트가 발생한다면 setDeferredPrompt에 beforeinstallprompt이벤트를 설정합니다.
 const handleBeforeInstallPrompt = (event: BeforeInstallPromptEvent) => {
    event.preventDefault();
    setDeferredPrompt(event);
  };

  1. deferredPrompt가 존재한다면 사용자에게 보여질 컴포넌트를 렌더해줍니다.
 {deferredPrompt && (
        <MobileInstallPrompt
          handleInstallClick={handleInstallClick}
          handleCancelClick={handleCancelClick}
          platform={isDeviceIOS ? 'ios' : 'android'}
        />
      )}

  1. 사용자가 선택했다면 setDeferredPrompt을 null로 바꿔줘서 사용자에게 보이지 않도록 합니다.
  const handleInstallClick = () => {
    if (deferredPrompt) {
      deferredPrompt.prompt();

      deferredPrompt.userChoice.then(() => {
        setDeferredPrompt(null);
      });
    }
  };

전체 코드

import { Fragment, useEffect, useState } from 'react';

import { BeforeInstallPromptEvent } from '../../../../window';

import MobileInstallPrompt from './MobileInstallPrompt';

const defaultBeforeInstallPromptEvent: BeforeInstallPromptEvent = {
  platforms: [],
  userChoice: Promise.resolve({ outcome: 'dismissed', platform: '' }),
  prompt: () => Promise.resolve(),
  preventDefault: () => {},
};

const isIOSPromptActive = () => {
  const isActive = JSON.parse(localStorage.getItem('iosInstalled') || 'true');

  if (isActive) {
    return defaultBeforeInstallPromptEvent;
  }

  return null;
};

export default function AppInstallPrompt() {
  const isDeviceIOS = /iPad|iPhone|iPod/.test(window.navigator.userAgent);
  const [deferredPrompt, setDeferredPrompt] = useState<BeforeInstallPromptEvent | null>(
    isDeviceIOS ? isIOSPromptActive() : null
  );

  const handleInstallClick = () => {
    if (deferredPrompt) {
      deferredPrompt.prompt();

      deferredPrompt.userChoice.then(() => {
        setDeferredPrompt(null);
      });
    }
  };

  const handleCancelClick = () => {
    localStorage.setItem('iosInstalled', 'false');
    setDeferredPrompt(null);
  };

  const handleBeforeInstallPrompt = (event: BeforeInstallPromptEvent) => {
    event.preventDefault();
    setDeferredPrompt(event);
  };

  useEffect(() => {
    window.addEventListener('beforeinstallprompt', handleBeforeInstallPrompt);

    return () => {
      window.removeEventListener('beforeinstallprompt', 		        handleBeforeInstallPrompt);
    };
  }, []);

  return (
    <Fragment>
      {deferredPrompt && (
        <MobileInstallPrompt
          handleInstallClick={handleInstallClick}
          handleCancelClick={handleCancelClick}
          platform={isDeviceIOS ? 'ios' : 'android'}
        />
      )}
    </Fragment>
  );
}

타입스크립트 beforeinstallprompt 이벤트 타입 적용

global로 선언해주어서 any가 아닌 beforeinstallprompt의 타입을 적용할 수 있습니다.

window.d.ts

export interface BeforeInstallPromptEvent {
  readonly platforms: string[];
  readonly userChoice: Promise<{
    outcome: 'accepted' | 'dismissed';
    platform: string;
  }>;
  preventDefault(): void;
  prompt(): Promise<void>;
}

declare global {
  interface WindowEventMap {
    beforeinstallprompt: BeforeInstallPromptEvent;
  }
}

참고 자료

https://web.dev/what-are-pwas/ (PWA란)

https://web.dev/drive-business-success/ (PWA의 이점)

https://web.dev/customize-install/ (자신만의 인앱 설치 경험을 제공하는 방법)

https://web.dev/promote-install/ (PWA 설치 촉진 디자인 패턴)

https://web.dev/install-criteria/ (PWA 설치가 가능하기 위한 조건)

https://web.dev/codelab-make-installable/ (PWA 설치 코드 예제)

https://kagrin97-blog.vercel.app/react/pwa-beforeInstallPrompt (PWA 설치 코드 예제 2)

https://stackoverflow.com/questions/51503754/typescript-type-beforeinstallpromptevent (beforeinstallprompt 이벤트 타입스크립트 적용하기)

https://developer.mozilla.org/en-US/docs/Web/Progressive_web_apps/Guides/Making_PWAs_installable (지원하는 브라우저 종류)

https://developer.mozilla.org/en-US/docs/Web/API/BeforeInstallPromptEvent (beforeinstallprompt MDN)

https://wonsss.github.io/PWA/before-install-prompt/

 

 

보투게더 기술 블로그에서 작성한 글을 가져왔습니다

 

 

프로그레시브 웹 앱(PWA)이란, 인앱 설치를 묻는 화면 구현하기 (feat.beforeinstallprompt)

beforeinstallprompt 이벤트를 이용해서 홈 화면에서 설치하는 것을 물어볼 수 있습니다 beforeinstallprompt는 Progressive Web App (PWA)를 설치하기 전에 사용자에게 설치 프롬프트를 제공하기 위한 이벤트입니

velog.io

 

 

 

 

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
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
26 27 28 29 30 31
글 보관함