Android

[AdMob] 앱에 GDPR 메시지 구현하는 방법 및 구현과정에서의 히스토리 기록.

구글 애드몹 사이트에 로그인하면 상단에 EEA 및 영국 사용자에게 광고를 게재하는 개발자는 구글에서 인증한 동의관리 플랫폼(CMP)을 사용해서 GDPR 메시지 만들어야합니다. 단순하게 구글 애드몹사이트에서 설정으로 끝날 문제는 아니며, 소스 코드 상에서 구현을 해야합니다. 해당 정책 부터 자세히 살펴볼까요?

EEA 및 영국에서 광고를 게재하기 위한 새로운 Google 동의 관리 요건(게시자 대상)

올해(2023년) 안에 Google 애드센스, Ad Manager 또는 AdMob을 사용하는 게시자와 개발자는 유럽 경제 지역 또는 영국의 사용자에게 광고를 게재할 때 EU 사용자 동의 정책이 적용되며 Google에서 인증하고 IAB의 투명성 및 동의 프레임워크(TCF)와 통합된 동의 관리 플랫폼(CMP)을 사용해야 합니다.

다음 정보를 검토하여 새로운 요건과 변경 시기, 게시자가 준비할 수 있는 작업에 대해 알아보세요.

새로운 IAB TCF 요건

게시자는 유럽 경제 지역 또는 영국의 사용자에게 광고를 게재할 때 Google 인증 CMP를 이용 중인지 확인해야 합니다. Google 인증 CMP는 TCF 규정 준수에 중점을 둔 Google 인증 기준에 따라 Google에서 평가를 받습니다. TCF를 사용하는 게시자가 TCF에 등록되지 않은 광고 기술 제공업체와도 협력하는 경우, Google은 현재 추가 동의 사양을 통해 이를 지원하고 있으며 앞으로도 계속 그렇게 할 것입니다. Google에서는 CMP를 평가할 때 추가 동의 사양을 지원하는 CMP가 이를 올바르게 지원할 수 있는지 확인합니다.  검토 결과 CMP가 Google 인증 기준을 따르는 것으로 확인되면 해당 CMP는 Google 인증 CMP 목록에 표시됩니다. Google에서는 CMP가 TCF 또는 관련 개인 정보 보호법을 완전히 준수하는지 확인하지 않습니다.

올해 내: Google 애드센스, Ad Manager 또는 AdMob을 사용하는 게시자와 개발자는 유럽 경제 지역 또는 영국의 사용자에게 광고를 게재할 때 EU 사용자 동의 정책이 적용되며 Google에서 인증받고 IAB의 투명성 및 동의 프레임워크(TCF)와 통합된 동의 관리 플랫폼(CMP)을 사용해야 합니다.

  • Google의 개인 정보 보호 및 메시지 GDPR 사용자 동의 메시지를 사용하는 게시자: 게시자는 자신에게 가장 적합한 CMP 솔루션을 고려하는 것이 좋습니다. 게시자를 지원하기 위해 Ad Manager, 애드센스, AdMob 게시자가 개인 정보 보호 및 메시지 탭에서 사용할 수 있는 GDPR 사용자 동의 메시지는 새로운 TCF 요건에 따라 인증됩니다. 개인 정보 보호 및 메시지 GDPR 지원 및 TCF 통합에 관해 자세히 알아보세요.
    • 앱 게시자: Google에서는 위 기능 외에도 사용자 메시지 플랫폼(UMP) SDK를 제공합니다. 앱에 Google 사용자 메시지 플랫폼(UMP) SDK (Ad ManagerAdMob) 를 추가하고 앱용 GDPR 메시지를 만드는 방법을 자세히 알아보세요 (Ad ManagerAdMob). 

앱에 Google 사용자 메시징 플랫폼 SDK 추가하기

앱 사용자의 동의를 수집하려면 Google 사용자 메시징 플랫폼(UMP) SDK를 앱에 추가해야 합니다. 권장되는 개발 환경이 있습니다.

Google Developers 문서에 설명된 단계를 따르세요.

개인정보 보호 사용자 메시지 유형

1. GDPR 메시지

