시스템에서 정의된 네이티브 광고 형식 표시
네이티브 광고가 로드되면 GADAdLoaderDelegate 프로토콜 메시지 중 하나를 사용하여
네이티브 광고 객체가 앱에 전송됩니다. 그런 다음 앱이 광고를 표시해야 하는데,
즉시 표시할 필요는 없습니다.
시스템 정의 광고 형식을 보다 쉽게 표시할 수 있도록 SDK에서는
유용한 리소스를 제공합니다.
GADNativeAdView
GADNativeAd의 경우 '광고 뷰' 클래스인
GADNativeAdView가
있습니다.
이 광고 뷰 클래스는 게시자가 광고를 표시하는 데 사용해야 하는 UIView입니다.
예를 들어 단일 GADNativeAdView는 GADNativeAd의 단일 인스턴스를 표시할 수
있습니다. 이 광고의 애셋을 표시하는 데 사용되는 UIView 객체 각각은
해당 GADNativeAdView 객체의 하위 뷰여야 합니다.
예를 들어 UITableView에 광고를 표시했다면 셀 중 하나의 뷰
계층 구조는 다음과 같습니다.

또한 GADNativeAdView 클래스는 개별 애셋에 사용되는 뷰를 등록하는
IBOutlets와 GADNativeAd 객체 자체를 등록하는
메서드 1개도
제공합니다. 이 방법으로 뷰를 등록하면 다음과 같은 작업을 SDK가 자동으로
처리할 수 있습니다.
- 클릭 기록
- 노출 기록(첫 픽셀이 화면에 표시되는 시점)
- AdChoices 오버레이 표시
AdChoices 오버레이
간접 네이티브 광고(Ad Manager 예비 광고나 Ad Exchange 또는 애드센스를 통해 제공)의 경우 SDK에서 AdChoices 오버레이를 추가합니다. 네이티브 광고 뷰에서 원하는 모서리 부분에 AdChoices 로고가 자동으로 삽입될 공간을 남겨두세요. 또한 아이콘이 잘 보이도록 AdChoices 오버레이가 콘텐츠 위에 배치되게 하세요. 오버레이의 모양과 기능에 대해 자세히 알아보려면 프로그래매틱 네이티브 광고 구현 가이드라인을 참고하세요.
프로그래매틱 네이티브 광고의 광고 표시
프로그래매틱 네이티브 광고를 표시할 때 이 뷰가 광고임을 나타내는 광고 표시를 적용해야 합니다. 정책 가이드라인에서 자세히 알아보세요.코드 예
이 섹션에서는 xib 파일에서 동적으로 로드된 뷰를 사용하여 네이티브 광고를 표시하는
방법을 보여줍니다. 이 방법은 여러 형식을 요청하도록 구성된 GADAdLoaders를
사용할 때 매우 유용합니다.
UIViews 레이아웃
먼저 네이티브 광고 확장 소재를 표시할 UIViews를 구성해야 합니다.
다른 xib 파일을 만들 때처럼 인터페이스 빌더를
사용할 수 있습니다. 다음은 네이티브 광고
레이아웃의 예시입니다.

이미지의 오른쪽 상단에 있는 커스텀 클래스 값을 확인하세요. 이 값은
GADNativeAdView로 설정되며,
GADNativeAd를 표시하는 데 사용된 광고 뷰 클래스입니다.
광고의 동영상 또는 이미지를 표시하는 데 사용되는
GADMediaView의 맞춤 클래스도 설정해야 합니다.
아웃렛과 뷰 연결
뷰를 배치했고 레이아웃에 올바른 광고 뷰 클래스를 할당했으면 생성한 UIViews에
광고 뷰의 확장 소재 아웃렛을 연결해야 합니다.
다음은 광고용으로 생성된 UIViews에 광고 뷰의 애셋 아웃렛을 연결하는 방법의
예시입니다.

