
사용자가 웹 사이트를 방문했을 때 다운로드를 받을 수 있는 사이트인지 잘 모르는 경향이 있습니다.
그래서 설치를 유도하는 것이 중요하다고 생각해서 찾아보다 나온 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;
}