GDPR 메시지는 광고 게재를 목적으로 유럽 경제 지역(EEA) 및 영국(UK)의 대상 사용자로부터 개인 정보 보호법(GDPR)에 따른 동의를 수집하기 위해 표시됩니다.

개인 정보 보호법(GDPR)에 대한 정보

2. IDFA 메시지

IDFA 메시지는 Apple의 앱 추적 투명성(ATT) 가이드라인에 따라 IDFA를 사용하도록 선택해야 하는 iOS 사용자에게 표시됩니다. 

IDFA 및 ATT 정보

  • 영향을 받는 사용자: Apple 기기에 iOS 14+가 설치된 iOS 사용자
  • 설명: IDFA(Identifier for Advertisers)는 사용자의 휴대기기를 식별하는 Apple iOS 기능입니다. IDFA를 사용하려면 사용자가 명시적으로 권한을 부여해야 합니다. 앱에 AppTrackingTransparency 권한을 추가하면 IDFA와 같은 식별자 액세스와 사용을 허용해 달라고 사용자에게 요청하는 ATT 알림(‘iOS ATT 알림’을 줄인 말)이 추가됩니다. 개인 정보 보호 및 메시지를 사용하여 iOS ATT 알림 직전에 사용자에게 IDFA 메시지를 표시할 수 있습니다. IDFA 설명 메시지는 사용자들에게 보다 자세한 맥락을 제공하여 사용자의 데이터가 사용되는 용도를 이해할 수 있도록 도와줍니다.
  • 리소스:

첫번째 작업은 앱용 GDPR 메시지 만들기

앱에서 동의를 수집할 수 있도록 하려면 Google 사용자 메시징 플랫폼 SDK를 앱에 추가해야 합니다.

  1. https://apps.admob.com에서 AdMob 계정에 로그인합니다.
  2. 개인 정보 보호 및 메시지를 클릭합니다.
  3. GDPR을 클릭합니다.
  4. 메시지 만들기를 클릭합니다. ‘GDPR 메시지’ 페이지가 열립니다.
  5. 메시지를 표시할 앱을 선택합니다.
    1. 앱 선택을 클릭합니다.
    2. 원하는 앱을 선택합니다.
    3. 저장을 클릭합니다.
  6. 메시지를 표시할 언어를 선택합니다.
    1. 기본 언어: 메시지는 사용자의 기기 언어를 확인할 수 없거나 사용자의 기기 언어에서 선택한 ‘추가 언어’와 정확히 일치하지 않으면 기본 언어로 표시됩니다.
    2. 추가 언어: 메시지가 사용자의 기기 언어와 일치하는 ‘추가 언어’로 사용자에게 표시될 수 있습니다. 여기에서 선택한 언어와 앱에서 사용 가능한 언어가 일치해야 합니다. 각 ‘추가 언어’별로 메시지 텍스트를 수정할 수 있습니다.‘추가 언어’ 필드에서 ‘네덜란드어’를 선택하면 기기 언어를 네덜란드어로 설정한 사용자에게 네덜란드어로 작성된 GDPR 메시지가 표시됩니다.
  7. ‘사용자 동의 옵션’ 섹션에서 다음 옵션 중 하나를 선택합니다.
    • 동의 또는 관리 옵션: 이 메시지는 사용자에게 광고 파트너 및 광고 파트너의 목적에 동의하거나 동의 선택을 맞춤설정할 수 있는 선택권을 제공합니다.
    • 동의, 동의하지 않음 또는 관리 옵션: 이 메시지는 사용자에게 광고 파트너 및 광고 파트너의 목적에 동의하거나 동의하지 않음, 또는 동의 선택을 맞춤설정할 수 있는 선택권을 제공합니다.
  8. (선택사항) 닫기 (동의하지 않음) 체크박스를 선택하여 메시지에 닫기 아이콘을 추가합니다. 사용자는 닫기 아이콘을 클릭하여 메시지를 닫거나, 광고 파트너 및 그 목적에 대한 동의를 거부할 수 있습니다.
  9. ‘타겟팅’ 섹션에서 다음 옵션 중 하나를 선택합니다.
    • GDPR이 적용되는 국가(EEA 및 영국): EEA 및 영국의 앱 방문자에게 GDPR 메시지를 표시합니다.
    • 모든 위치: 모든 앱 방문자에게 GDPR 메시지를 표시합니다.
  10. 계속을 클릭합니다. ‘메시지 수정’ 페이지가 열립니다.
  11. 나중에 메시지를 구분하는 데 도움이 되도록 설명이 포함된 메시지 이름을 ‘메시지 이름’ 입력란에 입력합니다. 이름은 개인 정보 보호 및 메시지 페이지에만 표시되어 사용자는 볼 수 없습니다.
  12. (선택사항) 앱의 광고 소재 및 시각적 기준에 맞게 메시지를 수정하고 서식을 지정합니다.메시지가 둘 이상의 언어로 표시되는 경우, 선택한 모든 언어로 메시지를 검토한 다음 게시하도록 하세요.
  13. 개인정보처리방침 URL을 추가합니다.
  14. 저장을 클릭합니다.
  15. 준비가 되면 메시지를 게시합니다.

