ios app 배포 준비 #애드몹 관련 주의사항
안드로이드 및 ios 패포를 위한 준비.
애드몹을 삽입한 경우 앱추적 관리를 위한 설정들이 필요했다.
테스트와 실제 배포를 위한 아이디 관리가 필요했다.
이 두가지가 가장 중요 포인트이다.
이 프로젝트는 구글 ai studio 에서 시작한 비개발자의 허접한 프로젝트라는 특징이 있다.
좀 복잡했다 여기까지 오기가.
일단 개발환경이 PWA > VITE (react) > Capacitor > Android (javaSDK) or Xcode (cocoapod)
대략 이런 흐름이었다. 다른건 별 문제 없었지만 애드몹 넣는 것 때문에 고생 좀 했다.
안드로이드 경우는 자바 버전과 캐팩시터 버전, 코틀린 버전, 애드몹 버전 등등의 충돌때문에 개고생.
애플 경우는 애드몹으로 인한 추적허용 추가, 유럽 버전 추적허용 추가 등등으로 리젝 되고, 개고생.
그냥 flutter + vscode + git copilot pro 이런 세팅이면 최고였을텐데,
물론 이것을 모두 경험하고 얻은 소중한 결과이긴 하다.
그래서 그 험난한 과정을 간략히 압축해서 정리하고자 했다.,
1. 애드몹 광고 아이디 관리
- 애드몹 사이트에서 각 플랫폼 별로 앱을 생성해야함.
1) 안드로이드용 앱
- 앱 아이디 : 테스트나 실제나 항상 사용한다 | capacitor.config 에 넣어주면 > androidManifest.xml 에 주입되는 방식
실제용 id : ca-app-pub-XXXX763379145766~XXXX..... - 광고단위 아이디 : 테스트 할때는 테스트 아이디를 사용한다 | adService.ts 에서 초기화하고 로드할 때 연결됨
테스트용 id : ca-app-pub-XXXX256099942544/XXXX..... // 공식 테스트용 id
실제용 id : ca-app-pub-XXXX0763379145766/XXXX..... // 발급받은 id
2) ios용 앱
- 앱 아이디 : 테스트나 실제나 항상 사용한다 | capacitor.config 에 넣어줘도 plist 에 자동 주입되지 않는다.
> info.plist 에 직접 넣어줘야 함
실제용 id : ca-app-pub-XXXX763379145766~XXXX..... - 광고단위 아이디 : 테스트 할때는 테스트 아이디를 사용한다 | adService.ts 에서 초기화하고 로드할 때 연결됨
테스트용 id : ca-app-pub-XXXX256099942544/XXXX..... // 공식 테스트용 id
실제용 id. : ca-app-pub-XXXX0763379145766/XXXX..... // 발급받은 id
3) .env 환경변수를 만들어 보안을 강화
위의 아이디는 코드에 직접 넣지 않고 변수로 만들어 사용, ai 를 사용하여 코딩할때 정보가 노출되는 것을 방지해야 함
! 이게 사실 엄청 중요한 것인데, IDE에서 ai 돌리면 다 긁어다가 정보를 캐가니까 유출 우려가 항상 있음
환경변수 사용헤도 아마 전역으로 모든 파일을 검토해서 코드를 생성해주기 때문에 사실상 노출된다고 봄
하지만 그래도 빌드나 배포시에는 조금이나마 불안함을 덜 수 있기에 최소한의 방법이라 생각함.
.env (example)
# Native AdMob App IDs (used by Capacitor config when packaging)
ADMOB_APP_ID_ANDROID=ca-app-pub-XXXX763379145766~XXXX.....
ADMOB_APP_ID_IOS=ca-app-pub-XXXX763379145766~XXXX.....
# Vite-exposed variables for ad unit IDs (frontend / runtime)
VITE_ADMOB_IOS_INTERSTITIAL_TEST=ca-app-pub-XXXX256099942544/XXXX.....
VITE_ADMOB_IOS_INTERSTITIAL_REAL=ca-app-pub-XXXX763379145766/XXXX.....
VITE_ADMOB_ANDROID_INTERSTITIAL_TEST=ca-app-pub-XXXX256099942544/XXXX.....
VITE_ADMOB_ANDROID_INTERSTITIAL_REAL=ca-app-pub-XXXX763379145766/XXXX.....
# Optional: force using real ads even in non-production builds
# Set to "true" to use real IDs (default는 false, production 빌드에서도 명시적으로 true로
# 설정하지 않으면 테스트 ID가 사용됩니다)
VITE_USE_REAL_ADS=false
nativeAdServie.ts
import { AdMob } from '@capacitor-community/admob';
import { Capacitor } from '@capacitor/core';
// NOTE:
// @capacitor-community/admob 패키지는 버전에 따라 Native Ads 타입/메서드가 TS 정의에 없을 수 있습니다.
// --- 전역 플래그 및 환경 변수 ---
// 1. 광고 단위 ID: Vite 환경변수에서 읽습니다. (빌드 시 `.env.*`에 설정)
// 변수명 예시:
// VITE_ADMOB_IOS_INTERSTITIAL_REAL, VITE_ADMOB_IOS_INTERSTITIAL_TEST
// VITE_ADMOB_ANDROID_INTERSTITIAL_REAL, VITE_ADMOB_ANDROID_INTERSTITIAL_TEST
// 기본 테스트 단위 ID (Google이 공식으로 제공하는 예시)
const FALLBACK_TEST_IDS = {
ios: 'ca-app-pub-XXXX56099942544/XXXX.....',
android: 'ca-app-pub-XXXX256099942544/XXXX.....'
};
const AD_IDS = {
ios: {
// Vite env가 없으면 개발 시에도 테스트 ID를 사용하도록
test: (import.meta.env.VITE_ADMOB_IOS_INTERSTITIAL_TEST as string) || FALLBACK_TEST_IDS.ios,
real: import.meta.env.VITE_ADMOB_IOS_INTERSTITIAL_REAL as string
},
android: {
test: (import.meta.env.VITE_ADMOB_ANDROID_INTERSTITIAL_TEST as string) || FALLBACK_TEST_IDS.android,
real: import.meta.env.VITE_ADMOB_ANDROID_INTERSTITIAL_REAL as string
}
};
// 빌드 시점의 VITE_USE_REAL_ADS 플래그로 실제/테스트 분기
// (기본값은 "false", PROD 환경에서도 명시적으로 true로 설정해야 실제 광고를 사용)
let IS_REAL = (import.meta.env.VITE_USE_REAL_ADS === 'true');
// 런타임에 전환하기 위한 헬퍼 함수
export const setUseRealAds = (value: boolean) => {
IS_REAL = value;
console.log(`[AdService] setUseRealAds -> ${IS_REAL}`);
};
// 환경 변수가 빠진 경우 빨리 감지하도록 간단한 검증
if (!AD_IDS.ios.test || !AD_IDS.android.test) {
console.warn("Ad unit IDs are missing for test mode; using fallback test IDs.");
}
if (!AD_IDS.ios.real || !AD_IDS.android.real) {
console.warn("Real ad unit IDs are missing; interstitials will fail until you set them.");
}
// 디버그용 로그: 어떤 ID가 선택되는지 확인
export const debugAdId = () => {
const platform = Capacitor.getPlatform();
const id = IS_REAL ? (platform === 'ios' ? AD_IDS.ios.real : AD_IDS.android.real)
: (platform === 'ios' ? AD_IDS.ios.test : AD_IDS.android.test);
console.log(`[AdService] using ${IS_REAL ? 'real' : 'test'} interstitial id:`, id);
};
export const getInterstitialAdId = () => {
const platform = Capacitor.getPlatform(); // 'ios' 또는 'android'
if (platform === 'ios') {
return IS_REAL ? AD_IDS.ios.real : AD_IDS.ios.test;
} else {
return IS_REAL ? AD_IDS.android.real : AD_IDS.android.test;
}
};
2. 빌드 시 자동 감지하도록 설정
위의 환경을 갖춰놓으면 각각의 아이디를 '테스트 / 실제 배포'로 나누어 빌드가 가능해짐
왜 이게 필요하냐, 애드몹을 테스트해보기 위해서 매우 필요하다.
실제 아이디를 사용하면 로딩하면서 경고가 뜨고, 광고를 폰에서 확인해볼 수가 없다
그럼 테스트할 땐 테스트 아이디 넣었다가 또 배포할 때 실제 아이디 넣고,
안드로이드 빌드할 땐 안드로이드 아이디 넣었다가, ios 빌드할 때 또 바꿔줘야 되고
이게 너무 비효율적이고, 여러번 수정하다보면 아이디가 꼬이기 마련이다.
해서 안드로이드 빌드 할 경우, ios빌드할 경우, 테스트용 광고 확인할 경우, 실제 광고 확인할 경우
이렇게 나누어 빌드를 자동으로 감지하도록 설정해놓는것이다.
- ios 빌드를 예로 들면 아래와 같은 상황으로 나뉨
테스트 빌드 시 : npm run build:ios:dev
배포용 빌드 시 : npm run build:ios:prod
이렇게 명령어를 분리하여 미리 설정해두어야한다. 다 사용할 일은 없긴 했다.
위처럼 각 플랫폼 별로 2종만 있으면 된다.
package.json
이걸 하려면 패키지 설치 필수
npm install dotenv
# prod 빌드라도 테스트 광고를 보려면
npm run build:ios:prod-test
npm run build:android:prod-test
# 혹은 그냥 개발 모드로 빌드
npm run build:ios:dev
npm run build:android:dev
"scripts": {
#web 빌드
"dev": "vite",
"build": "vite build",
"preview": "vite preview",
"build:web": "vite build",
#ios 빌드 ~ 싱크까지 한번에
"build:ios:dev": "vite build --mode ios-dev && npx cap copy ios && npx cap sync ios",
"build:ios:prod": "vite build --mode ios-prod && npx cap copy ios && npx cap sync ios",
#android 빌드 ~ 싱크까지 한번에
"build:android:dev": "vite build --mode android-dev && npx cap copy android && npx cap sync android",
"build:android:prod": "vite build --mode android-prod && npx cap copy android && npx cap sync android",
#ios 카피+싱크
"sync:ios": "npx cap copy ios && npx cap sync ios",
#android 카피+싱크 / 빌드+싱크 / 빌드+런
"sync:android": "npx cap copy android && npx cap sync android",
"cap:sync": "npm run build && npx cap sync android",
"cap:run": "npm run build && npx cap run android"
},
3. info.plist 키 생성 (ios 경우)
확실히 애플이 좀 더 복잡하긴 하다. 까다롭고 그렇다.
1) SKAdNetworkItems 생성하고 50개 구글 키를 넣어줘야 함.
https://developers.google.com/admob/ios/privacy/strategies?hl=ko#skadnetwork
개인 정보 보호 전략 | iOS | Google for Developers
iOS용 Google 모바일 광고 SDK를 사용하여 규정을 준수하는 개인 정보 보호 전략을 구현합니다.
developers.google.com
2) GADApplicationIdentifier 생성하고 애드몹 앱 아이디 넣어줘야 함.
https://developers.google.com/admob/ios/quick-start?hl=ko
Google 모바일 광고 SDK 설정 | iOS | Google for Developers
기본 요건 및 광고 유형을 비롯하여 iOS용 Google 모바일 광고 SDK를 시작합니다.
developers.google.com
3) Privacy - Tracking Usage Description 생성하고 ''앱 추적 동의 화면 팝업 문구"를 넣어줘야 함.
- 위 참조
최종적인 info.plist 확인

