들어가기에 앞서
하단의 참고한 자료를 바탕으로 비전문가가 정리한 글이므로 오류가 있을 수 있습니다.
오류에 대한 피드백은 언제든지 환영합니다. 부디 댓글로 알려주시길 바랍니다. 감사합니다.
expo 프로젝트에 admob 추가하기
시작하기에 앞서
이 글은 production이 아닌 development 환경을 기준으로 admob 추가 방법을 소개하는 글입니다. 앱 스토어에 등록된 앱에 admob을 추가하시려면 Google AdMob에서 계정을 생성하고 앱을 추가하셔야 합니다.
또한, admob 관련 패키지인 react-native-google-mobile-ads 는 Expo Go와 호환이 되지 않으므로, expo run:android, expo run:ios로 로컬 빌드하여서 테스트 하셔야 합니다.
마지막으로, Google AdMob에서 발급 받은 키들은 모두 환경 변수로 관리하셔서 외부에 노출되는 일이 없도록 하셔야 합니다. 이 글에서 나온 키들은 오직 테스트용으로써 화면에 보이게 하는 용도일 뿐, 실제 production 레벨에서는 사용하시면 안 됩니다.
admob App ID 추가하기
먼저, admob을 expo 프로젝트에 적용하려면 app.config.js(ts) 또는 app.json에 아래와 같은 형식으로 추가하셔야 합니다. 즉, expo 설정의 외부에 "react-native-google-mobile-ads" 키를 따로 지정하고 값을 설정하셔야 합니다.
{
"expo": ...
"react-native-google-mobile-ads": {
"android_app_id": "ca-app-pub-3940256099942544~3347511713",
"ios_app_id": "ca-app-pub-3940256099942544~3347511713",
}
}
Plain Text
복사
하지만 저는 app.config.ts에 react-native-google-mobile-ads 키를 추가하려고 보니 계속 적용이 안 되어서 관련 자료를 찾아보니 expo가 자동으로 app.config.ts와 app.json 설정을 통합하여 적용한다고 합니다.
그래서, app.json을 생성하고 하단과 같이 react-native-google-mobile-ads 키를 추가하였더니 제대로 적용이 되었습니다.
관련 패키지 설치 및 초기화 하기
이제 하단의 명령어를 통해 관련 라이브러리를 설치해주세요.
npm install react-native-google-mobile-ads
npx expo install expo-device
Shell
복사
그런 다음, App.tsx 혹은 _layout.tsx 같은 처음으로 로드되는 컴포넌트에 하단의 코드를 넣어주세요.
저는 zustand를 이용하여 사용자의 광고 추적 허용에 대한 상태를 전역적으로 저장하였습니다.
// Zustand 상태 관리 라이브러리를 사용하여 글로벌 상태에서 setTrackingGranted 함수와 trackingGranted 값을 가져옴
const setTrackingDenied = useStore(state => state.setTrackingDenied)
const trackingDenied = useStore(state => state.trackingDenied)
useEffect(() => {
;(async () => {
// requestTrackingPermissionsAsync : 사용자 또는 기기를 추적하는 데 사용할 수 있는
// 앱 관련 데이터에 대한 액세스를 승인하거나 거부하도록 사용자에게 요청하는 함수
const { status: trackingStatus } = await requestTrackingPermissionsAsync()
// 사용자의 액세스 승인 여부를 trackingDenied에 저장
setTrackingDenied(trackingStatus === 'denied')
await mobileAds().initialize()
})()
}, [trackingDenied])
TypeScript
복사
// zustandStore.ts
import { create } from 'zustand'
interface State {
trackingDenied: boolean
setTrackingDenied: (trackingDenied: boolean) => void
}
export const useStore = create<State>()(set => ({
trackingDenied: false,
setTrackingDenied: trackingDenied => set({ trackingDenied }),
}))
TypeScript
복사
참고로, 위 App.tsx에서 사용된 requestTrackingPermissionsAsync 함수의 반환 값 중 status 객체는 3가지의 상태를 가집니다. 저는 그 중 “denied” 상태를 이용하여 사용자 데이터 액세스 승인 상태 값을 저장하였습니다.
출처: expo 공식 문서
광고 배너 컴포넌트 작성 및 적용하기
이제 광고 배너 컴포넌트를 작성할 차례입니다. 광고 배너에 사용되는 id는 OS에 따라 다릅니다. 각각의 값을 .env등에 저장하여서 사용하셔야 합니다. 또한, 아래처럼 개발 환경(__DEV__)이라면 테스트ID를, 프로덕션 환경이라면 프로덕션ID를 넣으시면 좋습니다.
// InlinAd.tsx
import { View } from 'react-native'
import * as Device from 'expo-device'
import React, { useEffect, useState } from 'react'
import { BannerAd, BannerAdSize, TestIds } from 'react-native-google-mobile-ads'
import { useStore } from '@_components/common/utils/zustandStore'
const iosAdmobBanner = 'google admob에서 할당 받은 androidID'
const androidAdmobBanner = 'google admob에서 할당 받은 iosID'
const productionID =
Device.osName === 'Android' ? androidAdmobBanner : iosAdmobBanner
const InlineAd = () => {
const [isAdLoaded, setIsAdLoaded] = useState<boolean>(false)
const isTrackingDenied = useStore(state => state.trackingDenied)
useEffect(() => {}, [isTrackingDenied])
return (
<View style={{ height: isAdLoaded ? 'auto' : 0 }}>
<BannerAd
// 반드시 개발 환경에서는 테스트 광고 ID를 사용하고 프로덕션 환경에서는 실제 광고 ID를 사용해야 합니다.
unitId={__DEV__ ? TestIds.BANNER : productionID}
size={BannerAdSize.ANCHORED_ADAPTIVE_BANNER}
requestOptions={{
// App.tsx에서 업데이트한 trackingDenied 값에 따라 사용자화된 광고 제공여부 정함
requestNonPersonalizedAdsOnly: isTrackingDenied,
}}
onAdLoaded={() => {
setIsAdLoaded(true)
}}
/>
</View>
)
}
export default InlineAd
TypeScript
복사
또한, 앞서 App.tsx 에서 mobileAds().initialize()를 통해 admob을 초기화하고 사용자의 데이터 액세스 승인 여부 값을 zustand의 함수(setTrackingDenied())를 통해 저장했습니다. 이로 인해 만약 사용자가 추적 허용을 거부했다면, 사용자화된 광고가 출력되지 않고 일반적인 광고가 출력됩니다.
확인하기
이제 InlinedAd 컴포넌트를 원하는 곳에 넣어서 잘 출력되는지 확인해주세요. 아래와 같이 같이 Test mode로 나오면 성공하신겁니다. 참고로, 저는 탭 네비게이터에 삽입하였습니다.
Trouble Shooting
다음은 제가 Admob을 도입하던 중 만난 에러와 그에 대한 해결 방법입니다.
ManifestMerger2$MergeFailureException
AndroidManifest.xml 파일에서 manifest에 xmlns:tools="http://schemas.android.com/tools"
태그를 추가하여 해결했습니다.
transformDexArchiveWithExternalLibsDexMergerForDebug'
android/app/build.gradle에서 하단의 이미지와 같이 muiltDexEnabled true 를 추가해주세요.
SDK location not found. Define location with sdk.dir in the local.properties file or with an ANDROID_HOME environment variable
해당 문제는 local build시 발생하였는데, 에러 메시지에 나와있는데로 local.properties에 sdk.dir 경로를 설정하지 않아 발생되는 문제입니다.
android 폴더에 local.properties 파일을 생성하고 다음과 같이 작성해 주세요.
Window
sdk.dir=C\:\\Users\\USERNAME\\AppData\\Local\\Android\\sdk
Shell
복사
Mac
sdk.dir = /Users/USERNAME/Library/Android/sdk
Shell
복사
Linux(Ubuntu)
sdk.dir = /home/USERNAME/Android/Sdk
Shell
복사