메시지 생성시 “동의하지 않음” 과 “닫기(동의하지 않음)” 이 두가지는 사용 안함으로 처리해야합니다.

그렇지 않으면 사용자가 두 가지중에 하나를 선택하는 경우 광고가 노출되지 않습니다.



GDPR 구현 작업 히스토리 (Google AdMob 가이드 참고 )

1.Gradle로 설치

dependencies {
    implementation 'com.google.android.gms:play-services-ads:22.1.0'
}

2. 매니페스트 업데이트

AndroidManifest.xml에 앱ID를 추가합니다.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.rewardedinterstitialexample">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">

        <meta-data
            android:name="com.google.android.gms.ads.APPLICATION_ID"
            android:value="ca-app-pub-xxxxxxxxxxxxxxxx~yyyyyyyyyy"/>
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

1번과 2번 작업의 경우 구글 애드몹 광고를 앱내에 송출하고 있다면 이미 적용되어 있을것입니다.

앱에 Google 사용자 메시징 플랫폼 SDK 추가

앱 사용자의 동의를 수집하려면 Google 사용자 메시징 플랫폼(UMP) SDK를 앱에 추가해야 합니다.

Google Developers 문서에 설명된 단계를 따르세요.



안드로이드 작업 방법

1. Gradle로 설치

모듈의 앱 수준 Gradle 파일(일반적으로 app/build.gradle)에 Google 사용자 메시지 플랫폼 SDK의 종속 항목을 추가 후 프로젝트를 Gradle 파일과 동기화합니다.

dependencies {
  implementation 'com.google.android.ump:user-messaging-platform:2.1.0'
}



2. 동의 정보 요청 코드 작성

앱을 실행할 때마다 requestConsentInfoUpdate()를 사용하여 사용자 동의 정보 업데이트를 요청해야 합니다. 이렇게 하면 사용자가 아직 동의하지 않은 경우 또는 동의가 만료된 경우 동의를 제공해야 하는지 여부가 결정됩니다.

다음은 onCreate() 메서드의 MainActivity에서 상태를 확인하는 방법의 예입니다.

경고: 앱의 캐시 또는 이전에 저장된 동의 문자열과 같은 다른 방법으로 동의 상태를 확인할 경우 동의 만료 시 TCF 3.3 오류가 발생할 수 있습니다.

package com.example.myapplication;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;

import com.google.android.ump.ConsentInformation;
import com.google.android.ump.ConsentRequestParameters;
import com.google.android.ump.FormError;
import com.google.android.ump.UserMessagingPlatform;

public class MainActivity extends AppCompatActivity {
  private ConsentInformation consentInformation;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    // Set tag for under age of consent. false means users are not under age
    // of consent.
    ConsentRequestParameters params = new ConsentRequestParameters
        .Builder()
        .setTagForUnderAgeOfConsent(false)
        .build();

