시작하기

Google EU 사용자 동의 정책에 따라 영국과 함께 유럽 경제 지역 (EEA)의 사용자에게 특정 정보를 공개하고, 법적으로 필요한 경우 쿠키 또는 기타 로컬 저장소를 사용하고 개인 정보 (예: AdID)를 사용하여 광고를 게재한다는 것에 대한 사용자의 동의를 얻어야 합니다. 이 정책에는 EU 온라인 개인 정보 보호 지침 및 개인 정보 보호법 (GDPR)의 요구사항이 반영되어 있습니다.

게시자가 이 정책에 따른 의무사항을 준수하도록 지원하기 위해 Google에서는 사용자 메시지 플랫폼 (UMP) SDK를 제공합니다. UMP SDK는 최신 IAB 표준을 지원하도록 업데이트되었습니다. 이제 개인 정보 보호 및 메시지에서 AdMob 이러한 모든 구성을 편리하게 처리할 수 있습니다.

기본 요건

메시지 유형 만들기

AdMob 계정의 개인 정보 보호 및 메시지 탭에서 사용 가능한 사용자 메시지 유형 중 하나로 사용자 메시지를 만듭니다. UMP SDK는 프로젝트에 설정된 AdMob 애플리케이션 ID에서 생성된 사용자 메시지를 표시하려고 시도합니다. 애플리케이션에 구성된 메시지가 없으면 SDK가 오류를 반환합니다.

자세한 내용은 개인 정보 보호 및 메시지에 대한 정보를 참고하세요.

SDK 가져오기

CocoaPods (권장)

SDK를 iOS 프로젝트로 가져오는 가장 쉬운 방법은 CocoaPods를 사용하는 것입니다. 프로젝트의 Podfile을 열고 다음 행을 앱의 타겟에 추가하세요.

pod 'GoogleUserMessagingPlatform'

그런 후 다음 명령어를 실행하세요.

pod install --repo-update

CocoaPods를 처음 사용하는 경우에는 CocoaPods 사용에서 Podfile을 만들고 사용하는 방법을 참고하세요.

Swift Package Manager

UMP SDK는 Swift Package Manager도 지원합니다. Swift 패키지를 가져오려면 다음 단계를 따르세요.

  1. Xcode에서 File(파일) > Add Packages(패키지 추가)...로 이동하여 UMP SDK Swift 패키지를 설치합니다.

  2. 표시되는 프롬프트에서 UMP SDK Swift 패키지 GitHub 저장소를 검색합니다.

    https://github.com/googleads/swift-package-manager-google-user-messaging-platform.git
    
  3. 사용할 UMP SDK Swift 패키지의 버전을 선택합니다. 새 프로젝트의 경우 Up to Next Major Version(최대 다음 메이저 버전)을 사용하는 것이 좋습니다.

그러면 Xcode가 패키지 종속 항목을 확인하고 백그라운드에서 다운로드합니다. 패키지 종속 항목을 추가하는 방법에 관한 자세한 내용은 Apple 도움말을 참고하세요.

수동 다운로드

SDK를 가져오는 다른 방법은 수동으로 다운로드하는 것입니다.

SDK 다운로드

그런 다음 프레임워크를 Xcode 프로젝트로 드래그하여 Copy items if needed(필요한 경우 항목 복사)를 선택합니다.

그런 다음, 다음을 사용하여 필요한 모든 파일에 프레임워크를 포함할 수 있습니다.

Swift

import UserMessagingPlatform

Objective-C

#include <UserMessagingPlatform/UserMessagingPlatform.h>

앱을 실행할 때마다 requestConsentInfoUpdateWithParameters:completionHandler:를 사용하여 사용자 동의 정보 업데이트를 요청해야 합니다. 이를 통해 사용자가 아직 동의를 제공하지 않았는지 또는 동의가 만료되었는지 여부를 판단합니다.

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

Swift

override func viewDidLoad() {
  super.viewDidLoad()

  // Request an update for the consent information.
  UMPConsentInformation.sharedInstance.requestConsentInfoUpdate(with: nil) {
    [weak self] requestConsentError in
    guard let self else { return }

    if let consentError = requestConsentError {
      // Consent gathering failed.
      return print("Error: \(consentError.localizedDescription)")
    }

    // TODO: Load and present the consent form.
  }
}

Objective-C

- (void)viewDidLoad {
  [super viewDidLoad];

  // Request an update for the consent information.
  [UMPConsentInformation.sharedInstance
      requestConsentInfoUpdateWithParameters:nil
          completionHandler:^(NSError *_Nullable requestConsentError) {
            if (requestConsentError) {
              // Consent gathering failed.
              NSLog(@"Error: %@", requestConsentError.localizedDescription);
              return;
            }

            // TODO: Load and present the consent form.
          }];
}