아웃렛 패널에서 GADNativeAdView의 아웃렛이 인터페이스 빌더의
UIViews에 연결되었습니다. 따라서
어느 UIView가 어느 애셋을 표시하는지 SDK에서 인식할 수 있습니다.
이러한 아웃렛은 광고에서 클릭 가능한 뷰를
나타내기도 한다는 점에 유의하세요.
광고 표시
레이아웃이 완성되었고 아웃렛이 연결되었으면, 이제 로드된 광고를 표시하는 코드를 앱에 추가합니다.
Swift
func adLoader(_ adLoader: AdLoader, didReceive nativeAd: NativeAd) {
// ...
// Set ourselves as the native ad delegate to be notified of native ad events.
nativeAd.delegate = self
// Populate the native ad view with the native ad assets.
// The headline and mediaContent are guaranteed to be present in every native ad.
(nativeAdView.headlineView as? UILabel)?.text = nativeAd.headline
nativeAdView.mediaView?.mediaContent = nativeAd.mediaContent
// Some native ads will include a video asset, while others do not. Apps can use the
// GADVideoController's hasVideoContent property to determine if one is present, and adjust their
// UI accordingly.
let mediaContent = nativeAd.mediaContent
if mediaContent.hasVideoContent {
// By acting as the delegate to the GADVideoController, this ViewController receives messages
// about events in the video lifecycle.
mediaContent.videoController.delegate = self
videoStatusLabel.text = "Ad contains a video asset."
} else {
videoStatusLabel.text = "Ad does not contain a video."
}
// This app uses a fixed width for the GADMediaView and changes its height to match the aspect
// ratio of the media it displays.
if let mediaView = nativeAdView.mediaView, nativeAd.mediaContent.aspectRatio > 0 {
let aspectRatioConstraint = NSLayoutConstraint(
item: mediaView,
attribute: .width,
relatedBy: .equal,
toItem: mediaView,
attribute: .height,
multiplier: CGFloat(nativeAd.mediaContent.aspectRatio),
constant: 0)
mediaView.addConstraint(aspectRatioConstraint)
nativeAdView.layoutIfNeeded()
}
// These assets are not guaranteed to be present. Check that they are before
// showing or hiding them.
(nativeAdView.bodyView as? UILabel)?.text = nativeAd.body
nativeAdView.bodyView?.isHidden = nativeAd.body == nil
(nativeAdView.callToActionView as? UIButton)?.setTitle(nativeAd.callToAction, for: .normal)
nativeAdView.callToActionView?.isHidden = nativeAd.callToAction == nil
(nativeAdView.iconView as? UIImageView)?.image = nativeAd.icon?.image
nativeAdView.iconView?.isHidden = nativeAd.icon == nil
(nativeAdView.starRatingView as? UIImageView)?.image = imageOfStars(from: nativeAd.starRating)
nativeAdView.starRatingView?.isHidden = nativeAd.starRating == nil
(nativeAdView.storeView as? UILabel)?.text = nativeAd.store
nativeAdView.storeView?.isHidden = nativeAd.store == nil
(nativeAdView.priceView as? UILabel)?.text = nativeAd.price
nativeAdView.priceView?.isHidden = nativeAd.price == nil
(nativeAdView.advertiserView as? UILabel)?.text = nativeAd.advertiser
nativeAdView.advertiserView?.isHidden = nativeAd.advertiser == nil
// In order for the SDK to process touch events properly, user interaction should be disabled.
nativeAdView.callToActionView?.isUserInteractionEnabled = false
// Associate the native ad view with the native ad object. This is
// required to make the ad clickable.
// Note: this should always be done after populating the ad views.
nativeAdView.nativeAd = nativeAd
}
SwiftUI
뷰 모델 만들기
네이티브 광고를 로드하고 네이티브 광고 데이터 변경사항을 게시하는 뷰 모델을 만듭니다.
import GoogleMobileAds
class NativeAdViewModel: NSObject, ObservableObject, NativeAdLoaderDelegate {
@Published var nativeAd: NativeAd?
private var adLoader: AdLoader!
func refreshAd() {
adLoader = AdLoader(
adUnitID: "ca-app-pub-3940256099942544/3986624511",
// The UIViewController parameter is optional.
rootViewController: nil,
adTypes: [.native], options: nil)
adLoader.delegate = self
adLoader.load(Request())
}
func adLoader(_ adLoader: AdLoader, didReceive nativeAd: NativeAd) {
// Native ad data changes are published to its subscribers.
self.nativeAd = nativeAd
nativeAd.delegate = self
}
func adLoader(_ adLoader: AdLoader, didFailToReceiveAdWithError error: Error) {
print("\(adLoader) failed with error: \(error.localizedDescription)")
}
}
UIViewRepresentable 만들기
NativeView의
UIViewRepresentable을 만들고
ViewModel 클래스에서 데이터 변경사항을 구독합니다.
private struct NativeAdViewContainer: UIViewRepresentable {
typealias UIViewType = NativeAdView
// Observer to update the UIView when the native ad value changes.
@ObservedObject var nativeViewModel: NativeAdViewModel
func makeUIView(context: Context) -> NativeAdView {
return
Bundle.main.loadNibNamed(
"NativeAdView",
owner: nil,
options: nil)?.first as! NativeAdView
}
func updateUIView(_ nativeAdView: NativeAdView, context: Context) {
guard let nativeAd = nativeViewModel.nativeAd else { return }
// Each UI property is configurable using your native ad.
(nativeAdView.headlineView as? UILabel)?.text = nativeAd.headline
nativeAdView.mediaView?.mediaContent = nativeAd.mediaContent
(nativeAdView.bodyView as? UILabel)?.text = nativeAd.body
(nativeAdView.iconView as? UIImageView)?.image = nativeAd.icon?.image
(nativeAdView.starRatingView as? UIImageView)?.image = imageOfStars(from: nativeAd.starRating)
(nativeAdView.storeView as? UILabel)?.text = nativeAd.store
(nativeAdView.priceView as? UILabel)?.text = nativeAd.price
(nativeAdView.advertiserView as? UILabel)?.text = nativeAd.advertiser
(nativeAdView.callToActionView as? UIButton)?.setTitle(nativeAd.callToAction, for: .normal)
// For the SDK to process touch events properly, user interaction should be disabled.
nativeAdView.callToActionView?.isUserInteractionEnabled = false
// Associate the native ad view with the native ad object. This is required to make the ad
// clickable.
// Note: this should always be done after populating the ad views.
nativeAdView.nativeAd = nativeAd
}
뷰를 뷰 계층 구조에 추가
다음 코드는 UIViewRepresentable을 뷰 계층 구조에 추가하는
방법을 보여줍니다.
struct NativeContentView: View {
// Single source of truth for the native ad data.
@StateObject private var nativeViewModel = NativeAdViewModel()
var body: some View {
ScrollView {
VStack(spacing: 20) {
// Updates when the native ad data changes.
NativeAdViewContainer(nativeViewModel: nativeViewModel)
.frame(minHeight: 300) // minHeight determined from xib.
Objective-C
- (void)adLoader:(GADAdLoader *)adLoader didReceiveNativeAd:(GADNativeAd *)nativeAd {
// ...
GADNativeAdView *nativeAdView = self.nativeAdView;
// Set ourselves as the ad delegate to be notified of native ad events.
nativeAd.delegate = self;
// Populate the native ad view with the native ad assets.
// The headline and mediaContent are guaranteed to be present in every native ad.
((UILabel *)nativeAdView.headlineView).text = nativeAd.headline;
nativeAdView.mediaView.mediaContent = nativeAd.mediaContent;
// This app uses a fixed width for the GADMediaView and changes its height
// to match the aspect ratio of the media content it displays.
if (nativeAdView.mediaView != nil && nativeAd.mediaContent.aspectRatio > 0) {
NSLayoutConstraint *aspectRatioConstraint =
[NSLayoutConstraint constraintWithItem:nativeAdView.mediaView
attribute:NSLayoutAttributeWidth
relatedBy:NSLayoutRelationEqual
toItem:nativeAdView.mediaView
attribute:NSLayoutAttributeHeight
multiplier:(nativeAd.mediaContent.aspectRatio)
constant:0];
[nativeAdView.mediaView addConstraint:aspectRatioConstraint];
[nativeAdView layoutIfNeeded];
}
if (nativeAd.mediaContent.hasVideoContent) {
// By acting as the delegate to the GADVideoController, this ViewController
// receives messages about events in the video lifecycle.
nativeAd.mediaContent.videoController.delegate = self;
self.videoStatusLabel.text = @"Ad contains a video asset.";
} else {
self.videoStatusLabel.text = @"Ad does not contain a video.";
}
// These assets are not guaranteed to be present. Check that they are before
// showing or hiding them.
((UILabel *)nativeAdView.bodyView).text = nativeAd.body;
nativeAdView.bodyView.hidden = nativeAd.body ? NO : YES;
[((UIButton *)nativeAdView.callToActionView) setTitle:nativeAd.callToAction
forState:UIControlStateNormal];
nativeAdView.callToActionView.hidden = nativeAd.callToAction ? NO : YES;
((UIImageView *)nativeAdView.iconView).image = nativeAd.icon.image;
nativeAdView.iconView.hidden = nativeAd.icon ? NO : YES;
((UIImageView *)nativeAdView.starRatingView).image = [self imageForStars:nativeAd.starRating];
nativeAdView.starRatingView.hidden = nativeAd.starRating ? NO : YES;
((UILabel *)nativeAdView.storeView).text = nativeAd.store;
nativeAdView.storeView.hidden = nativeAd.store ? NO : YES;
((UILabel *)nativeAdView.priceView).text = nativeAd.price;
nativeAdView.priceView.hidden = nativeAd.price ? NO : YES;
((UILabel *)nativeAdView.advertiserView).text = nativeAd.advertiser;
nativeAdView.advertiserView.hidden = nativeAd.advertiser ? NO : YES;
// In order for the SDK to process touch events properly, user interaction
// should be disabled.
nativeAdView.callToActionView.userInteractionEnabled = NO;
// Associate the native ad view with the native ad object. This is
// required to make the ad clickable.
// Note: this should always be done after populating the ad views.
nativeAdView.nativeAd = nativeAd;
}
GitHub의 전체 예
각 GitHub 링크를 따라 Swift, SwiftUI, Objective-C에서 네이티브 광고를 통합하는 전체 예를 확인하세요.
Swift 맞춤 렌더링 예 SwiftUI 네이티브 광고 예 Objective-C 맞춤 렌더링 예
GADMediaView
이미지 및 동영상 애셋은 GADMediaView를 사용하여
사용자에게 표시됩니다.
이는 xib 파일에서 정의하거나 동적으로 생성할 수 있는 UIView입니다.
다른 애셋 뷰와 마찬가지로 GADNativeAdView의 뷰 계층 구조 내에
배치되어야 합니다.
모든 애셋 뷰와 마찬가지로 미디어 뷰에는 콘텐츠를 채워야 하며, 이는 GADMediaView의
mediaContent 속성을
사용하여 설정됩니다. GADNativeAd의
mediaContent 속성에는
GADMediaView에
전달할 수 있는
미디어 콘텐츠가
포함됩니다.
다음은
맞춤 렌더링 예(Swift
| Objective-C)의
스니펫으로,
GADNativeAd의 GADMediaContent를 사용하여
네이티브 광고 확장 소재로 GADMediaView를 채우는 방법을 보여줍니다.
Swift
nativeAdView.mediaView?.mediaContent = nativeAd.mediaContent
Objective-C
nativeAdView.mediaView.mediaContent = nativeAd.mediaContent;
네이티브 광고 뷰의 인터페이스 빌더 파일에서 뷰 커스텀 클래스를 GADMediaView로
설정하고 mediaView 아웃렛에 연결했는지
확인하세요.
이미지 콘텐츠 모드 변경
GADMediaView 클래스는 이미지를 표시할 때 UIView
contentMode
속성을 따릅니다. GADMediaView에서 이미지의 크기가 조정되는 방식을
변경하려면 GADMediaView의
contentMode 속성에서 해당
UIViewContentMode를 설정합니다.
다음 예시는 이미지가 표시될 때 GADMediaView를 채우려는 경우입니다(광고에
동영상이 없음).
Swift
nativeAdView.mediaView?.contentMode = .scaleAspectFit
Objective-C
GADMediaView *mediaView = nativeAdView.mediaView;
if (mediaView) {
mediaView.contentMode = UIViewContentModeScaleAspectFit;
}
GADMediaContent
GADMediaContent
클래스에는 GADMediaView 클래스를 사용하여 표시되는 네이티브 광고의 미디어 콘텐츠와
관련된 데이터가 포함됩니다. GADMediaView mediaContent 속성에 설정한
경우에는 다음과 같습니다.
사용할 수 있는 동영상 애셋은 버퍼링 후
GADMediaView안에서 재생되기 시작합니다.hasVideoContent를 확인하면 동영상 애셋을 사용할 수 있는지 알 수 있습니다.광고에 동영상 애셋이 없으면
mainImage애셋이 대신 다운로드되어GADMediaView에 배치됩니다.
다음 단계
사용자 개인 정보 보호에 대해 자세히 알아보세요.