[React Native] AdMob 연동기

aborile·2023년 6월 23일
2

React Native

목록 보기
6/8
post-thumbnail

Google AdMob 설정

Google AdMob 가입

본인 인증을 위한 재로그인 후, 생년월일을 등록해두지 않은 계정이라면 가입 전 생년월일 등 개인 정보를 입력하는 페이지가 뜬다.

해당 정보를 입력하고 재접속하면 (자동 리다이렉션이 안 된다...) 이메일 수신 여부, 국가 설정, 이용약관 동의 후 계정 가입이 완료된다!

단, 안내 문구에서도 적혀 있듯 결제 정보를 입력하고 난 이후에 검토 절차가 시작되고, 검토에는 몇 시간 정도가 소요될 수 있으니 가급적 결제 정보를 빨리 입력하자. (나는 이 문구를 대충 읽고 지나갔어서... 며칠 째 검토가 안 되다가 결제 정보를 넣으니 1~2시간만에 검토가 완료되었다.)

어플리케이션 등록

스토어에 이미 등록해 둔 어플리케이션이 있어서 쉽게 등록할 수 있었다.

각 플랫폼을 선택한 뒤, 본인 어플의 package name / bundle id를 입력해서 추가하고, 정보를 다시 확인하고 나면 간단하게 앱 추가를 할 수 있다.

광고 단위 추가

등록 완료 후 광고 단위를 추가할 수 있다.

자신이 원하는 유형의 광고를 골라 추가하면 된다. 나의 경우, 배너 광고와 리워드 광고를 테스트 해보았다.

배너 광고

기본적으로 광고 단위를 추가하려면 형식을 선택한 후 이름만 지정해 주면 되지만, 광고 유형이나 eCPM 등 고급 설정을 선택할 수도 있다. 나는 대기업 구글이 알아서 잘 해주겠지 하는 심정으로 아무 옵션을 건드리지 않았다.

리워드 광고

리워드 광고나 보상형 전면 광고에서는 광고 단위 이름 뿐만 아니라 광고 시청 후에 얻을 리워드를 미리 설정해 두어야 한다. 추후에 광고를 로딩하고 시청할 때에 여기에서 설정한 대로 리워드 정보가 넘어간다.

또한 보상형 광고는 고급 설정에서 SSV(Server Side Verification)을 지정할 수 있다.

미리 정의해 둔 (혹은 앞으로 구현할) 콜백으로 사용할 서버 URL을 여기서 등록해 두면, 나중에 해당 광고를 유저가 시청 완료했을 때 자동으로 서버에 콜백을 보내 서버 측에서 바로 검증하고 보상을 지급할 수 있다.

app-ads.txt 설정

app-ads.txt 설정을 하지 않으면 다음과 같은 주의 문구가 뜬다. 실제로 광고를 게시하는 데에는 이상이 없어 보이나, 광고 수익이 감소할 수 있다는 문구가 신경 쓰였다.

app-ads.txt로 이동 버튼을 누르면 다음과 같은 대시보드가 뜨며 설정하는 방법을 안내한다.

혹은 고객센터에서 설정하는 방법에 대한 자세한 가이드를 확인할 수 있다.

결국 요지는, 광고를 적용하려고 연동한 각 앱에 개발자 웹사이트를 설정하고, 해당 사이트에 app-ads.txt를 업로드하면 된다는 것이다. 구글 플레이스토어의 경우 앱 정보 - 스토어 설정 - 스토어 등록정보 연락처 세부정보 - 웹사이트를 추가하면 되고, 앱스토어의 경우 앱 정보 내 마케팅 URL을 추가하면 된다.

단, 앱스토어의 도메인 URL을 변경했다면, Google 크롤러에서 변경을 감지하기까지 최대 7일이 소요될 수 있다고 한다.

react-native-google-mobile-ads 연동