4. 내 디바이스를 테스트 기기로 등록
일단 최종적으로 앱 개발자 센터에 올리고 승인이 나서 실제 퍼브리싱이 되기 전까지
내 기기는 테스트 기기로 등록되어있는 것이 안전하다
애드몹 사이트에 내 기기를 테스트 기기로 등록하기 위해서, 기기의 광고 아이디 ID(ADID/IDFA) 를 알아야 한다.
핸드폰의 설정에 들어가 구글 세팅에 들어가 어디로 어디로 들어가면 아주 깨알만한 글씨로 써진 것을 찾을 수는 있다.
하지만 이건 빌드할 때마다 시시각각 변한다. 그래서 콘솔 로그에 남기도록 해주면 편하다
아래와 같이 한 줄 넣어주면 끝 (단, 위의 내용 모두 적용한 후에 됨)
Appdelegate.swift
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
print("IDFV: \(UIDevice.current.identifierForVendor?.uuidString ?? "N/A")") // 이부분을 삽입
return true
}
Xcode / run 실행 후 콘솔 로그 확인
초반 부근에 "IDFV : ---" 이렇게 찍힌 아이디가 보일 것임. 그것이 바로 내 기기의 광고아이디임.

애드몹 사이트에서 '설정 / 기기테스트/ 기기추가' 할때 내 기기 광고아이디를 넣어주면 됨

5. 테스트 광고 확인 및 실제 광고 아이디로 빌드
이제 테스트 빌드를 하고, 광고를 확인한다.
npm run build:ios:dev
실행한 앱 로그에 에러가 없고, 화면에 테스트 광고가 잘 나오면 성공이다.
이제 실제 빌드를 한다.
npm run build:ios:prod
실제 빌드를 하면, 아래와 같이 로그 마지막에 광고 에러가 뜬다.
이것은 실제 광고 아이디를 연결했는데, 애드몹에서 광로를 뿌려줄 수 없기 때문에
즉 아직 승인이 난 앱이 아니기 때문에 광고를 뿌려주지 못해서 생긴 에러이므로 무시하고 진행하면 된다.
추적권한 상태 잘 돌아가고 있음 확인
실제 광고 아이디를 사용하고 있음 확인

광고 로딩 실패 로그 (무시해도 됨)

이제 실제 광고 아이디를 이용해 빌드하여 테스트를 마침
이 상태 그대로 배포하면 됨.
BR.h