본문으로 건너뛰기

네이티브 광고

Native 광고를 통해 서비스의 UI에 맞춘 자연스러운 광고를 제공할 수 있습니다.

제목, 이미지, 행동 유도 버튼 등의 광고 속성이 제공되므로 맞춤형 UI를 구성할 수 있습니다.


시작하기 앞서

  • 광고 호출을 위해 Ad Unit ID가 필요합니다.

    NAM Admin을 통해 광고 공급자 설정, Inventory 설정, 광고 유닛 등록 등의 과정을 마무리하여 주시기 바랍니다.

    관련 내용은 NAM 관리자에게 문의 부탁드립니다.

  • 광고 상위에 다른 View가 있다면 노출 측정이 제대로 되지 않아 성과 지표 측정에 불이익이 있을 수 있습니다.


[Step 1] NAM SDK 적용 완료

공통 통합 내용을 참고해 주세요

이하 내용은 NAM SDK 적용이 완료된 상태를 가정하고 진행합니다.


[Step 2] 레이아웃 구성

네이티브 광고를 게재하기 위해서는 먼저 광고를 게재하려는 Activity 또는 Fragment 의 레이아웃에 네이티브 광고가 삽입될 ViewGroup 을 추가해야 합니다.

아래 예제에서는 RelativeLayout ViewGroup 에 native_container 라는 id 로 네이티브 광고가 게재될 ViewGroup 을 선언했습니다.

<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".NativeBannerFragment">

<RelativeLayout
android:id="@+id/native_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_alignParentBottom="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

[Step 3] GfpNativeAdView 레이아웃 구성

네이티브 광고가 게재될 ViewGroup 이 포함된 레이아웃을 구성했다면 이어서 네이티브 광고가 렌더링 될 레이아웃을 구성해야 합니다.

아래의 필수 주의 사항이 반영된 xml 파일의 이름은 content_native_ad.xml 이라고 가정합니다.

이 레이아웃은 로드 완료 이후 렌더링 단계에서 사용됩니다.

  1. 최상단의 레이아웃은 com.naver.gfpsdk.GfpNativeAdView 가 되어야 합니다.

  2. GfpNativeAdView 하위에는 Asset 들을 담을 ViewGroup 이 할당되어야 합니다.

    아래 예제 에서는 assets_container 라는 id 로 선언했습니다.

    • 해당 ViewGroup 은 이후에 렌더링을 시도하게 되는 광고 제공자의 필수 layout 의 child 로 포함되게 됨으로 필수로 할당되어야 합니다.
  3. AdChoicesView 가 렌더링 되는 GfpAdChoicesView 를 할당해야 합니다.

    • FAN, S2S 광고의 AdChoicesView 가 해당 영역에 렌더링 됩니다.
    • Asset 들은 container 인 ViewGroup 하위에 할당되어야 합니다.
    • width, height 값은 20dp 이상이어야 하고 권장 사이즈는 width20dp, height20dp 입니다.
    • 광고 표준(IAB) 스펙으로 네이티브 광고는 반드시 표시해야 합니다.
    • 참고 - 구글 안내
  4. icon 이 아닌 메인으로 사용될 이미지나 동영상이 그려질 영역은 GfpMediaView 로 선언해야만 합니다.

  5. 'Native Banner' 광고를 렌더링 하는 경우 GfpMediaView는 선언하지 않아도 됩니다.

<?xml version="1.0" encoding="utf-8"?>
<com.naver.gfpsdk.GfpNativeAdView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/gfp_native_ad"
android:layout_width="match_parent"
android:layout_height="wrap_content">

<FrameLayout
android:id="@+id/assets_container"
android:layout_width="match_parent"
android:layout_height="wrap_content">

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:background="#FFFFFF"
android:minHeight="50dp"
android:orientation="vertical">

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="10dp">

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="12dp"
android:orientation="horizontal">

