메인 콘텐츠로 건너뛰기

개요

네이티브 광고는 앱의 디자인에 맞게 광고 UI를 자유롭게 커스터마이징할 수 있는 광고 포맷입니다. 광고 소재(이미지, 동영상), 제목, 설명, CTA 버튼 등의 요소를 개별적으로 배치하여 자연스러운 사용자 경험을 제공할 수 있습니다.

주요 기능

  • 완전한 UI 커스터마이징: 앱의 디자인 시스템에 맞게 광고 레이아웃을 자유롭게 구성
  • 다양한 미디어 지원: 이미지 및 동영상 광고 소재 지원
  • 유연한 클릭 처리: 전체 클릭 또는 커스텀 클릭 처리 가능
  • 프로필 정보 표시: 광고주 프로필 로고 및 이름 지원
  • 백필 광고 지원: 백필 광고 여부 확인 가능

AdropNativeAd 클래스

네이티브 광고를 로드하고 관리하는 메인 클래스입니다.

생성자

new AdropNativeAd(unitId: string, useCustomClick?: boolean)
unitId
string
required
광고 지면 ID (콘솔에서 발급)
useCustomClick
boolean
default:"false"
커스텀 클릭 처리 사용 여부
  • true: 개발자가 직접 클릭 처리를 구현 (비디오 광고 컨트롤러 사용 가능)
  • false: AdropNativeAdView가 모든 클릭 이벤트를 자동으로 처리

메서드

메서드설명
load()광고를 요청하고 로드합니다
destroy()광고 리소스를 해제합니다

프로퍼티

프로퍼티타입설명
isLoadedboolean광고 로드 완료 여부 (읽기 전용)
unitIdstring광고 지면 ID (읽기 전용)
useCustomClickboolean커스텀 클릭 처리 사용 여부 (읽기 전용)
creativeIdstring광고 소재 ID (읽기 전용)
txIdstring트랜잭션 ID (읽기 전용)
campaignIdstring캠페인 ID (읽기 전용)
isBackfilledboolean백필 광고 여부 (읽기 전용)
propertiesAdropNativeProperties광고 속성 정보 (읽기 전용)
listenerAdropNativeAdListener광고 이벤트 리스너

AdropNativeAdView 컴포넌트

네이티브 광고를 표시할 컨테이너 컴포넌트입니다.

Props

interface Props extends ViewProps {
  nativeAd?: AdropNativeAd
}
nativeAd
AdropNativeAd
표시할 네이티브 광고 인스턴스

사용 예시

<AdropNativeAdView nativeAd={nativeAd} style={styles.adContainer}>
  {/* 광고 요소들 */}
</AdropNativeAdView>
AdropNativeAdView는 광고 컨텍스트를 제공하므로, 모든 광고 요소 뷰들은 이 컴포넌트 내부에 배치해야 합니다.

네이티브 광고 요소 뷰

AdropProfileLogoView

광고주 프로필 로고를 표시하는 이미지 컴포넌트입니다.
<AdropProfileLogoView style={styles.profileLogo} />
Props: ImageProps (React Native의 Image 컴포넌트 속성)

AdropProfileNameView

광고주 프로필 이름을 표시하는 텍스트 컴포넌트입니다.
<AdropProfileNameView style={styles.profileName} />
Props: TextProps (React Native의 Text 컴포넌트 속성)

AdropHeadLineView

광고 제목을 표시하는 텍스트 컴포넌트입니다.
<AdropHeadLineView style={styles.headline} />
Props: TextProps (React Native의 Text 컴포넌트 속성)

AdropBodyView

광고 본문을 표시하는 텍스트 컴포넌트입니다.
<AdropBodyView style={styles.body} />
Props: TextProps (React Native의 Text 컴포넌트 속성)

AdropMediaView

광고 이미지 또는 동영상을 표시하는 미디어 컴포넌트입니다.
<AdropMediaView style={styles.media} />
Props: ViewProps (React Native의 View 컴포넌트 속성)
백필 광고가 아닌 경우, 동영상 광고는 WebView를 사용하여 직접 렌더링해야 합니다. (구현 예제 참조)

AdropCallToActionView

행동 유도 문구(CTA)를 표시하는 텍스트 컴포넌트입니다.
<AdropCallToActionView style={styles.cta} />
Props: TextProps (React Native의 Text 컴포넌트 속성)

AdropAdvertiserView

광고주 이름을 표시하는 텍스트 컴포넌트입니다.
<AdropAdvertiserView style={styles.advertiser} />
Props: TextProps (React Native의 Text 컴포넌트 속성)

AdropIconView

광고 아이콘을 표시하는 이미지 컴포넌트입니다.
<AdropIconView style={styles.icon} />
Props: ImageProps (React Native의 Image 컴포넌트 속성)

AdropNativeAdListener 인터페이스