나는 AdMob를 연동할 라이브러리로 react-native-google-mobile-ads를 선택하였다. 최근 사용량이 가장 많기도 하고, react-native-firebase를 만든 invertase 팀에서 만든 라이브러리이다.

공식 문서가 있기는 한데 타이핑이 안 맞거나 누락되는 등 세세한 사항이 깔끔하게 정리되어 있지는 않은 느낌이다. (그래도 설치 가이드는 구체적이고 정확하게 작성되어 있어 다행이다...)

Installation

# Install the admob module
yarn add react-native-google-mobile-ads
# Do pod install

라이브러리 설치를 완료하면, 프로젝트 root에 있는 app.json 파일에 연동 정보를 추가해 주어야 한다. 위의 AdMob 대시보드에서 생성/연동한 각 OS 별 App ID를 추가한다. (광고 단위의 Ad Unit ID가 아닌 App ID임에 유의하자)

{
  "name": "my-app",
  "displayName": "my-app",
  "react-native-google-mobile-ads": {
    "android_app_id": "ca-app-pub-xxxxxxxx~xxxxxxxx",
    "ios_app_id": "ca-app-pub-xxxxxxxx~xxxxxxxx"
  }
}

또한 iOS 구현을 하고 있다면, SKAdNetwork tracking을 위해 동일한 파일에 50개의 SKAdNetwork ID를 추가해야 한다. (IDFA를 사용할 수 없을 때 구글과 기타 써드파티가 전환 추적을 할 수 있게 도와주는 기능이라고 한다.)

{
  "react-native-google-mobile-ads": {
    "android_app_id": "ca-app-pub-xxxxxxxx~xxxxxxxx",
    "ios_app_id": "ca-app-pub-xxxxxxxx~xxxxxxxx",
    "sk_ad_network_items": [
      "cstr6suwn9.skadnetwork",
      "4fzdc2evr5.skadnetwork",
      "4pfyvq9l8r.skadnetwork",
      "2fnua5tdw4.skadnetwork",
      "ydx93a7ass.skadnetwork",
      "5a6flpkh64.skadnetwork",
      "p78axxw29g.skadnetwork",
      "v72qych5uu.skadnetwork",
      "ludvb6z3bs.skadnetwork",
      "cp8zw746q7.skadnetwork",
      "c6k4g5qg8m.skadnetwork",
      "s39g8k73mm.skadnetwork",
      "3qy4746246.skadnetwork",
      "3sh42y64q3.skadnetwork",
      "f38h382jlk.skadnetwork",
      "hs6bdukanm.skadnetwork",
      "prcb7njmu6.skadnetwork",
      "v4nxqhlyqp.skadnetwork",
      "wzmmz9fp6w.skadnetwork",
      "yclnxrl5pm.skadnetwork",
      "t38b2kh725.skadnetwork",
      "7ug5zh24hu.skadnetwork",
      "9rd848q2bz.skadnetwork",
      "y5ghdn5j9k.skadnetwork",
      "n6fk4nfna4.skadnetwork",
      "v9wttpbfk9.skadnetwork",
      "n38lu8286q.skadnetwork",
      "47vhws6wlr.skadnetwork",
      "kbd757ywx3.skadnetwork",
      "9t245vhmpl.skadnetwork",
      "a2p9lx4jpn.skadnetwork",
      "22mmun2rn5.skadnetwork",
      "4468km3ulz.skadnetwork",
      "2u9pt9hc89.skadnetwork",
      "8s468mfl3y.skadnetwork",
      "av6w8kgt66.skadnetwork",
      "klf5c3l5u5.skadnetwork",
      "ppxm28t8ap.skadnetwork",
      "424m5254lk.skadnetwork",
      "ecpz2srf59.skadnetwork",
      "uw77j35x4d.skadnetwork",
      "mlmmfzh3r3.skadnetwork",
      "578prtvx9j.skadnetwork",
      "4dzt52r2t5.skadnetwork",
      "gta9lk7p23.skadnetwork",
      "e5fvkxwrpn.skadnetwork",
      "8c4e2ghe7u.skadnetwork",
      "zq492l623r.skadnetwork",
      "3rd42ekr43.skadnetwork",
      "3qcr597p9d.skadnetwork"
    ]
  }
}