필요한 경우 동의 양식 로드 및 표시

중요: 다음 API는 UMP SDK 버전 2.1.0 이상과 호환됩니다.

최신 동의 상태를 수신했으면 UMPConsentForm 클래스에서 loadAndPresentIfRequiredFromViewController:completionHandler: 를 호출하여 동의 양식을 로드하세요. 동의 상태가 필요한 경우 SDK는 양식을 로드한 후 제공된 view controller에서 양식을 즉시 표시합니다. 양식을 닫으면 completion handler 가 호출됩니다. 동의가 필요하지 않으면 completion handler 가 즉시 호출됩니다.

Swift

override func viewDidLoad() {
  super.viewDidLoad()

  // Request an update for the consent information.
  UMPConsentInformation.sharedInstance.requestConsentInfoUpdate(with: nil) {
    [weak self] requestConsentError in
    guard let self else { return }

    if let consentError = requestConsentError {
      // Consent gathering failed.
      return print("Error: \(consentError.localizedDescription)")
    }

    UMPConsentForm.loadAndPresentIfRequired(from: self) {
      [weak self] loadAndPresentError in
      guard let self else { return }

      if let consentError = loadAndPresentError {
        // Consent gathering failed.
        return print("Error: \(consentError.localizedDescription)")
      }

      // Consent has been gathered.
    }
  }
}

Objective-C

- (void)viewDidLoad {
  [super viewDidLoad];

  __weak __typeof__(self) weakSelf = self;
  // Request an update for the consent information.
  [UMPConsentInformation.sharedInstance
      requestConsentInfoUpdateWithParameters:nil
          completionHandler:^(NSError *_Nullable requestConsentError) {
            if (requestConsentError) {
              // Consent gathering failed.
              NSLog(@"Error: %@", requestConsentError.localizedDescription);
              return;
            }

            __strong __typeof__(self) strongSelf = weakSelf;
            if (!strongSelf) {
              return;
            }

            [UMPConsentForm loadAndPresentIfRequiredFromViewController:strongSelf
                completionHandler:^(NSError *loadAndPresentError) {
                  if (loadAndPresentError) {
                    // Consent gathering failed.
                    NSLog(@"Error: %@", loadAndPresentError.localizedDescription);
                    return;
                  }

                  // Consent has been gathered.
                }];
          }];
}

사용자가 선택을 하거나 양식을 닫은 후에 작업을 실행해야 하는 경우 이 로직을 양식의 completion handler에 배치합니다.

광고 요청

앱에서 광고를 요청하기 전에 UMPConsentInformation.sharedInstance.canRequestAds를 사용하여 사용자의 동의를 얻었는지 확인하세요. 동의를 수집할 때 다음 두 곳에서 확인할 수 있습니다.

  1. 현재 세션에서 동의를 수집한 후
  2. requestConsentInfoUpdateWithParameters:completionHandler:를 호출한 직후 이전 세션에서 동의를 받았을 수 있습니다. 지연 시간 권장사항에 따라 앱 실행 후 최대한 빨리 광고 로드를 시작할 수 있도록 콜백이 완료될 때까지 기다리지 않는 것이 좋습니다.

동의 수집 프로세스 중에 오류가 발생해도 광고를 요청해야 합니다. UMP SDK는 이전 세션의 동의 상태를 사용합니다.

Swift

class ViewController: UIViewController {

  // Use a boolean to initialize the Google Mobile Ads SDK and load ads once.
  private var isMobileAdsStartCalled = false

  override func viewDidLoad() {
    super.viewDidLoad()

    // Request an update for the consent information.
    UMPConsentInformation.sharedInstance.requestConsentInfoUpdate(with: nil) {
      [weak self] requestConsentError in
      guard let self else { return }

      if let consentError = requestConsentError {
        // Consent gathering failed.
        return print("Error: \(consentError.localizedDescription)")
      }

      UMPConsentForm.loadAndPresentIfRequired(from: self) {
        [weak self] loadAndPresentError in
        guard let self else { return }

        if let consentError = loadAndPresentError {
          // Consent gathering failed.
          return print("Error: \(consentError.localizedDescription)")
        }

        // Consent has been gathered.
        if UMPConsentInformation.sharedInstance.canRequestAds {
          self.startGoogleMobileAdsSDK()
        }
      }
    }
    
    // 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 UMPConsentInformation.sharedInstance.canRequestAds {
      startGoogleMobileAdsSDK()
    }
  }
  
  private func startGoogleMobileAdsSDK() {
    DispatchQueue.main.async {
      guard !self.isMobileAdsStartCalled else { return }

      self.isMobileAdsStartCalled = true

      // Initialize the Google Mobile Ads SDK.
      GADMobileAds.sharedInstance().start()

      // TODO: Request an ad.
      // GADInterstitialAd.load(...)
    }
  }
}

