플러팅 AI/배포

애플 앱 심사 반려: ATT 거부 시 맞춤형 광고 제공 문제 해결 방법 🚀

Solo.dev 2025. 1. 21. 13:15
애플 앱 심사에서 ATT(앱 추적 투명성, App Tracking Transparency) 관련 반려를 받았다면, ATT 거부 시 맞춤형 광고(Personalized Ads)를 제공하지 않도록 설정해야 합니다.

이 문제를 해결하려면 ATT 상태를 전역적으로 관리하고, 이를 광고 제공 컴포넌트(AdProvider)에서 반영하는 방식으로 수정해야 합니다.


📌 문제점: ATT 거부 시 맞춤형 광고 제공

1️⃣ ATT 관련 애플 심사 가이드라인 위반

  • 애플은 사용자가 ATT를 거부했을 때 다시 동의를 요청하면 안 된다고 명확히 규정하고 있음.
  • 하지만 현재 코드는 사용자가 ATT를 거부해도 Alert로 재요청을 하거나 광고 제공 방식을 변경하지 않음.

2️⃣ ATT 거부 시 개인화 광고(PA) 제공 문제

  • ATT를 거부한 경우, 구글 애드몹에서 개인화 광고(PA)를 제공하면 안 됨.
  • 하지만 현재 광고 제공 컴포넌트(AdProvider.js)는 ATT 상태를 반영하지 않고 광고 요청을 실행하고 있음.
  • 이로 인해 ATT 거부 후에도 맞춤형 광고가 제공되는 문제가 발생.

🔹 해결 방법: ATT 상태를 전역 상태로 관리하고, 광고 요청 시 반영하기

ATT 상태를 TrackingPermissionContext에서 전역으로 관리
AdProvider.js에서 requestNonPersonalizedAdsOnly를 ATT 상태에 따라 설정
ATT 거부 시 자동으로 비개인화 광고(NPA, Non-Personalized Ads)를 요청


🚀 1. TrackingPermissionContext.js (ATT 상태 전역 관리)

✅ ATT 상태를 앱 전체에서 사용할 수 있도록 설정


import React, { createContext, useState, useEffect, useContext } from 'react';
import { Platform } from 'react-native';
import { requestTrackingPermission } from 'react-native-tracking-transparency';

const TrackingPermissionContext = createContext();

export const TrackingPermissionProvider = ({ children }) => {
const [isTrackingAllowed, setIsTrackingAllowed] = useState(null);

useEffect(() => {
const checkTrackingPermission = async () => {
if (Platform.OS === 'ios') {
const status = await requestTrackingPermission();
setIsTrackingAllowed(status === 'authorized'); // ✅ ATT 승인 여부 저장
console.log(`[TrackingPermission] ATT 상태: ${status}`);
} else {
setIsTrackingAllowed(true); // ✅ Android는 자동 허용
}
};

checkTrackingPermission();
}, []);

return (
<TrackingPermissionContext.Provider value={{ isTrackingAllowed }}>
{children}
</TrackingPermissionContext.Provider>
);
};

export const useTrackingPermission = () => useContext(TrackingPermissionContext);

isTrackingAllowed 값이 true이면 맞춤형 광고(PA) 제공 가능
false이면 비개인화 광고(NPA) 제공하도록 광고 설정 변경 필요
이제 AdProvider.js에서 useTrackingPermission()을 사용하여 ATT 상태를 반영 가능


🚀 2. AdProvider.js (ATT 상태 반영하여 광고 요청)

✅ ATT 상태에 따라 맞춤형 광고 vs 비개인화 광고 제공

import React, { createContext, useState, useEffect, useContext, useRef } from 'react';
import AsyncStorage from '@react-native-async-storage/async-storage';
import { RewardedAd, RewardedAdEventType, TestIds } from 'react-native-google-mobile-ads';
import { Platform } from 'react-native';
import { useTrackingPermission } from '../services/TrackingPermissionContext'; // 🚀 ATT 상태 가져오기

const adUnitId = Platform.select({
ios: "ca-app-pub-8662733550474556/1064615361",
});

const AdContext = createContext();

export const AdProvider = ({ children }) => {
const [isAdLoaded, setIsAdLoaded] = useState(false);
const rewardedAdRef = useRef(null);
const { isTrackingAllowed } = useTrackingPermission(); // 🚀 ATT 상태 가져오기

const loadAd = async () => {
try {
if (isTrackingAllowed === null) {
console.log('[AdProvider] ATT 상태 확인 중... 광고 로드 보류');
return;
}

const requestOptions = {
requestNonPersonalizedAdsOnly: !isTrackingAllowed, // ✅ ATT 거부 시 비개인화 광고 요청
};

rewardedAdRef.current = RewardedAd.createForAdRequest(adUnitId, requestOptions);
console.log(`[AdProvider] 광고 요청 옵션: ${JSON.stringify(requestOptions)}`);

rewardedAdRef.current.addAdEventListener(RewardedAdEventType.LOADED, () => {
setIsAdLoaded(true);
console.log('[AdProvider] 광고 이벤트: 로드 완료');
});

rewardedAdRef.current.onAdDismissedFullScreenContent = () => {
console.log('[AdProvider] 광고 닫힘 → 새로운 광고 로드');
setIsAdLoaded(false);
loadAd(); // 새로운 광고 로드
};

await rewardedAdRef.current.load();
console.log('[AdProvider] 광고 로드 완료');
} catch (error) {
console.error('[AdProvider] 광고 로드 실패:', error);
setIsAdLoaded(false);
}
};

useEffect(() => {
if (isTrackingAllowed !== null) {
loadAd();
}
}, [isTrackingAllowed]);

return (
<AdContext.Provider value={{ isAdLoaded }}>
{children}
</AdContext.Provider>
);
};

export const useAd = () => useContext(AdContext);

🚀 3. App.js에서 TrackingPermissionProvider 적용하기

App.js에서 TrackingPermissionProvider를 감싸서 모든 컴포넌트가 ATT 상태를 공유할 수 있도록 설정해야 함.



import React from 'react';
import { NavigationContainer } from '@react-navigation/native';
import { TrackingPermissionProvider } from './services/TrackingPermissionContext'; // 🚀 추가
import { AdProvider } from './services/AdProvider';

export default function App() {
return (
<TrackingPermissionProvider>
<AdProvider>
<NavigationContainer>
{/* 앱 내 라우팅 구조 */}
</NavigationContainer>
</AdProvider>
</TrackingPermissionProvider>
);
}

📌 최종 정리

✔️ ATT 거부 시 맞춤형 광고 제공을 막는 방식

1️⃣ TrackingPermissionContext에서 ATT 상태를 전역적으로 관리
2️⃣ AdProvider에서 requestNonPersonalizedAdsOnly 옵션을 ATT 상태에 따라 설정

  • ATT 승인(true) → 맞춤형 광고(Personalized Ads) 제공
  • ATT 거부(false) → 비개인화 광고(Non-Personalized Ads) 제공
    3️⃣ 앱 전체에서 ATT 상태를 공유하도록 App.js에서 TrackingPermissionProvider 적용

이제 애플 정책을 완벽하게 준수하면서도 광고가 정상적으로 동작! 🚀
ATT 거부 시 개인화 광고를 제공하지 않도록 완벽히 차단 가능! 💡
심사 재반려 없이 문제 해결 완료! 🎯