<ImageView
android:id="@+id/ad_app_icon"
android:layout_width="46dp"
android:layout_height="46dp"
android:layout_marginRight="10dp"
android:adjustViewBounds="true" />

<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_weight="1"
android:orientation="vertical">

<TextView
android:id="@+id/ad_headline"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="4dp"
android:ellipsize="end"
android:lines="1"
android:textColor="#000000"
android:textSize="12dp" />

<TextView
android:id="@+id/ad_sponsored"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/ad_attribution"
android:textColor="#999999"
android:textSize="12dp" />

</LinearLayout>

<com.naver.gfpsdk.GfpAdChoicesView
android:id="@+id/ad_choices_view"
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_gravity="center_vertical"
android:layout_marginLeft="10dp" />

</LinearLayout>

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">

<TextView
android:id="@+id/ad_body"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="12dp"
android:ellipsize="end"
android:maxLines="2"
android:textColor="#000000"
android:textSize="15dp" />

<!--
if there is no media view
new GfpNativeAdOptions.Builder().setHasMediaView(false)
this should be deleted
-->
<com.naver.gfpsdk.GfpMediaView
android:id="@+id/ad_media"
android:layout_width="match_parent"
android:layout_height="220dp"
android:layout_marginBottom="12dp"
android:adjustViewBounds="true" />

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">

<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="3"
android:orientation="vertical">

<TextView
android:id="@+id/ad_advertiser"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="end"
android:lines="1"
android:textColor="@android:color/darker_gray"
android:textSize="13dp" />

<TextView
android:id="@+id/ad_social_context"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="end"
android:gravity="center_vertical"
android:lines="1"
android:textColor="@android:color/black"
android:textSize="13dp" />

</LinearLayout>

<Button
android:id="@+id/ad_call_to_action"
android:layout_width="100dp"
android:layout_height="40dp"
android:background="@color/colorPrimary"
android:paddingLeft="3dp"
android:paddingRight="3dp"
android:textColor="#ffffff"
android:textSize="13dp" />

</LinearLayout>

</LinearLayout>
</LinearLayout>
</LinearLayout>

</FrameLayout>
</com.naver.gfpsdk.GfpNativeAdView>

[Step 4] AdParam 과 GfpAdLoader 생성

Native 광고를 요청하기 위해GfpAdLoader 를 생성해야 합니다.

광고 요청 정보를 담은 AdParam 객체를 생성하고 GfpAdLoader 생성자에 할당하게 됩니다.

요청 정보는 Ad Unit ID를 제외한 값은 선택적이고 광고 요청 정보를 참고해 주시기 바랍니다.

override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val view = inflater.inflate(R.layout.fragment_native_banner, container, false)
val nativeContainer = view.findViewById<RelativeLayout>(R.id.native_container)

// 광고 요청 파라미터
val adParam = AdParam.Builder().setAdUnitId("YOUR_AD_UNIT_ID").build()

// 네이티브 광고 옵션 생성
val nativeAdOptions = GfpNativeAdOptions.Builder().setHasMediaView(true).build()

// 광고 Loader 생성
val adLoader = GfpAdLoader.Builder(requireActivity(), adParam)
// 광고 요청 타임아웃 설정
.withTimeoutMillis(60_000L)
// 광고 리스너 설정
.withAdListener(object: AdEventListener() {
override fun onAdClicked() {
// AD Clicked
}
override fun onAdImpression() {
// AD Impression
}
override fun onAdMuted() {
// AD Muted
}
override fun onAdMetaChanged(params: Map<String, String>) {
// AD Meta Changed
}
override fun onError(error: GfpError, responseInfo: GfpResponseInfo) {
Log.e("NativeBannerFragment", responseInfo.toString())
}
})
// 네이티브 광고 옵션 및 로드 완료 리스너 설정
.withNativeAd(
nativeAdOptions,
object: GfpNativeAd.OnNativeAdLoadedListener {
override fun onNativeAdLoaded(gfpNativeAd: GfpNativeAd) {
inflateAd(gfpNativeAd)
}
}
)
.build()