Objective-C

@implementation ViewController

- (void)viewDidLoad {
  [super viewDidLoad];

  __weak __typeof__(self) weakSelf = self;
  // Request an update for the consent information.
  [UMPConsentInformation.sharedInstance
      requestConsentInfoUpdateWithParameters:nil
          completionHandler:^(NSError *_Nullable requestConsentError) {
            if (requestConsentError) {
              // Consent gathering failed.
              NSLog(@"Error: %@", requestConsentError.localizedDescription);
              return;
            }
            __strong __typeof__(self) strongSelf = weakSelf;
            if (!strongSelf) {
              return;
            }

            [UMPConsentForm loadAndPresentIfRequiredFromViewController:strongSelf
                completionHandler:^(NSError *loadAndPresentError) {
                  if (loadAndPresentError) {
                    // Consent gathering failed.
                    NSLog(@"Error: %@", loadAndPresentError.localizedDescription);
                    return;
                  }

                  // Consent has been gathered.
                  __strong __typeof__(self) strongSelf = weakSelf;
                  if (!strongSelf) {
                    return;
                  }

                  if (UMPConsentInformation.sharedInstance.canRequestAds) {
                    [strongSelf startGoogleMobileAdsSDK];
                  }
                }];
          }];

  // 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 (UMPConsentInformation.sharedInstance.canRequestAds) {
    [self startGoogleMobileAdsSDK];
  }
}

- (void)startGoogleMobileAdsSDK {
  static dispatch_once_t onceToken;
  dispatch_once(&onceToken, ^{
    // Initialize the Google Mobile Ads SDK.
    [GADMobileAds.sharedInstance startWithCompletionHandler:nil];

    // TODO: Request an ad.
    // [GADInterstitialAd loadWithAdUnitID...];
  });
}

공개 설정 옵션

일부 동의 양식의 경우 사용자가 언제든지 동의를 수정해야 합니다. 필요한 경우 다음 단계를 따라 개인 정보 보호 옵션 버튼을 구현합니다.

이 경우 방법은 다음과 같습니다.

  1. 개인 정보 보호 옵션 양식을 트리거할 수 있는 UI 요소(예: 앱의 설정 페이지에 있는 버튼)를 구현합니다.
  2. loadAndPresentIfRequiredFromViewController:completionHandler: 가 완료되면privacyOptionsRequirementStatus 를 확인하여 개인 정보 보호 옵션 양식을 표시할 수 있는 UI 요소를 표시할지 결정합니다.
  3. 사용자가 UI 요소와 상호작용하면presentPrivacyOptionsFormFromViewController:completionHandler: 를 호출하여 양식을 표시합니다. 그러면 사용자가 언제든지 개인 정보 보호 옵션을 업데이트할 수 있습니다.

다음 예는 UIBarButtonItem에서 개인 정보 보호 옵션 양식을 표시하는 방법을 보여줍니다.

Swift

@IBOutlet weak var privacySettingsButton: UIBarButtonItem!

var isPrivacyOptionsRequired: Bool {
  return UMPConsentInformation.sharedInstance.privacyOptionsRequirementStatus == .required
}

override func viewDidLoad() {
  // ...

  // Request an update for the consent information.
  UMPConsentInformation.sharedInstance.requestConsentInfoUpdate(with: parameters) {
    // ...

    UMPConsentForm.loadAndPresentIfRequired(from: self) {
      //...

      // Consent has been gathered.

      // Show the button if privacy options are required.
      self.privacySettingsButton.isEnabled = isPrivacyOptionsRequired
    }
  }
  // ...
}

// Present the privacy options form when a user interacts with the
// privacy settings button.
@IBAction func privacySettingsTapped(_ sender: UIBarButtonItem) {
  UMPConsentForm.presentPrivacyOptionsForm(from: self) {
    [weak self] formError in
    guard let self, let formError else { return }

    // Handle the error.
  }
}

Objective-C

@interface ViewController ()
@property(weak, nonatomic) IBOutlet UIBarButtonItem *privacySettingsButton;
@end

- (BOOL)isPrivacyOptionsRequired {
  return UMPConsentInformation.sharedInstance.privacyOptionsRequirementStatus ==
         UMPPrivacyOptionsRequirementStatusRequired;
}

