[React-Native] React를 React-native를 통해 Webview로 웹앱 배포하기 (feat. PG 결제 연동)

 

환경설정 (expo)

expo 선택 이유는 행사 일정이 얼마 남지 않아 그 전에 앱 등록이 완료되어야 했고, 위치권한만 필요한 앱이라 expo로 충분히 가능하다고 생각이 들었다. 또한,리액트 네이티브를 처음 접한거라 러닝 커브를 최대한 낮춰야 한다고 생각했다.

 

하단 두개의 블로그를 참고하여 환경설정 셋팅을 완료하였습니다.

1. https://velog.io/@chloedev/React-Native]

 

[React-Native] 리액트 네이티브 개발 환경 구축하기(for Mac)(* 업데이트 중)

📌 Cross-platform 앱 개발을 위한 React-Native 개발환경 구축 크로스플랫폼 앱 개발을 하기에 앞서 React-Native와 Flutter를 고민하고 있다면 비교 article 읽어보기 -> Flutter vs React-native, Flutte

velog.io

2. https://ssjeong.tistory.com/entry/React-Native

 

[React-Native] 프로젝트 생성 및 에뮬레이터 실행

안녕하세요! 프뚜(프로그래머 뚜)입니다! [개발 환경] - OS: windows 10 64bit - Node: v14.16.0 - Npm: v6.14.11 - Target: Android Emulator Or Android Phone (윈도우에서 사용하기 때문에 iOS 지원X) 저번 포스팅에는 개발

ssjeong.tistory.com

 

오류 (PG 결제)

react-native-webview를 이용하여 모바일 web으로 이동한 후 앱 카드 결제 시 앱 카드 앱 호출이 되지 않는 문제가 생겼다.

ios

URL의 스킴을 추출한 다음 iosSchemes에 있는지 검사 후 native 내장 함수 Linking.openURL을 통해 앱을 열 수 있게 수정했다.

 const scheme = url.split(":")[0] + "://"; // URL의 스킴 추출
      if (iosSchemes.includes(scheme)) {
        Linking.openURL(url)
          .then(() => console.log("URL 성공적으로 열림:", url))
          .catch((err) => {
            console.error("URL 열기에 실패함:", err);
            Alert.alert(
              "앱이 설치되어 있지 않습니다,",
              " 앱 설치 후 다시 시도해주세요."
            );
          });

        return false; // WebView에서 로드하지 않음
      } else {
        return true;
      }

 

android

url을 직접 호출해가며 intent의 형식을 파악했고, url이 intent:로 시작하는지 확인 후 만약 url이 인텐트 형식이라면, openAndroidUrl(url) 함수를 호출하여 외부 앱을 실행시켰다.

intent: 다른 앱을 호출하거나 특정 작업을 수행하기 위해 사용되는 Android 고유의 URL 형식

 const packageNames = Object.values(androidPackageNames);

      // 외부 앱 호출 처리

      if (packageNames.some((pkg) => url.includes(pkg))) {
        if (event.url.startsWith("intent:")) {
          openAndroidUrl(url);
        }

        return false; // WebView에서 로드하지 않음
      }

 

const openAndroidUrl = async (url: string) => {
    // const testUrl =
    //   "intent://www.youtube.com/watch?v=dQw4w9WgXcQ#Intent;scheme=https;package=com.google.android.youtube;end;";
    const intents = url.split("#Intent;");
    const path = intents[0] || "";
    const query = intents[1] || "";
    const params: Record<string, string> = {}; // params는 key-value 형태의 객체

    query.split(";").forEach((each: any) => {
      if (each.includes("=")) {
        const pairs = each.split("=");
        params[pairs[0]] = pairs[1];
      }
    });

    const scheme = params?.scheme;
    const packageName = params?.package;
    const data = path.replace("intent://", `${scheme}://`);

    try {
      // Android 인텐트 실행
      const result = await startActivityAsync("android.intent.action.VIEW", {
        data, // 예: kakaotalk://
        packageName, // 예: com.kakao.talk
      });

      console.log("result : ", result);
    } catch (error) {
      console.error("URL 열기에 실패함:", error);
      Alert.alert(
        "앱이 설치되어 있지 않습니다,",
        " 앱 설치 후 다시 시도해주세요."
      );
    }
  };

 

빌드

https://docs.expo.dev/build/setup/

 

Create your first build

Learn how to create a build for your app with EAS Build.

docs.expo.dev