adLoader.loadAd()

return view
}

4-1. 광고 요청 타임아웃 설정

광고 요청마다 타임아웃을 설정할 경우에는 GfpAdLoaderBuilder 설정시 withTimeoutMillis() 를 추가해야만 합니다.

미설정시 기본값은 SdkProperties 를 통해 전역 설정된 값(기본값 : 60초)을 사용합니다.

4-2. GfpNativeAdOptions

네이티브 광고의 adChoicesView 위치를 변경하거나

MediaView 를 가지지 않는 Native Banner 광고를 요청하고 싶을 경우 사용합니다.

네이티브 광고 옵션 값은 GfpAdLoader 생성시 withNativeAd() 를 통해 전달합니다.

  • setAdChoicesPlacement(int)

    DFP/NDA 네이티브 광고의 adChoicesView 위치를 변경하는데 사용됩니다.

    정보

    InMobi 네이티브 광고는 AdChoicesView 의 렌더링 뿐만 아니라 렌더링 될 위치를 InMobi SDK 내부적으로 처리하게 됩니다.

    따라서 네이티브 광고 레이아웃의 GfpAdChoicesView 위치 그리고 GfpNativeAdOptions 에 설정되는 adChoicesPlacement 값에 관계없이 렌더링 됩니다.

  • setHasMediaView(boolean)

    default 값은 true 이고, false 로 할당할 경우 MediaView 를 가지지 않는 Native Banner 광고 를 렌더링 할 수 있습니다.

    만약 false 로 할당할 경우에는 아래와 같은 제약사항이 있습니다.

    • 현재 NAM SDK 기준으로 MediaView 를 가지지 않는 네이티브 광고는 DFP, FAN 모듈 에서만 제공됩니다.
    • GfpNativeAdView 가 포함된 레이아웃을 생성할 때 mediaView 를 제거해야 합니다. (위 레이아웃의 ad_media id 참고)
    정보

    Native Banner 광고를 렌더링 한다면 NAM 관리자에게 광고 공급자에서 Native Banner 광고 설정이 되어 있는지 확인 후 진행 부탁드립니다.

4-3. 광고 로드 이벤트 수신 - GfpNativeAd.OnNativeAdLoadedListener

GfpAdLoader.Builder#withNativeAd(GfpNativeAdOptions, OnNativeAdLoadedListener)를 통해 광고가 성공적으로 로드 됐을 때 로드 이벤트를 수신 할 수 있는데,

이때 GfpNativeAd.OnNativeAdLoadedListener#onNativeAdLoaded() 의 파라미터로 로드된 광고 정보를 담고 있는 GfpNativeAd 객체가 전달됩니다.

로드가 완료된 이후 렌더링이 필요하므로 해당 리스너에서 GfpNativeAdView를 생성하고 native_container에 inflate 해야 합니다.

val adLoader = GfpAdLoader.Builder(this, adParam)
...
.withNativeAd(
nativeAdOptions,
object: GfpNativeAd.OnNativeAdLoadedListener {
override fun onNativeAdLoaded(nativeAd: GfpNativeAd) {
// 광고 로드에 성공했을 경우
inflateNativeAd(nativeAd)
}
}
)
.build()

4-4. AdEventListener

GfpAdLoader.Builder#withAdListener(AdEventListener) 를 설정함으로써 로드를 제외한 click, impression, error 등에 대한 이벤트를 수신 할 수 있습니다.


[Step 5] 광고 로드

GfpAdLoader 에 대한 설정이 마무리 되었다면 광고를 로드할 수 있습니다.

단일 GfpAdLoader 를 통해서 광고를 로드할 경우 한 번에 하나씩만 요청해야 합니다.

GfpAdLoader 를 다시 사용하는 경우 각 요청이 완료된 후에 loadAd() 를 다시 호출해 다음 요청을 시작해야 합니다.