- (void)viewDidLoad {
  // ...

  __weak __typeof__(self) weakSelf = self;
  // Request an update for the consent information.
  [UMPConsentInformation.sharedInstance
      requestConsentInfoUpdateWithParameters:parameters
          completionHandler:^(NSError *_Nullable requestConsentError) {
            // ...

            [UMPConsentForm loadAndPresentIfRequiredFromViewController:strongSelf
                completionHandler:^(NSError *loadAndPresentError) {
                  // ...

                  // Consent has been gathered.

                  // Show the button if privacy options are required.
                  strongSelf.privacySettingsButton.enabled = isPrivacyOptionsRequired;
                }];
          }];
}

// Present the privacy options form when a user interacts with your
// privacy settings button.
- (IBAction)privacySettingsTapped:(UIBarButtonItem *)sender {
  [UMPConsentForm presentPrivacyOptionsFormFromViewController:self
                                completionHandler:^(NSError *_Nullable formError) {
                                  if (formError) {
                                    // Handle the error.
                                  }
                                }];
}

테스트

개발 중에 앱에서 통합을 테스트하려면 아래 단계에 따라 프로그래매틱 방식으로 테스트 기기를 등록하세요.

  1. requestConsentInfoUpdateWithParameters:completionHandler:를 호출합니다.
  2. 로그 출력에서 다음과 같은 메시지를 확인합니다. 메시지에는 기기 ID와 이를 테스트 기기로 추가하는 방법이 나와 있습니다.

    <UMP SDK>To enable debug mode for this device, set: UMPDebugSettings.testDeviceIdentifiers = @[2077ef9a63d2b398840261c8221a0c9b]
    
  3. 테스트 기기 ID를 클립보드에 복사합니다.

  4. 코드를 수정하여 call UMPDebugSettings().testDeviceIdentifiers 을 설정하고 테스트 기기 ID 목록을 전달합니다.

Swift

let parameters = UMPRequestParameters()
let debugSettings = UMPDebugSettings()
debugSettings.testDeviceIdentifiers = ["TEST-DEVICE-HASHED-ID"]
parameters.debugSettings = debugSettings
// Include the UMPRequestParameters in your consent request.
UMPConsentInformation.sharedInstance.requestConsentInfoUpdate(
    with: parameters,
    completionHandler: { error in
      ...
    })

Objective-C

UMPRequestParameters *parameters = [[UMPRequestParameters alloc] init];
UMPDebugSettings *debugSettings = [[UMPDebugSettings alloc] init];
debugSettings.testDeviceIdentifiers = @[ @"TEST-DEVICE-HASHED-ID" ];
parameters.debugSettings = debugSettings;
// Include the UMPRequestParameters in your consent request.
[UMPConsentInformation.sharedInstance
    requestConsentInfoUpdateWithParameters:parameters
                        completionHandler:^(NSError *_Nullable error){
                          ...
}];

지역 강제 설정

UMP SDK는 the debugGeography property of type UMPDebugGeography on UMPDebugSettings를 사용하여 기기가 EEA 또는 영국에 있는 것처럼 앱 동작을 테스트할 수 있는 방법을 제공합니다. 디버그 설정은 테스트 기기에서만 작동합니다.

Swift

let parameters = UMPRequestParameters()
let debugSettings = UMPDebugSettings()
debugSettings.testDeviceIdentifiers = ["TEST-DEVICE-HASHED-ID"]
debugSettings.geography = .EEA
parameters.debugSettings = debugSettings
// Include the UMPRequestParameters in your consent request.
UMPConsentInformation.sharedInstance.requestConsentInfoUpdate(
    with: parameters,
    completionHandler: { error in
      ...
    })

Objective-C

UMPRequestParameters *parameters = [[UMPRequestParameters alloc] init];
UMPDebugSettings *debugSettings = [[UMPDebugSettings alloc] init];
debugSettings.testDeviceIdentifiers = @[ @"TEST-DEVICE-HASHED-ID" ];
debugSettings.geography = UMPDebugGeographyEEA;
parameters.debugSettings = debugSettings;
// Include the UMPRequestParameters in your consent request.
[UMPConsentInformation.sharedInstance
    requestConsentInfoUpdateWithParameters:parameters
                         completionHandler:^(NSError *_Nullable error){
                           ...
}];

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

Swift

UMPConsentInformation.sharedInstance.reset()

Objective-C

[UMPConsentInformation.sharedInstance reset];

GitHub의 예

UMP SDK 통합 예시: Swift | Objective-C