앱을 개발하다 보면 네이티브 화면과 웹뷰(WebView)를 함께 사용해야 할 때가 있습니다. 예를 들어, 네이티브에서 로그인한 사용자 정보를 웹뷰에서도 그대로 유지하려면 어떻게 해야 할까요? 매번 웹뷰에서 로그인하는 건 사용자 입장에서 불편한 일이겠죠.
이 문제를 해결하려면 네이티브와 웹뷰가 데이터를 주고받을 수 있어야 합니다. postMessage
와 onMessage
를 사용하면 웹뷰에서 네이티브로 데이터를 전달할 수 있고, injectJavaScript
를 활용하면 네이티브에서 웹뷰로 데이터를 보낼 수 있습니다.
같이 활용하면 좋은 기능으로는 onNavigationStateChange
가 있습니다.onNavigationStateChange
를 이용하면 웹뷰에서 다른 페이지로 이동할 때를 감지해서 원하는 동작을 실행시킬 수 있습니다.
이번 글에서는 이 기능들을 활용해서 네이티브와 웹뷰 간 데이터를 연동하는 방법을 알아보고, 다크 모드 적용과 로그인 상태 유지 같은 실용적인 예제도 한번 구현해 보겠습니다.
1. injectJavaScript 활용
injectJavaScript
는 네이티브에서 WebView 내부의 JavaScript 코드를 실행할 때 사용합니다. 웹뷰에 원하는 코드를 주입하거나 document
속성을 변경할 수 있습니다.
배포된 웹 페이지의 소스 코드를 수정하지 않고도 네이티브에서 웹뷰의 코드를 추가할 수 있기 때문에 잘 활용한다면 매우 유용합니다.
다크 모드 적용 예제 코드
import React, { useEffect, useRef } from "react";
import { View, useColorScheme } from "react-native";
import { WebView } from "react-native-webview";
const MyWebView = () => {
const webViewRef = useRef(null);
const colorScheme = useColorScheme(); // 기기의 다크 모드 여부 확인
useEffect(() => {
if (webViewRef.current) {
webViewRef.current.injectJavaScript(`
document.body.style.backgroundColor = '${
colorScheme === "dark" ? "black" : "white"
}';
document.body.style.color = '${
colorScheme === "dark" ? "white" : "black"
}';
`);
}
}, [colorScheme]);
return (
<View style={{ flex: 1 }}>
<WebView ref={webViewRef} source={{ uri: "https://example.com" }} />
</View>
);
};
export default MyWebView;
예제 코드에서는 useColorScheme()
을 사용해 기기의 다크 모드 설정을 감지하고 WebView에 반영하고 있습니다.
2. postMessage와 onMessage 활용
웹뷰에서 로그인하면 네이티브에서 세션 정보를 저장해야 하는 경우가 있습니다. 이때 postMessage
를 사용하면 웹에서 네이티브로 데이터를 전달할 수 있습니다.
로그인 후 토큰 전달 예제 코드
WebView에서 네이티브로 메시지 보내기
import React, { useRef } from "react";
import { View, Alert } from "react-native";
import { WebView } from "react-native-webview";
const MyWebView = () => {
const webViewRef = useRef(null);
const onMessage = (event) => {
try {
const data = JSON.parse(event.nativeEvent.data);
Alert.alert("토큰을 받았습니다!", data.token);
} catch (error) {
console.error("메세지 파싱 오류:", error);
}
};
return (
<View style={{ flex: 1 }}>
<WebView
ref={webViewRef}
source={{
html: `
<html>
<body>
<script>
function sendToken() {
const token = 'auth-token';
window.ReactNativeWebView.postMessage(JSON.stringify({ token }));
}
</script>
<button onclick="sendToken()">Login</button>
</body>
</html>
`,
}}
onMessage={onMessage}
/>
</View>
);
};
export default MyWebView;
이제 웹뷰에서 로그인 버튼을 누르면 네이티브로 토큰이 전달됩니다.
3. onNavigationStateChange 활용
웹뷰에서 로그인 후 완료 페이지(success
페이지)로 이동하면 네이티브에서 이를 감지하고 자동으로 화면을 닫거나, 세션을 저장할 수 있습니다. 또한 injectJavaScript
를 함께 사용하면 웹뷰에서 다른 URL로 이동할 때 네이티브에서 추가적인 처리를 할 수도 있습니다.
로그인 완료 감지 후 알림 예제 코드
import React, { useRef } from "react";
import { View, Alert } from "react-native";
import { WebView } from "react-native-webview";
const MyWebView = () => {
const webViewRef = useRef(null);
const onLoad = () => {
webViewRef.current.injectJavaScript(
"window.ReactNativeWebView.postMessage('로그인 완료')"
);
};
const onNavigationStateChange = (navState) => {
if (navState.url.includes("success")) {
Alert.alert("로그인 성공", "잠시 후 다른 화면으로 이동합니다.");
// 다른 화면으로 이동하는 코드
}
};
return (
<View style={{ flex: 1 }}>
<WebView
ref={webViewRef}
source={{ uri: "https://example.com/login" }}
onLoad={onLoad}
onNavigationStateChange={onNavigationStateChange}
/>
</View>
);
};
export default MyWebView;
이제 웹뷰에서 로그인 성공 페이지로 이동하면 네이티브에서 알림을 띄울 수 있습니다.
주의사항
- 보안을 위해
postMessage
사용 시origin
을 체크하는 것을 권장합니다!
웹뷰 앱 구현 중에 어려운 점이 있다면 댓글로 남겨주세요. 같이 고민해 보겠습니다. 감사합니다! 🙇♂️
'MOBILE APP' 카테고리의 다른 글
React Native BLE에서 MTU 설정으로 데이터 전송량 늘리기 (Android) (1) | 2025.02.14 |
---|---|
React Native에서 SSL 인증서 검증 우회하기 (Expo 포함) (1) | 2025.01.31 |
React Native에서 로컬 서버에 접속하기 (Expo 포함) (0) | 2025.01.24 |
Expo에서 pod install 오류: "cannot load such file -- ./scripts/autolinking" 해결 방법 (0) | 2025.01.23 |