React Native WebView에서 네이티브와 데이터 주고받기

2025. 3. 18. 18:00·MOBILE APP

앱을 개발하다 보면 네이티브 화면과 웹뷰(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
'MOBILE APP' 카테고리의 다른 글
  • React Native BLE에서 MTU 설정으로 데이터 전송량 늘리기 (Android)
  • React Native에서 SSL 인증서 검증 우회하기 (Expo 포함)
  • React Native에서 로컬 서버에 접속하기 (Expo 포함)
  • Expo에서 pod install 오류: "cannot load such file -- ./scripts/autolinking" 해결 방법
shinejung
shinejung
저의 블로그에 오신것을 환영합니다. 프론트엔드 개발을 많이 다룹니다.
  • shinejung
    shine.log
    shinejung
  • 전체
    오늘
    어제
    • 전체 글 (7)
      • FRONTEND (0)
      • BACKEND (0)
      • MOBILE APP (5)
      • 프로젝트 (1)
      • 후기 (1)
      • 회고 (0)
      • 기타 (0)
  • 블로그 메뉴

    • 방명록
    • 태그
  • 링크

    • 홈페이지
    • 깃허브
    • 링크드인
  • 인기 글

  • 태그

    webview
    프로젝트
    swift student challenge
    Android
    스위프트 스튜던트 챌린지
    WWDC
    expo
    ios
    양자역학
    보드게임
    오목
    React Native
    SWIFT
    apple
    bluetooth
    오류 해결
    AR
    ble
    https
  • 최근 댓글

  • 최근 글

  • 반응형
  • hELLO· Designed By정상우.v4.10.3
shinejung
React Native WebView에서 네이티브와 데이터 주고받기
상단으로

티스토리툴바