광고 이벤트를 처리하는 리스너 인터페이스입니다.
interface AdropNativeAdListener {
  onAdReceived?: (ad: AdropNativeAd) => void
  onAdClicked?: (ad: AdropNativeAd) => void
  onAdImpression?: (ad: AdropNativeAd) => void
  onAdFailedToReceive?: (ad: AdropNativeAd, errorCode?: any) => void
}
콜백 메서드설명
onAdReceived광고 수신 성공 시 호출됩니다
onAdClicked광고 클릭 시 호출됩니다
onAdImpression광고 노출 시 호출됩니다
onAdFailedToReceive광고 수신 실패 시 호출됩니다

AdropNativeProperties 타입

광고 속성 정보를 담는 타입입니다.
type AdropNativeProperties = {
  icon?: string                      // 아이콘 이미지 URL
  cover?: string                     // 커버 이미지 URL
  headline?: string                  // 광고 제목
  body?: string                      // 광고 본문
  creative?: string                  // 광고 소재 HTML (WebView 렌더링용)
  asset?: string                     // 에셋 정보
  destinationURL?: string            // 목적지 URL
  advertiserURL?: string             // 광고주 URL
  accountTag?: string                // 계정 태그
  creativeTag?: string               // 소재 태그
  advertiser?: string                // 광고주 이름
  callToAction?: string              // 행동 유도 문구
  profile?: AdropNativeProfile       // 프로필 정보
  extra?: Record<string, string>     // 추가 정보
  isBackfilled?: boolean             // 백필 광고 여부
}

AdropNativeProfile 타입

광고주 프로필 정보를 담는 타입입니다.
type AdropNativeProfile = {
  displayName: string                // 프로필 표시 이름
  displayLogo: string                // 프로필 로고 이미지 URL
}

구현 예제

다음은 네이티브 광고를 구현하는 전체 예제입니다.
import React, { useCallback, useEffect, useMemo, useState } from 'react'
import {
  AdropBodyView,
  AdropHeadLineView,
  AdropMediaView,
  AdropNativeAd,
  AdropNativeAdView,
  AdropProfileLogoView,
  AdropProfileNameView,
} from 'adrop-ads-react-native'
import type { AdropNativeAdListener } from 'adrop-ads-react-native'
import { WebView } from 'react-native-webview'
import {
  Button,
  Dimensions,
  ScrollView,
  StyleSheet,
  Text,
  View,
  Linking,
  Platform,
} from 'react-native'

const NativeAdExample: React.FC = () => {
  const [nativeAd, setNativeAd] = useState<AdropNativeAd>()
  const [isLoaded, setIsLoaded] = useState(false)
  const [errorCode, setErrorCode] = useState('')

  // URL 열기 핸들러
  const openUrl = useCallback((url: string) => {
    Linking.openURL(url).catch((err) =>
      console.error('Failed to open URL:', err)
    )
  }, [])

  // 광고 이벤트 리스너
  const listener = useMemo(
    (): AdropNativeAdListener => ({
      onAdReceived: (ad) => {
        console.log('광고 수신:', ad.unitId, ad.properties)
        setIsLoaded(true)
        setErrorCode('')
      },
      onAdFailedToReceive: (_, error) => {
        console.log('광고 수신 실패:', error)
        setErrorCode(error)
      },
      onAdClicked: (ad) => {
        console.log('광고 클릭:', ad.unitId)
      },
      onAdImpression: (ad) => {
        console.log('광고 노출:', ad.unitId)
      },
    }),
    []
  )

  // 광고 초기화
  const initialize = useCallback(
    (unitId: string) => {
      const adropNativeAd = new AdropNativeAd(unitId)
      adropNativeAd.listener = listener

      setNativeAd((prev) => {
        prev?.destroy()
        return adropNativeAd
      })

      setIsLoaded(false)
      setErrorCode('')
    },
    [listener]
  )

  // 컴포넌트 마운트 시 광고 초기화
  useEffect(() => {
    initialize('YOUR_UNIT_ID')

    // 컴포넌트 언마운트 시 광고 해제
    return () => {
      nativeAd?.destroy()
    }
  }, [])

  // 광고 로드
  const load = () => nativeAd?.load()

  // 광고 뷰 렌더링
  const adView = useMemo(() => {
    if (!isLoaded) return null

    return (
      <AdropNativeAdView
        nativeAd={nativeAd}
        style={{
          ...styles.adContainer,
          width: Dimensions.get('window').width,
        }}
      >
        {/* 프로필 영역 */}
        <View style={styles.rowContainer}>
          <AdropProfileLogoView style={styles.profileLogo} />
          <AdropProfileNameView style={styles.profileName} />
        </View>

        {/* 광고 제목 */}
        <AdropHeadLineView style={styles.headline} />

        {/* 광고 본문 */}
        <AdropBodyView style={styles.body} />

        {/* 미디어 영역 */}
        {nativeAd?.isBackfilled ? (
          // 백필 광고: AdropMediaView 사용
          <AdropMediaView style={styles.media} />
        ) : (
          // 일반 광고: WebView로 렌더링
          <WebView
            source={{
              html: nativeAd?.properties?.creative ?? '',
            }}
            style={styles.media}
            javaScriptEnabled={true}
            mediaPlaybackRequiresUserAction={false}
            allowsInlineMediaPlayback={true}
            scrollEnabled={false}
            onNavigationStateChange={(event) => {
              // Android WebView 이벤트
              if (
                event.url &&
                event.url !== 'about:blank' &&
                !event.url.startsWith('data:')
              ) {
                openUrl(event.url)
              }
            }}
            onOpenWindow={(event) => {
              // iOS WebView 이벤트 (window.open)
              if (event.nativeEvent?.targetUrl) {
                openUrl(event.nativeEvent.targetUrl)
              }
            }}
          />
        )}
      </AdropNativeAdView>
    )
  }, [isLoaded, nativeAd, openUrl])

  return (
    <ScrollView>
      <View style={styles.container}>
        {/* 광고 로드 버튼 */}
        <View style={styles.button}>
          <Button title="광고 로드" onPress={load} />
        </View>

        {/* 광고 뷰 */}
        {adView}

        {/* 에러 표시 */}
        {errorCode && (
          <Text style={styles.error}>
            Error: {errorCode}
          </Text>
        )}
      </View>
    </ScrollView>
  )
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    alignItems: 'center',
    paddingVertical: 5,
    paddingHorizontal: 16,
  },
  button: {
    marginVertical: 8,
  },
  adContainer: {
    paddingHorizontal: 16,
  },
  rowContainer: {
    flexDirection: 'row',
    justifyContent: 'flex-start',
    alignItems: 'center',
    marginBottom: 8,
  },
  profileLogo: {
    width: 32,
    height: 32,
    marginRight: 8,
    borderRadius: 16,
  },
  profileName: {
    fontSize: 14,
    fontWeight: 'bold',
    color: 'black',
  },
  headline: {
    fontSize: 16,
    fontWeight: 'bold',
    color: 'black',
    marginTop: 8,
  },
  body: {
    fontSize: 14,
    color: 'black',
    marginVertical: 8,
  },
  media: {
    width: '100%',
    height: 360,
    marginTop: 8,
  },
  error: {
    color: 'red',
    marginVertical: 8,
  },
})