iOS에서는 IDFA 접근을 위해 App Tracking Transparency 설정 또한 해주어야 한다. 기존 프로젝트에서 해당 설정을 해두지 않았다면 마찬가지로 app.json 내에 user_tracking_usage_description 옵션을 넘겨 권한 허용 문구를 설정할 수 있다.

{
  "react-native-google-mobile-ads": {
    "android_app_id": "ca-app-pub-xxxxxxxx~xxxxxxxx",
    "ios_app_id": "ca-app-pub-xxxxxxxx~xxxxxxxx",
    "user_tracking_usage_description": "This identifier will be used to deliver personalized ads to you."
  }
}

또한 별도로 권한 허용을 체크해야 하는데, 공식 문서 상으로는 react-native-permissions 라이브러리를 추천하고 있다.

Initialize

AdMob 대시보드에서 설정한 앱의 기본 광고 설정이 올바르지 않은 경우, 모든 광고 요청에 적용할 설정을 별도로 지정할 수 있다. (예를 들어, 앱이 어린이를 대상으로 하는 경우 광고를 로드하기 전에 어린이에게 적합한 콘텐츠만 수신하도록 구성해야 한다.) 맞춤 configuration이 필요한 경우 광고 SDK를 초기화하기 전에 setRequestConfiguration 메소드를 호출해야 한다.

광고를 로드하기 전 Google Mobile Ads SDK를 초기화하는 작업은 (보통은 앱 실행 시) 최초 1회만 실행하면 된다. mobileAds().initialize() 함수를 사용하면 SDK를 초기화하고, 초기화 완료 또는 30초의 시간 초과를 알리는 Promise를 반환한다. 단, 위에서 말한 맞춤 configuration이 필요한 경우, 반드시 initialize 전에 setRequestConfiguration를 진행해야 한다.

import mobileAds, { MaxAdContentRating } from "react-native-google-mobile-ads";

const configureAdMob = async () => {
  await mobileAds().setRequestConfiguration({
    // Update all future requests suitable for parental guidance
    maxAdContentRating: MaxAdContentRating.PG,

    // Indicates that you want the ad request to be handled in a
    // manner suitable for users under the age of consent.
    tagForUnderAgeOfConsent: true,

    // An array of test device IDs to allow.
    testDeviceIdentifiers: ["EMULATOR"],
  });
};

export const initializeAdMob = async () => {
  await configureAdMob();
  const adapterStatuses = await mobileAds().initialize();
  return adapterStatuses;
};

Usage

배너 광고(BannerAd)는 컴포넌트 형으로 단순하게 구현할 수 있으며, 이외 앱 오픈 광고(AppOpenAd), 전면 광고(InterstitialAd), 리워드 광고(RewardedAd), 보상형 전면 광고(RewardedInterstitialAd)는 컴포넌트 내에서 subsribe 형태로 구현하거나, hook을 사용해서 구현할 수 있다.

한 가지 유의할 점은, 개발을 진행할 때에는 실제 AdMob의 Ad Unit ID를 사용하기보다는 Test Ad ID를 사용해야 한다는 점이다. (Test ID를 사용하지 않는 경우, 정도에 따라 계정이 정지될 수도 있다고 한다.) 아래의 예제 코드에는 전부 TestIds를 넣어놨는데, 본인의 개발환경에 따라 TestIds 또는 실제 ID를 사용하도록 분기처리 하면 된다.

const adUnitId = __DEV__ ? TestIds.BANNER : 'ca-app-pub-xxxxxxxxxxxxx/yyyyyyyyyyyyyy';