만약 요청이 완료되기 전 loadAd() 를 다시 호출할 경우에는 이전 로드가 취소되거나 이미 로드된 광고가 삭제될 수 있습니다.

import ...
import com.naver.gfpsdk.AdEventListener
import com.naver.gfpsdk.AdParam
import com.naver.gfpsdk.GfpAdChoicesView
import com.naver.gfpsdk.GfpAdLoader
import com.naver.gfpsdk.GfpError
import com.naver.gfpsdk.GfpMediaView
import com.naver.gfpsdk.GfpNativeAd
import com.naver.gfpsdk.GfpNativeAdOptions
import com.naver.gfpsdk.GfpNativeAdView
import com.naver.gfpsdk.GfpResponseInfo
import com.naver.gfpsdk.Image

class NativeBannerFragment : Fragment() {
private lateinit var nativeContainer: RelativeLayout
private lateinit var adLoader: GfpAdLoader

override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
val view = inflater.inflate(R.layout.fragment_native_banner, container, false)
nativeContainer = view.findViewById(R.id.native_container)
val adParam = AdParam.Builder().setAdUnitId(AD_UNIT_ID).build()
val nativeAdOptions = GfpNativeAdOptions.Builder()
.setHasMediaView(true)
.build()
adLoader = GfpAdLoader.Builder(this, adParam)
.withTimeoutMillis(60_000L)
.withAdListener(object: AdEventListener() {
override fun onAdClicked() {
Log.d("NativeBannerFragment", "클릭 발생")
}

override fun onAdImpression() {
Log.d("NativeBannerFragment", "노출 성공")
}

override fun onError(error: GfpError, responseInfo: GfpResponseInfo) {
val errorString = String.format(
"code[%d] subCode[%s] message[%s] responseInfo[%s]",
error.errorCode,
error.errorSubCode,
error.errorMessage,
responseInfo.toString()
)
Log.e("NativeBannerFragment", errorString)
}
})
.withNativeAd(
nativeAdOptions,
object: GfpNativeAd.OnNativeAdLoadedListener {
override fun onNativeAdLoaded(nativeAd: GfpNativeAd) {
inflateAd(nativeAd)
}
}
)
.build()

adLoader.loadAd()

return view
}

private fun inflateAd(nativeAd: GfpNativeAd) {
// native 광고 렌더링
}

companion object {
private const val AD_UNIT_ID = "YOUR_AD_UNIT_ID"
}
}

[Step 6] 광고 렌더링

광고를 성공적으로 로드했을 때 전달받게 되는 GfpNativeAd 객체를 통해 asset 들의 meta 정보를 가져오게 됩니다.

렌더링 시에 주의해야 할 내용은 아래와 같습니다.

  • GfpNativeAdView 객체에 assetsContaineradChoicesView 를 반드시 set 해줘야 합니다.
    • set 을 해주지 않을 경우 exception 이 발생합니다.
  • GfpNativeAdView 객체에 icon, title, body, callToAction, advertiser, socialContext 에 대한 assetView 들을 set 해줘야 합니다.
    • set 을 해주지 않을 경우 click event 가 발생하지 않을 수 있습니다.
  • GfpNativeAdView 객체에 setNativeAd() 를 꼭 호출해야만 합니다.
    • 해당 작업을 하지 않을 경우 광고 제공자들이 강제하는 레이아웃을 추가해주는 작업과 재사용시에 이전 광고객체에 대한 clear 작업이 이뤄지지 않으므로 동작에 문제가 생길 수 있습니다.
  • Native Banner 광고를 설정한 경우 (GfpNativeAdOptions.setHasMediaView(false)) GfpNativeAdView 객체에 setMediaView(mediaView)를 호출하지 않아야 합니다.
    • media view를 사용하지 않기로 설정했기 때문에 validation 과정에서 exception 이 발생합니다.