export default NativeAdExample

테스트 유닛 ID

개발 및 테스트 시 다음 테스트 유닛 ID를 사용하세요.
플랫폼포맷테스트 유닛 ID
Android/iOS네이티브 (이미지)PUBLIC_TEST_UNIT_ID_NATIVE
Android/iOS네이티브 비디오 (16:9)PUBLIC_TEST_UNIT_ID_NATIVE_VIDEO_16_9
Android/iOS네이티브 비디오 (9:16)PUBLIC_TEST_UNIT_ID_NATIVE_VIDEO_9_16
프로덕션 배포 전에 반드시 실제 유닛 ID로 교체하세요.

에러 처리

광고 로드 실패 시 onAdFailedToReceive 콜백에서 에러 코드를 받을 수 있습니다.

주요 에러 코드

에러 코드설명
ERROR_CODE_NETWORK네트워크 오류
ERROR_CODE_INTERNAL내부 오류
ERROR_CODE_INITIALIZE초기화 오류
ERROR_CODE_INVALID_UNIT유효하지 않은 유닛 ID
ERROR_CODE_AD_NO_FILL광고 없음
ERROR_CODE_AD_LOADING광고 로딩 중

에러 처리 예제

const listener: AdropNativeAdListener = {
  onAdFailedToReceive: (ad, errorCode) => {
    switch (errorCode) {
      case 'ERROR_CODE_AD_NO_FILL':
        console.log('광고 없음 - 광고 영역 숨기기')
        break
      case 'ERROR_CODE_NETWORK':
        console.log('네트워크 오류 - 재시도')
        setTimeout(() => ad.load(), 3000)
        break
      default:
        console.log('광고 로드 실패:', errorCode)
    }
  }
}

모범 사례

1. 리소스 해제

컴포넌트 언마운트 시 반드시 광고 리소스를 해제하세요.
useEffect(() => {
  const ad = new AdropNativeAd('YOUR_UNIT_ID')
  setNativeAd(ad)

  return () => {
    ad.destroy()
  }
}, [])

2. 백필 광고 처리

백필 광고 여부에 따라 적절한 렌더링 방식을 선택하세요.
{nativeAd?.isBackfilled ? (
  <AdropMediaView style={styles.media} />
) : (
  <WebView source={{ html: nativeAd?.properties?.creative ?? '' }} />
)}

3. URL 처리

WebView에서 URL 클릭 시 외부 브라우저로 열리도록 처리하세요.
<WebView
  onNavigationStateChange={(event) => {
    if (event.url && event.url !== 'about:blank') {
      Linking.openURL(event.url)
    }
  }}
/>

4. 광고 요소 선택적 사용

앱의 디자인에 맞게 필요한 광고 요소만 선택적으로 사용하세요.
<AdropNativeAdView nativeAd={nativeAd}>
  {/* 최소 구성: 미디어와 제목만 표시 */}
  <AdropHeadLineView style={styles.headline} />
  <AdropMediaView style={styles.media} />
</AdropNativeAdView>

다음 단계