BannerAd

import { View } from "react-native";
import { BannerAd, BannerAdSize, TestIds } from "react-native-google-mobile-ads";

const AdMobBanner = () => {
  return (
    <View>
      <BannerAd unitId={TestIds.BANNER} size={BannerAdSize.INLINE_ADAPTIVE_BANNER} />
    </View>
  );
};

RewardedAd

import { useEffect } from "react";
import { Pressable } from "react-native";
import { TestIds, useRewardedAd } from "react-native-google-mobile-ads";

const AdMobRewarded = () => {
  const { isEarnedReward, isLoaded, load, show } = useRewardedAd(TestIds.REWARDED, {
    serverSideVerificationOptions: { userId: "test_userId_1234", customData: JSON.stringify({ custom: "data" }) },
  });

  useEffect(() => {
    load();
  }, [load]);

  return (
    <Pressable disabled={!isLoaded} onPress={() => show()}>
      <Text>Show Interstitial Ad</Text>
    </Pressable>
  );
};

OR

import { useEffect, useState } from "react";
import { Pressable } from "react-native";
import { RewardedAd, RewardedAdEventType, TestIds } from "react-native-google-mobile-ads";

const rewarded = RewardedAd.createForAdRequest(TestIds.REWARDED, {
  requestNonPersonalizedAdsOnly: true,
  keywords: ['fashion', 'clothing'],
  serverSideVerificationOptions: { userId: "test_userId_1234", customData: JSON.stringify({ custom: "data" }) },
});

const AdMobRewarded = () => {
  const [isLoaded, setIsLoaded] = useState(false);
  
  useEffect(() => {
    const unsubscribeLoaded = rewarded.addAdEventListener(RewardedAdEventType.LOADED, () => {
      setIsLoaded(true);
    });
    const unsubscribeEarned = rewarded.addAdEventListener(
      RewardedAdEventType.EARNED_REWARD,
      reward => {
        console.log('User earned reward of ', reward);
      },
    );

    // Start loading the rewarded ad straight away
    rewarded.load();

    // Unsubscribe from events on unmount
    return () => {
      unsubscribeLoaded();
      unsubscribeEarned();
    };
  }, [load]);

  return (
    <Pressable disabled={!isLoaded} onPress={() => rewarded.show()}>
      <Text>Show Interstitial Ad</Text>
    </Pressable>
  );
};

네이티브 고급 광고(Native Ads)

배너 광고와 보상형 광고의 연동까지 확인해 봤는데, 한 가지 치명적인 단점이 있었다. 바로 해당 라이브러리에서는 네이티브 고급 광고(Native Ads)를 지원하지 않고 있다는 점이다. 공식 깃헙에서 관련 이슈를 찾아 보니, 아직 기능 구현 중에 있는 모양이다.

Native Ads를 구현한 다른 라이브러리(Docs)도 있긴 한데, 해당 라이브러리는 @react-native-firebase/admob이 있던 시절에 나온 라이브러리였고, 내 로컬에서 확인해 봤을 때에는 현재 사용중인 react-native-google-mobile-ads와 호환이 되지 않는 느낌이었다. (더 살펴봐야겠지만 두 라이브러리를 동시에 연동, 사용하려니 빌드가 되지 않았다ㅠㅠ)

위에 언급한 이슈 글을 보면 react-native-admob-native-ads 라이브러리의 개발자가 invertase 팀과 같이 개발하고 있는 것으로 보이는데, 마지막 코멘트가 2022년 4월 27일이라 기능 출시가 언제 될지는 미지수로 보인다. 😢

References

테스트 광고 사용 설정

https://docs.page/invertase/react-native-google-mobile-ads

https://support.google.com/admob/answer/7311747?hl=ko&ref_topic=7384409&sjid=5260966966642722958-AP

profile
기록하고 싶은 것을 기록하는 저장소

0개의 댓글