    consentInformation = UserMessagingPlatform.getConsentInformation(this);
    consentInformation.requestConsentInfoUpdate(
        this,
        params,
        (OnConsentInfoUpdateSuccessListener) () -> {
          // TODO: Load and show the consent form.
        },
        (OnConsentInfoUpdateFailureListener) requestConsentError -> {
          // Consent gathering failed.
          Log.w(TAG, String.format("%s: %s",
              requestConsentError.getErrorCode(),
              requestConsentError.getMessage()));
        });
  }
}

3. 동의 양식 요청 코드 추가

최신 동의 상태를 받은 후ConsentForm 클래스의 loadAndShowConsentFormIfRequired() 를 호출하여 동의 양식을 로드합니다. 동의 상태가 필요한 경우 SDK에서 양식을 로드하여 제공된 activity에서 즉시 표시합니다. callback는 양식이 닫힌 후에 호출됩니다. 동의가 필요하지 않으면 callback가 즉시 호출됩니다.

public class MainActivity extends AppCompatActivity {
  private ConsentInformation consentInformation;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    // Set tag for under age of consent. false means users are not under age
    // of consent.
    ConsentRequestParameters params = new ConsentRequestParameters
        .Builder()
        .setTagForUnderAgeOfConsent(false)
        .build();

    consentInformation = UserMessagingPlatform.getConsentInformation(this);
    consentInformation.requestConsentInfoUpdate(
        this,
        params,
        (OnConsentInfoUpdateSuccessListener) () -> {
          UserMessagingPlatform.loadAndShowConsentFormIfRequired(
            this,
            (OnConsentFormDismissedListener) loadAndShowError -> {
              if (loadAndShowError != null) {
                // Consent gathering failed.
                Log.w(TAG, String.format("%s: %s",
                    loadAndShowError.getErrorCode(),
                    loadAndShowError.getMessage()));
              }

              // Consent has been gathered.
            }
          );
        },
        (OnConsentInfoUpdateFailureListener) requestConsentError -> {
          // Consent gathering failed.
          Log.w(TAG, String.format("%s: %s",
              requestConsentError.getErrorCode(),
              requestConsentError.getMessage()));
        });
  }
}

사용자가 결정을 내렸거나 양식을 닫은 후에 작업을 실행해야 하는 경우 이 로직을 양식의 callback에 배치합니다.

3. 광고 요청

앱에서 광고를 요청하기 전에 canRequestAds()를 사용하여 사용자의 동의를 얻었는지 확인해야합니다. 동의를 수집하는 동안 확인할 두 가지가 있습니다.

  1. 현재 세션에서 동의가 수집되면
  2. requestConsentInfoUpdate()를 호출한 직후 이전 세션에서 동의를 받았을 수도 있습니다. 지연 시간이 권장됩니다. 앱 실행 후 가능한 한 빨리 광고 로드를 시작할 수 있도록 콜백이 완료될 때까지 기다리지 않는 것이 좋습니다.

참고: canRequestAds() 는 다음을 호출할 때까지 항상 false을 반환합니다. requestConsentInfoUpdate()

public class MainActivity extends AppCompatActivity {
  private ConsentInformation consentInformation;
  // Use an atomic boolean to initialize the Google Mobile Ads SDK and load ads once.
  private final AtomicBoolean isMobileAdsInitializeCalled = new AtomicBoolean(false);

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    // Set tag for under age of consent. false means users are not under age
    // of consent.
    ConsentRequestParameters params = new ConsentRequestParameters
        .Builder()
        .setTagForUnderAgeOfConsent(false)
        .build();

    consentInformation = UserMessagingPlatform.getConsentInformation(this);
    consentInformation.requestConsentInfoUpdate(
        this,
        params,
        (OnConsentInfoUpdateSuccessListener) () -> {
          UserMessagingPlatform.loadAndShowConsentFormIfRequired(
            this,
            (OnConsentFormDismissedListener) loadAndShowError -> {
              if (loadAndShowError != null) {
                // Consent gathering failed.
                Log.w(TAG, String.format("%s: %s",
                    loadAndShowError.getErrorCode(),
                    loadAndShowError.getMessage()));
              }

              // Consent has been gathered.
              if (consentInformation.canRequestAds) {
                initializeMobileAdsSdk();
              }
            }
          )
        },
        (OnConsentInfoUpdateFailureListener) requestConsentError -> {
          // Consent gathering failed.
          Log.w(TAG, String.format("%s: %s",
              requestConsentError.getErrorCode(),
              requestConsentError.getMessage()));
        });

