회사에서 웹으로 개발한 프로젝트를 앱으로 패키징 작업을 진행하였습니다.
앱에서 로그인 유지와 사진첩 권한, 팝업 창 설정 등등을 해줘야 하기 때문에 brdige 연결 작업을 진행했습니다.
진행하고 생각해보면 그렇게 어려운 작업은 아니였는데, 연결 과정에서는 정말 많은 시행착오를 겪었습니다.
그래서 기록으로 남기기 위해 블로그에 작성하기로 결정했습니다.
nextjs에서 작업을 진행했기에 nextjs 위주로 작성하겠습니다.
// _app.tsx 파일에서
const dispatch = useDispatch();
useEffect(() => {
// userAgent에 ios // android 가 있는 지 확인해줍니다.
const iOS = navigator.userAgent.match(/iOS_App/i);
const Android = navigator.userAgent.match(/Android_App/i);
// 전역으로 사용할 것이기 때문에 리덕스에 데이터를 보관해주었습니다.
if (iOS) dispatch(userAgentAction.set('iOS_App'));
if (Android) dispatch(userAgentAction.set('Android_App'));
}, []);
_app.tsx
파일에서 useEffect로 기기판별을 하도록 해주었습니다. // 웹에서 앱 함수를 실행 시켜준다.
// 여기서 신경써야할 부분은 함수명이 같아야하고, paramter값을 알고 있어야한다.
// 보통은 안드로이드와 iOS가 별도로 처리되니, 따로 분기 처리를 해줄 필요가 있다.
requestPermissionCheck = () => {
if (userAgent === 'Android_App') {
window.android.test();
} else if (userAgent === 'iOS_App') {
window.webkit.messageHandlers.test.postMessage('');
}
}
window.webkit.messageHandlers.[함수이름].postMessage()
로 호출해주면 됩니다.useEffect(() => {
if (userAgent === 'Android_App') {
window.test = () => {alert('안드로이드 호출 성공!')};
} else if (userAgent === 'iOS_App') {
window.test = () => {alert('iOS 호출 성공!')};
}
},[])
<meta
name="viewport"
content="initial-scale=1.0,userscalable=no,maximum-scale=1,width=device-width"
/>
//파일 온클릭
const handleFileClick = () => {
// 앱이 아닐 경우 그냥 클릭
if (userAgent === '') {
fileRef?.current?.click();
} else {
// 앱일 경우 웹 => 앱 브릿지 신청
requestPermissionCheck(userAgent, 'file');
}
};
// 앱에서 이미지 or 파일 온클릭 (앱->웹)
useEffect(() => {
if (userAgent === 'Android_App') {
window.openGallery = () => {
imgRef?.current?.click();
};
window.openFileUpload = () => {
fileRef?.current?.click();
};
} else if (userAgent === 'iOS_App') {
window.openGallery = () => {
imgRef?.current?.click();
};
window.openFileUpload = () => {
fileRef?.current?.click();
};
}
}, []);
// 사진 input box `capture={true}` 추가
// 안드로이드는 capture atrribute가 필요하지만, iOS는 없어야 합니다. 별도 처리가 필요합니다.
<input
ref={imgRef}
type="file"
accept="image/*"
capture={userAgent === 'Android_App' && true}
/>
capture={true}
추가합니다.저희 프로젝트의 경우는 로그인 했을 때 웹에서 앱으로 브릿지를 보냅니다. 보낼 때 로그인 할때 필요한 데이터를 보내줍니다.
로그아웃 할땐 그 데이터들을 삭제해주는 브릿지를 호출해줍니다.
이렇게만 하면 간단하지만, 앱에서 로그인 상태를 유지를 하기위해서는 데이터가 있는지 확인 과정이 필요합니다.
그래서 스플래쉬페이지 or 메인페이지에서 로그인에 필요한 데이터가 기기에 저장되어 있는지 확인을 하기위한 브릿지를 한번 더 호출합니다.
만약 그 브릿지가 있으면 브라우저 로컬스토리지에 저장해서 로그인 처리를 해주고 없다면, 비로그인 상태로 유지됩니다.
** 하이브리드앱이라서 모든 처리는 웹에서 하기 때문에 로그인 유무도 브라우저에서 처리하는 방식으로 진행해야합니다.
즉, 로컬스토리지 or 쿠키에 로그인 필요 데이터가 없으면 로그인 상태가 풀리게 되고, 있으면 로그인 상태가 유지되게 됩니다.
https://www.howdy-mj.me/next/how-to-detect-device
https://gradler.tistory.com/33