사용자가 웹 사이트를 방문했을 때 다운로드를 받을 수 있는 사이트인지 잘 모르는 경향이 있습니다.
그래서 설치를 유도하는 것이 중요하다고 생각해서 찾아보다 나온 beforeinstallprompt!
beforeinstallprompt 이벤트는 웹사이트가 사용자에게 앱을 설치할 수 있다는 메세지를 표시하기 전에 발생합니다.
그렇기 때문에 사용자에게 설치 버튼을 표시할 수 있고, 설치 안내를 제공할 수 있고, 설치 프로세를 생략할 수도 있게합니다.
window.addEventListener('beforeinstallprompt', (e) => {
e.preventDefault();
deferredPrompt = e;
});
고려해야 할 상황도 있었습니다.
왜냐하면 safari에서는 beforeinstallprompt가 지원하지 않는다는 사실..
iOS에서는 PWA에대해 안드로이드만큼 지원을 잘 안해줍니다ㅠ
그래서 애플 기기인지 파악을 하여 다른 배너를 보여주여야 겠다고 생각하였습니다.
const isDeviceIOS =
/iPad|iPhone|iPod/.test(window.navigator.userAgent) && !window.MSStream;
setIsIOS(isDeviceIOS);
브라우저의 userAgent
를 이용해 현재 사용 중인 기기가 iOS 기반 장치인지 확인하는 코드입니다.
정규식을 이용해서 userAgent 문자열에서 'iPad', 'iPhone' 또는 'iPod' 단어가 있는지 확인합니다.
윈도우 기반 장치에서 iOS를 모방하는 경우도 있기 때문에 !window.MSStream
도 추가해줍니다. 현재 환경이 윈도우 환경인지를 확인합니다.
Mozilla/5.0 (iPhone; CPU iPhone OS 16_4_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.4 Mobile/15E148 Safari/604.1
const InstallPrompt = () => {
const [isShown, setIsShown] = useState(false);
const [isIOS, setIsIOS] = useState(false);
const [deferredPrompt, setDeferredPrompt] = useState(null);
useEffect(() => {
const isDeviceIOS =
/iPad|iPhone|iPod/.test(window.navigator.userAgent) && !window.MSStream;
setIsIOS(isDeviceIOS);
const handleBeforeInstallPrompt = e => {
e.preventDefault();
setDeferredPrompt(e);
setIsShown(true);
};
window.addEventListener('beforeinstallprompt', handleBeforeInstallPrompt);
return () => {
window.removeEventListener(
'beforeinstallprompt',
handleBeforeInstallPrompt,
);
};
}, []);
// ... 코드 생략 ...
if (!isIOS && !isShown) {
return null;
}
return (
/* 설치 프롬프트 컴포넌트 */
);
};
export default InstallPrompt;
최종적으로 위와 같이 코드를 작성하였습니다.
beforeinstall 이벤트가 발생하면 이를 캐치하여 사용자에게 설치 프롬프트를 보여줍니다.
또한 iOS와 같은 환경에서 다른 메세지를 보여줍니다.
const handleClick = async () => {
setIsShown(false);
if (!deferredPrompt) {
return;
}
deferredPrompt.prompt();
const { outcome } = await deferredPrompt.userChoice;
setDeferredPrompt(null);
};
setIsShown(false)
: 설치 프롬프트를 숨깁니다.if (!deferredPrompt) { return; }
: deferredPrompt 객체가 있는지 확인합니다. (웹앱을 설치하지 못하는 상태이면 종료되도록합니다)deferredPrompt.prompt()
: 웹 앱 설치를 요청하는 프롬프트를 표시합니다.const { outcome } = await deferredPrompt.userChoice;
: 사용자가 설치 프롬프트에 어떻게 응답했는지를 기다린 후, 그 결과를 받습니다.setDeferredPrompt(null)
: deferredPrompt
를 초기화합니다. 웹앱 설치를 요청한 후에는 이 객체를 더이상 사용할 수 없기 때문입니다. if (!isIOS && !isShown) {
return null;
}