WebView 통신 — 웹과 네이티브 간 데이터 교환
WebView는 앱 안에 웹 페이지를 임베딩하는 컴포넌트입니다. 결제, 약관, 외부 콘텐츠 표시 등에 자주 사용됩니다.
기본 사용
npm install react-native-webview
import { WebView } from 'react-native-webview';
function WebViewScreen() {
return (
<WebView
source={{ uri: 'https://example.com' }}
style={{ flex: 1 }}
// 로딩 인디케이터
startInLoadingState
renderLoading={() => <ActivityIndicator style={{ flex: 1 }} />}
// 에러 처리
renderError={(errorName) => (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>페이지를 불러올 수 없습니다</Text>
</View>
)}
/>
);
}
네이티브 → 웹 통신
import { useRef } from 'react';
import { WebView } from 'react-native-webview';
function NativeToWeb() {
const webViewRef = useRef<WebView>(null);
// 네이티브에서 웹으로 데이터 전송
const sendToWeb = (data: any) => {
const script = `
window.receiveFromNative(${JSON.stringify(data)});
true; // iOS에서 필수
`;
webViewRef.current?.injectJavaScript(script);
};
return (
<View style={{ flex: 1 }}>
<WebView
ref={webViewRef}
source={{ uri: 'https://mywebapp.com' }}
/>
<Pressable onPress={() => sendToWeb({ token: 'abc', userId: '123' })}>
<Text>데이터 전송</Text>
</Pressable>
</View>
);
}
// 웹 측 코드
// window.receiveFromNative = function(data) {
// console.log('네이티브에서 받은 데이터:', data);
// };
웹 → 네이티브 통신
function WebToNative() {
const handleMessage = (event: WebViewMessageEvent) => {
try {
const data = JSON.parse(event.nativeEvent.data);
switch (data.type) {
case 'PAYMENT_COMPLETE':
handlePaymentComplete(data.payload);
break;
case 'NAVIGATE':
navigation.navigate(data.screen, data.params);
break;
case 'CLOSE':
navigation.goBack();
break;
}
} catch (error) {
console.error('메시지 파싱 에러:', error);
}
};
return (
<WebView
source={{ uri: 'https://payment.example.com' }}
onMessage={handleMessage}
// injectedJavaScript로 웹에 브릿지 함수 주입
injectedJavaScript={`
window.sendToNative = function(type, payload) {
window.ReactNativeWebView.postMessage(
JSON.stringify({ type, payload })
);
};
true;
`}
/>
);
}
// 웹 측 코드
// 결제 완료 시:
// window.sendToNative('PAYMENT_COMPLETE', { orderId: '123', amount: 50000 });
결제 모듈 연동 패턴
function PaymentWebView({ orderId, amount }: {
orderId: string;
amount: number;
}) {
const webViewRef = useRef<WebView>(null);
// 결제 페이지 URL에 파라미터 전달
const paymentUrl = `https://payment.example.com?orderId=${orderId}&amount=${amount}`;
const handleMessage = (event: WebViewMessageEvent) => {
const data = JSON.parse(event.nativeEvent.data);
if (data.type === 'PAYMENT_SUCCESS') {
Alert.alert('결제 완료', `주문번호: ${data.orderId}`);
navigation.navigate('OrderComplete', { orderId: data.orderId });
} else if (data.type === 'PAYMENT_FAIL') {
Alert.alert('결제 실패', data.message);
} else if (data.type === 'PAYMENT_CANCEL') {
navigation.goBack();
}
};
return (
<WebView
ref={webViewRef}
source={{ uri: paymentUrl }}
onMessage={handleMessage}
// 결제 관련 설정
javaScriptEnabled={true}
domStorageEnabled={true}
// 외부 앱(카카오페이 등) 이동 허용
originWhitelist={['*']}
onShouldStartLoadWithRequest={(request) => {
// 외부 앱 스킴 처리
if (request.url.startsWith('kakaopay://') ||
request.url.startsWith('intent://')) {
Linking.openURL(request.url);
return false;
}
return true;
}}
/>
);
}
보안 주의사항
<WebView
// 신뢰할 수 있는 도메인만 허용
originWhitelist={['https://myapp.com', 'https://payment.example.com']}
// 파일 접근 차단
allowFileAccess={false}
// 콘텐츠 보안 정책
injectedJavaScript={`
// 민감한 정보를 window 객체에 노출하지 않기
delete window.ReactNativeWebView;
true;
`}
/>
정리
- **네이티브→웹 **:
injectJavaScript로 JS 코드를 실행합니다 - ** 웹→네이티브 **:
window.ReactNativeWebView.postMessage와onMessage를 사용합니다 - 결제 모듈 연동 시 ** 외부 앱 스킴 처리 **(
onShouldStartLoadWithRequest)가 필수입니다 - 메시지는 JSON 문자열 로 주고받고,
type필드로 메시지 종류를 구분하세요 - 보안 을 위해 신뢰할 수 있는 도메인만 허용하세요
댓글 로딩 중...