private fun inflateAd(nativeAd: GfpNativeAd) {
nativeContainer.removeAllViews()

val nativeAdView = layoutInflater.inflate(R.layout.content_native_ad, nativeContainer, false) as GfpNativeAdView
nativeContainer.addView(nativeAdView)

with(nativeAdView) {
val assetsContainer = findViewById<FrameLayout>(R.id.assets_container)
val mediaView = findViewById<GfpMediaView>(R.id.ad_media)
val adChoicesView = findViewById<GfpAdChoicesView>(R.id.ad_choices_view)
val iconView = findViewById<ImageView>(R.id.ad_app_icon)
val titleView = findViewById<TextView>(R.id.ad_headline)
val bodyView = findViewById<TextView>(R.id.ad_body)
val advertiserView = findViewById<TextView>(R.id.ad_advertiser)
val socialContextView = findViewById<TextView>(R.id.ad_social_context)
val callToActionButton = findViewById<Button>(R.id.ad_call_to_action)
val noticeView = findViewById<TextView>(R.id.ad_notice)

setAssetsContainer(assetsContainer)
setAdChoicesView(adChoicesView)
setIconView(iconView)
setTitleView(titleView)
setBodyView(bodyView)
setAdvertiserView(advertiserView)
setSocialContextView(socialContextView)
setCallToActionView(callToActionButton)
setNoticeView(noticeView)
setMediaView(mediaView)
}


nativeAd.run {
titleView.text = title
bodyView.text = body
callToActionButton.text = callToAction
advertiserView.text = advertiserName

icon?.let {
iconView.setImageDrawable(it.drawable)
iconView.visibility = View.VISIBLE
} ?: iconView.visibility = View.GONE

socialContext?.let {
socialContextView.text = it
socialContextView.visibility = View.VISIBLE
} ?: socialContextView.visibility = View.GONE

notice?.let {
noticeView.text = it
noticeView.visibility = View.VISIBLE
} ?: noticeView.visibility = View.GONE

nativeAdView.setNativeAd(this)
}
}

[Step 7] 광고 삭제

네이티브 광고의 게재가 끝나면 광고가 올바르게 폐기되도록 광고를 삭제해야 합니다.

광고 삭제는 아래와 같이 GfpAdLoader 가 제공하는 cancel() 을 호출하면 됩니다.

@Override
public void onDestroy() {
super.onDestroy();
if (adLoader != null) {
adLoader.cancel();
}
}

부록 각 DSP 별 NAM SDK 가 지원하는 Assets

1. FAN Native 광고에 대해서 NAM SDK 가 지원하는 Assets

Asset지원 여부비고
titleO
imageONative Banner 로 렌더링할 때는 사용되지 않음
uri, width, height 값을 전달
bodyO
iconOuri, width, height 값을 전달
call to actionO
advertiser nameOFAN SDK 4.9.0 이상 버전에서부터 추가된 항목
social contextO

2. DFP Native 광고에 대해서 NAM SDK 가 지원하는 Assets

Asset지원 여부비고
titleO
imageOdrawable, uri, scale, width, height 값을 전달
bodyO
iconOdrawable, uri, scale, width, height 값을 전달
call to actionO
advertiser nameO
social contextX

3. InMobi Native 광고에 대해서 NAM SDK 가 지원하는 Assets

Asset지원 여부비고
titleO
imageOInMobi 는 네이티브 광고(동영상, 이미지) 에서 이미지 asset 을 제공하지 않음
bodyO
iconOdrawable, uri 값 전달
call to actionO
advertiser nameX
social contextX

4. AppLovin Native 광고에 대해서 NAM SDK 가 지원하는 Assets

Asset지원 여부비고
titleO반드시 포함 되어야 함
imageONative Banner 로 렌더링할 때는 사용되지 않음
bodyO
iconO
call to actionO반드시 Button 객체 이어야 함
advertiser nameO
social contextX