    // Check if you can initialize the Google Mobile Ads SDK in parallel
    // while checking for new consent information. Consent obtained in
    // the previous session can be used to request ads.
    if (consentInformation.canRequestAds()) {
      initializeMobileAdsSdk();
    }
  }

  private void initializeMobileAdsSdk() {
    if (isMobileAdsInitializeCalled.getAndSet(true)) {
      return;
    }

    // Initialize the Google Mobile Ads SDK.
    MobileAds.initialize(this);

    // TODO: Request an ad.
    // InterstitialAd.load(...);
  }
}

4. 테스트

테스트 결과 성공 스크린샷을 첨부합니다. 잘 뜹니다. 그럼 테스트 방법에 대해 알아볼까요?

프로그래매틱 방식으로 테스트 기기를 등록하여 테스트가 가능합니다.

테스트디바이스해시아이디값은 본인의 폰 값을 넣어주어야하며, 지역 강제설정 코드까지 추가해주어야 GDPR 동의 팝업을 확인할 수 있습니다.


Use new ConsentDebugSettings.Builder().addTestDeviceHashedId("33BE2250B43518CCDA7DE426D04EE231") to set this as a debug device.

테스트 기기 ID를 클립보드에 복사합니다.

ConsentDebugSettings.Builder().addTestDeviceHashedId() 를 호출하고 테스트 기기 ID 목록을 전달하도록 코드를 수정합니다.

ConsentDebugSettings debugSettings = new ConsentDebugSettings.Builder(this)
    .addTestDeviceHashedId("TEST-DEVICE-HASHED-ID")
    .build();

ConsentRequestParameters params = new ConsentRequestParameters
    .Builder()
    .setConsentDebugSettings(debugSettings)
    .build();

consentInformation = UserMessagingPlatform.getConsentInformation(this);
// Include the ConsentRequestParameters in your consent request.
consentInformation.requestConsentInfoUpdate(
    this,
    params,
    ...
);

지역 강제 설정

UMP SDK는 the setDebugGeography() method which takes a DebugGeography on ConsentDebugSettings.Builder를 사용하여 기기가 EEA 또는 영국에 있는 것처럼 앱 동작을 테스트할 수 있는 방법을 제공합니다. 디버그 설정은 테스트 기기에서만 작동합니다.

ConsentDebugSettings debugSettings = new ConsentDebugSettings.Builder(this)
    .setDebugGeography(ConsentDebugSettings.DebugGeography.DEBUG_GEOGRAPHY_EEA)
    .addTestDeviceHashedId("TEST-DEVICE-HASHED-ID")
    .build();

ConsentRequestParameters params = new ConsentRequestParameters
    .Builder()
    .setConsentDebugSettings(debugSettings)
    .build();

consentInformation = UserMessagingPlatform.getConsentInformation(this);
// Include the ConsentRequestParameters in your consent request.
consentInformation.requestConsentInfoUpdate(
    this,
    params,
    ...
);

UMP SDK로 앱을 테스트할 때 사용자의 첫 설치 경험을 시뮬레이션할 수 있도록 SDK 상태를 재설정하면 도움이 될 수 있습니다. SDK는 이를 위한 reset() 메서드를 제공합니다.

consentInformation.reset();

그러나 동의상태 재설정 코드를 추가하면 앱이 시작도 하기 전에 중지됩니다. 초기화 하고 싶은 경우 앱을 삭제하고 다시 빌드하면 됩니다.

만약 구현과정에서 오류가 발생한다면 다음 글도 참고해보세요.

GDPR 메시지 AdMob을 위해 Android에서 Google 사용자 메시징 플랫폼 SDK(UMP)를 구현하려고 하지만 작동하지 않음

코틀린으로 개발중이라면 아래 유튜브이 도움이 되시길 바랍니다.

[REFERENCE]

https://support.google.com/admob/answer/10113207

https://developers.google.com/admob/android/privacy?hl=ko

Leave a Reply

error: Content is protected !!