들어가며..
웹뷰(Next.js)에서 네이티브 앱(iOS/Android)과 연동하여 인증(Face ID, PIN..)을 처리하는 과정 중 무지함 때문에 주말에 집도 못 가고 새벽까지 붙잡고 있었다.. ㅎㅎ
앱팀에서 정의한 onResult() 라는 함수를 Next.js (React) 코드 내에 정의해 두면 네이티브에서 인증 처리를 한 후 다시 웹뷰로 인증 결과를 onResult()를 통해 전달하는 방식이다.
처음에는 단순히 onResult 함수만 정의하면 네이티브 앱이 해당 함수를 직접 호출할 수 있다고 생각했는데.. 아니었다.
💡 네이티브 → 웹뷰 호출
웹뷰 내에서 실행되는 JavaScript와 네이티브 앱이 서로 다른 실행 환경에서 동작하기 때문에 단순히 onResult함수를 정의하면 네이티브 앱이 해당 함수를 직접 호출할 수 없다.
Next.js 코드 내에서 단순히 onResult 함수를 정의하면, 이 함수는 React 컴포넌트 내부에 존재하는 일반 함수일 뿐이다.
🤔 그럼? window 객체를 이용해야 한다.
네이티브 앱(Swift/Kotlin)에서 웹뷰에 데이터를 전달하려면, JavaScript 실행 환경에 접근해야 한다.
이를 위해서 evaluateJavaScript (iOS) 또는 evaluateJavascript (Andorid) 메서드를 사용해서 JS 코드를 실행하는 방식이 일반적이라고 한다.
// iOS (Swift)
func returnToWebView(result: String, webView: WKWebView) {
let jsCode = "window.onResult('\(result)');" // window 객체의 onResult 호출
webView.evaluateJavaScript(jsCode, completionHandler: nil)
}
// Android (Kotlin)
fun returnToWebView(result: String, webView: WebView) {
val jsCode = "window.onResult('$result');"
webView.post {
webView.evaluateJavascript(jsCode, null)
}
}
네이티브에서 실행할 수 있는 코드는 "window.onResult('success');" 같은 문자열 형태의 JavaScript 코드이다.
즉, 네이티브 앱이 웹뷰에서 직접 특정 함수를 호출하려면 window 객체에 해당 함수를 등록해야 한다.
인증 흐름 및 구현 방법
1️⃣ 웹뷰(Next.js)에서 네이티브 앱 호출
- 웹뷰에서 window.location.href를 사용하여 네이티브 앱의 딥링크 실행
- 네이티브 앱이 열리면서 인증 화면으로 이동
const openNativeAuth = () => {
window.location.href = `${APP_REQUEST_AUTH_URL}`;
};
2️⃣ 네이티브 앱에서 인증 진행
- 사용자가 PIN 또는 Face ID 인증 수행
- 인증이 완료되면 웹뷰로 돌아갈 URL을 포함하여 다시 웹뷰를 연다.
3️⃣ 네이티브 앱에서 웹뷰로 결과 전달
- 웹뷰는 onResult(resultLstring) 함수를 통해 인증 결과를 받는다.
- 웹뷰 상태가 유지된 상태에서 결과를 처리한다.
useEffect(() => {
// onResult 함수를 전역 객체에 등록
window.onResult = (result: string) => {
console.log('네이티브 인증 결과:', result);
if (result === 'success') {
alert('인증 성공!');
} else {
alert('인증 실패');
}
};
}, []);
😳 그런데 여기서, 타입스크립트에서는 window 객체에 onResult 같은 커스텀 속성을 추가하면 타입 오류가 발생한다. ("window에 없는 속성" 오류 발생..)
그래서 window 전역 객체 타입 확장이 필요하다.
// global.d.ts 파일
export {};
declare global {
interface Window {
onResult: (result: string) => void;
}
}
정리
- 웹뷰의 실행 환경과 네이티브 앱의 실행 환경은 다르다.
- 네이티브에서 웹뷰로 데이터를 전달하려면 웹뷰의 JavaScript 실행 환경(window 객체)에 접근해야 한다.
- window.onResult 처럼 전역 객체에 함수를 등록하면, 네이티브 앱이 evaluateJavaScript를 통해 해당 함수를 실행할 수 있다.