> ## Documentation Index
> Fetch the complete documentation index at: https://docs.adrop.io/llms.txt
> Use this file to discover all available pages before exploring further.

# 예제

> React Native SDK의 다양한 사용 예제를 제공합니다.

## 개요

이 문서는 Adrop React Native SDK의 실제 동작 예제를 제공합니다. 모든 예제는 TypeScript로 작성되었으며, 실제 프로젝트에서 바로 사용할 수 있습니다.

***

## 샘플 프로젝트

GitHub에서 전체 샘플 프로젝트를 확인할 수 있습니다.

<Card title="React Native 샘플 프로젝트" icon="github" href="https://github.com/OpenRhapsody/adrop-ads-react-native">
  TypeScript로 작성된 React Native 샘플 앱
</Card>

***

## 배너 광고 예제

배너 광고를 ref를 사용하여 수동으로 로드하고, 에러를 처리하는 전체 예제입니다.

<CodeGroup>
  ```typescript BannerExample.tsx theme={null}
  import React, { useMemo, useRef, useState } from 'react'
  import {
      Button,
      Dimensions,
      Platform,
      StyleSheet,
      Text,
      View,
  } from 'react-native'
  import { AdropBanner, type AdropBannerMetadata } from 'adrop-ads-react-native'

  interface IBanner {
      load: () => void
  }

  const BannerExample: React.FC = () => {
      const bannerRef = useRef<IBanner>(null)
      const emptyBannerRef = useRef<IBanner>(null)
      const [errorCode, setErrorCode] = useState('')
      const [emptyErrorCode, setEmptyErrorCode] = useState('')

      const unit = useMemo(() => {
          // 실제 배너 광고 유닛 ID를 사용하세요
          return Platform.OS === 'android'
              ? 'PUBLIC_TEST_UNIT_ID_320_50'
              : 'PUBLIC_TEST_UNIT_ID_320_50'
      }, [])

      const loadBanner = () => {
          bannerRef.current?.load()
          setErrorCode('')
      }

      const loadEmptyBanner = () => {
          emptyBannerRef.current?.load()
          setEmptyErrorCode('')
      }

      const onAdClicked = (unitId: string, metadata?: AdropBannerMetadata) =>
          console.log('배너 클릭됨', unitId, metadata)

      const onAdReceived = (unitId: string, metadata?: AdropBannerMetadata) =>
          console.log('배너 수신 성공', unitId, metadata)

      const onAdFailedToReceive = (unitId: string, error?: string) => {
          console.log('배너 수신 실패', unitId, error)
          setErrorCode(error ?? '')
      }

      const onAdImpression = (unitId: string, metadata?: AdropBannerMetadata) =>
          console.log('배너 노출됨', unitId, metadata)

      const onEmptyAdFailedToReceive = (_: string, error?: string) => {
          console.log('배너 수신 실패', _, error)
          setEmptyErrorCode(error ?? '')
      }

      const screenWidth = Dimensions.get('window').width

      return (
          <View style={styles.container}>
              <Button title={'배너 로드 (테스트 광고)'} onPress={loadBanner} />

              <AdropBanner
                  ref={bannerRef}
                  unitId={unit}
                  style={{ ...styles.banner, width: screenWidth }}
                  autoLoad={false}
                  onAdClicked={onAdClicked}
                  onAdReceived={onAdReceived}
                  onAdFailedToReceive={onAdFailedToReceive}
                  onAdImpression={onAdImpression}
              />

              {errorCode && (
                  <Text style={styles.error}>에러 코드: {errorCode}</Text>
              )}

              <View style={styles.divider} />

              <Button
                  title={'배너 로드 (빈 광고)'}
                  onPress={loadEmptyBanner}
              />

              <AdropBanner
                  ref={emptyBannerRef}
                  unitId={'TEST_UNIT_ID'}
                  style={{ ...styles.banner, width: screenWidth }}
                  autoLoad={false}
                  onAdFailedToReceive={onEmptyAdFailedToReceive}
              />

              {emptyErrorCode && (
                  <Text style={styles.error}>에러 코드: {emptyErrorCode}</Text>
              )}
          </View>
      )
  }

  export default BannerExample

  const styles = StyleSheet.create({
      container: {
          flex: 1,
          alignItems: 'center',
          marginVertical: 50,
          paddingHorizontal: 16,
      },
      banner: {
          width: '100%',
          height: 80,
          marginVertical: 4,
      },
      error: {
          marginVertical: 2,
          color: 'black',
          textAlign: 'center',
      },
      divider: {
          width: '100%',
          height: 1,
          marginVertical: 16,
          backgroundColor: 'black',
      },
  })
  ```
</CodeGroup>

### 주요 기능

* **수동 로드**: `autoLoad={false}`로 설정하고 ref를 통해 원하는 시점에 광고 로드
* **에러 처리**: `onAdFailedToReceive` 콜백으로 에러 상태 관리
* **다중 배너**: 여러 배너를 독립적으로 관리
* **플랫폼 대응**: `Platform.OS`로 플랫폼별 유닛 ID 설정

***

## 네이티브 광고 예제

네이티브 광고를 WebView와 함께 사용하고, 백필(backfill) 광고도 처리하는 예제입니다.

<CodeGroup>
  ```typescript NativeAdExample.tsx theme={null}
  import React, { useCallback, useEffect, useMemo, useState } from 'react'
  import {
      AdropBodyView,
      AdropHeadLineView,
      AdropMediaView,
      AdropNativeAd,
      AdropNativeAdView,
      AdropProfileLogoView,
      AdropProfileNameView,
  } from 'adrop-ads-react-native'
  import { WebView } from 'react-native-webview'
  import {
      Button,
      Dimensions,
      ScrollView,
      StyleSheet,
      Text,
      View,
      Linking,
      Platform,
  } from 'react-native'
  import type { AdropNativeAdListener } from 'adrop-ads-react-native'

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

      const disabledReset = !errorCode

      const unit = useMemo(() => {
          return Platform.OS === 'android'
              ? 'PUBLIC_TEST_UNIT_ID_NATIVE'
              : 'PUBLIC_TEST_UNIT_ID_NATIVE'
      }, [])

      const openUrl = useCallback((url: string) => {
          Linking.openURL(url).catch((err) =>
              console.error('URL 열기 실패:', err)
          )
      }, [])

      const listener = useMemo(
          (): AdropNativeAdListener => ({
              onAdReceived: (ad) => {
                  console.log(
                      `네이티브 광고 수신: ${ad.unitId}`,
                      ad.properties,
                      ad.txId,
                      ad.campaignId,
                      ad.creativeId
                  )
                  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) => {
              let adropNativeAd = new AdropNativeAd(unitId)
              adropNativeAd.listener = listener
              setNativeAd((prev) => {
                  prev?.destroy()
                  return adropNativeAd
              })
              setIsLoaded(false)
              setErrorCode('')
          },
          [listener]
      )

      useEffect(() => {
          initialize(unit)
      }, [initialize, unit])

      const load = () => nativeAd?.load()

      const resetTestAd = () => {
          initialize(unit)
      }

      const resetEmptyAd = () => {
          initialize('TEST_UNIT_ID')
      }

      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.icon} />
                      <AdropProfileNameView style={styles.name} />
                  </View>

                  <AdropHeadLineView style={styles.headline} />
                  <AdropBodyView style={styles.body} />

                  {!nativeAd?.isVideoAd || nativeAd?.isBackfilled ? (
                      <AdropMediaView style={styles.adStyle} />
                  ) : (
                      <WebView
                          source={{
                              html: nativeAd?.properties?.creative ?? '',
                          }}
                          style={styles.adStyle}
                          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>
                  <View style={styles.button}>
                      <Button
                          disabled={disabledReset}
                          title={'네이티브 광고 초기화 (테스트 광고)'}
                          onPress={resetTestAd}
                      />
                  </View>
                  {adView}
                  <Text style={styles.description}>
                      네이티브 광고를 초기화한 후, 로드 버튼을 클릭하면 광고가 표시됩니다.
                  </Text>
                  <View style={styles.button}>
                      <Button
                          disabled={disabledReset}
                          title={'네이티브 광고 초기화 (빈 광고)'}
                          onPress={resetEmptyAd}
                      />
                  </View>
                  <Text style={styles.description}>
                      네이티브 광고를 초기화한 후, 로드 버튼을 클릭하면 에러 콜백이 호출됩니다.
                  </Text>
                  {errorCode && (
                      <Text style={styles.error}>에러 코드: {errorCode}</Text>
                  )}
              </View>
          </ScrollView>
      )
  }

  export default NativeAdExample

  const styles = StyleSheet.create({
      container: {
          flex: 1,
          alignItems: 'center',
          paddingVertical: 5,
          paddingHorizontal: 66,
      },
      button: {
          marginVertical: 4,
      },
      description: {
          color: 'black',
          marginBottom: 24,
          paddingHorizontal: 16,
          textAlign: 'center',
      },
      error: {
          color: 'black',
          marginVertical: 2,
      },
      adContainer: {
          paddingHorizontal: 16,
      },
      adStyle: {
          width: '100%',
          height: 360,
          marginBottom: 24,
      },
      icon: {
          width: 32,
          height: 32,
          marginRight: 8,
      },
      name: {
          fontSize: 14,
          fontWeight: 'bold',
          color: 'black',
      },
      headline: {
          fontSize: 16,
          fontWeight: 'bold',
          color: 'black',
      },
      body: {
          fontSize: 14,
          color: 'black',
          marginVertical: 16,
      },
      rowContainer: {
          display: 'flex',
          flexDirection: 'row',
          justifyContent: 'flex-start',
          alignItems: 'center',
          marginBottom: 8,
      },
  })
  ```
</CodeGroup>

### 주요 기능

* **프로필 정보 표시**: `AdropProfileLogoView`와 `AdropProfileNameView`로 광고주 정보 표시
* **WebView 통합**: HTML 크리에이티브를 WebView로 렌더링
* **백필 처리**: `isBackfilled` 속성으로 백필 광고 분기 처리
* **URL 처리**: WebView의 네비게이션 이벤트를 처리하여 외부 링크 열기
* **메모리 관리**: `destroy()` 메서드로 광고 객체 정리

***

## 전면 광고 예제

Hook을 사용하여 전면 광고를 구현하는 예제입니다.

<CodeGroup>
  ```typescript InterstitialAdExample.tsx theme={null}
  import React, { useCallback, useMemo, useState } from 'react'
  import { Button, Platform, StyleSheet, Text, View } from 'react-native'
  import { useAdropInterstitialAd } from 'adrop-ads-react-native'

  const InterstitialAdExample: React.FC = () => {
      const unit = useMemo(() => {
          return Platform.OS === 'android'
              ? 'PUBLIC_TEST_UNIT_ID_INTERSTITIAL'
              : 'PUBLIC_TEST_UNIT_ID_INTERSTITIAL'
      }, [])

      const [unitId, setUnitId] = useState(unit)

      const { load, show, errorCode, reset, isLoaded, isOpened, isReady } =
          useAdropInterstitialAd(unitId)

      const disabledReset = !(isOpened || errorCode)

      const loadAd = useCallback(() => {
          if (isReady) {
              load()
          }
      }, [isReady, load])

      const resetTestAd = useCallback(() => {
          reset()
          setUnitId(unit)
      }, [reset, unit])

      const resetEmptyAd = useCallback(() => {
          reset()
          setUnitId('TEST_UNIT_ID')
      }, [reset])

      return (
          <View style={styles.container}>
              <View style={styles.button}>
                  <Button title={'전면 광고 로드'} onPress={loadAd} />
              </View>
              <View style={styles.button}>
                  <Button
                      disabled={!isLoaded}
                      title={'전면 광고 표시'}
                      onPress={show}
                  />
              </View>
              <View style={styles.button}>
                  <Button
                      disabled={disabledReset}
                      title={'전면 광고 초기화 (테스트 광고)'}
                      onPress={resetTestAd}
                  />
              </View>
              <Text style={styles.description}>
                  전면 광고를 초기화한 후, 로드 버튼을 클릭하면 광고가 로드됩니다.
              </Text>
              <View style={styles.button}>
                  <Button
                      disabled={disabledReset}
                      title={'전면 광고 초기화 (빈 광고)'}
                      onPress={resetEmptyAd}
                  />
              </View>
              <Text style={styles.description}>
                  전면 광고를 초기화한 후, 로드 버튼을 클릭하면 에러 콜백이 호출됩니다.
              </Text>
              {errorCode && (
                  <Text style={styles.error}>에러 코드: {errorCode}</Text>
              )}
          </View>
      )
  }

  export default InterstitialAdExample

  const styles = StyleSheet.create({
      container: {
          flex: 1,
          alignItems: 'center',
          marginVertical: 50,
      },
      button: {
          marginVertical: 4,
      },
      description: {
          color: 'black',
          marginBottom: 24,
          paddingHorizontal: 16,
          textAlign: 'center',
      },
      error: {
          color: 'black',
          marginVertical: 2,
      },
  })
  ```
</CodeGroup>

### 주요 기능

* **Hook 사용**: `useAdropInterstitialAd` Hook으로 간편한 상태 관리
* **상태 확인**: `isLoaded`, `isOpened`, `isReady` 상태로 광고 상태 추적
* **에러 처리**: `errorCode`로 에러 상태 확인
* **초기화**: `reset()` 메서드로 광고 초기화

<Note>
  전면 광고는 화면 전체를 덮기 때문에, 사용자 경험을 고려하여 적절한 타이밍에 표시하는 것이 중요합니다.
</Note>

***

## 보상형 광고 예제

Hook을 사용하여 보상형 광고를 구현하는 예제입니다.

<CodeGroup>
  ```typescript RewardedAdExample.tsx theme={null}
  import React, { useCallback, useMemo, useState } from 'react'
  import { Button, Platform, StyleSheet, Text, View } from 'react-native'
  import { useAdropRewardedAd } from 'adrop-ads-react-native'

  const RewardedAdExample: React.FC = () => {
      const unit = useMemo(() => {
          return Platform.OS === 'android'
              ? 'PUBLIC_TEST_UNIT_ID_REWARDED'
              : 'PUBLIC_TEST_UNIT_ID_REWARDED'
      }, [])

      const [unitId, setUnitId] = useState(unit)

      const { load, show, errorCode, reset, isLoaded, isOpened, isReady } =
          useAdropRewardedAd(unitId)

      const disabledReset = !(isOpened || errorCode)

      const loadAd = useCallback(() => {
          if (isReady) {
              load()
          }
      }, [isReady, load])

      const resetTestAd = useCallback(() => {
          reset()
          setUnitId(unit)
      }, [reset, unit])

      const resetEmptyAd = useCallback(() => {
          reset()
          setUnitId('TEST_UNIT_ID')
      }, [reset])

      return (
          <View style={styles.container}>
              <View style={styles.button}>
                  <Button title={'보상형 광고 로드'} onPress={loadAd} />
              </View>
              <View style={styles.button}>
                  <Button
                      disabled={!isLoaded}
                      title={'보상형 광고 표시'}
                      onPress={show}
                  />
              </View>
              <View style={styles.button}>
                  <Button
                      disabled={disabledReset}
                      title={'보상형 광고 초기화 (테스트 광고)'}
                      onPress={resetTestAd}
                  />
              </View>
              <Text style={styles.description}>
                  보상형 광고를 초기화한 후, 로드 버튼을 클릭하면 광고가 로드됩니다.
              </Text>
              <View style={styles.button}>
                  <Button
                      disabled={disabledReset}
                      title={'보상형 광고 초기화 (빈 광고)'}
                      onPress={resetEmptyAd}
                  />
              </View>
              <Text style={styles.description}>
                  보상형 광고를 초기화한 후, 로드 버튼을 클릭하면 에러 콜백이 호출됩니다.
              </Text>
              {errorCode && (
                  <Text style={styles.error}>에러 코드: {errorCode}</Text>
              )}
          </View>
      )
  }

  export default RewardedAdExample

  const styles = StyleSheet.create({
      container: {
          flex: 1,
          alignItems: 'center',
          marginVertical: 50,
      },
      button: {
          marginVertical: 4,
      },
      description: {
          color: 'black',
          marginBottom: 24,
          paddingHorizontal: 16,
          textAlign: 'center',
      },
      error: {
          color: 'black',
          marginVertical: 2,
      },
  })
  ```
</CodeGroup>

### 주요 기능

* **Hook 사용**: `useAdropRewardedAd` Hook으로 간편한 상태 관리
* **보상 처리**: 리스너를 통해 보상 지급 시점 확인 (리스너 설정 방법은 [보상형 광고 가이드](/ko/sdk/react-native/rewarded) 참조)
* **상태 관리**: `isLoaded`, `isOpened`, `isReady`로 광고 상태 확인

<Warning>
  보상형 광고는 사용자가 광고를 끝까지 시청해야 보상이 지급됩니다. `onAdEarnRewardHandler` 콜백에서만 보상을 지급하세요.
</Warning>

***

## 팝업 광고 예제

클래스를 사용하여 팝업 광고를 구현하고 커스터마이징하는 예제입니다.

<CodeGroup>
  ```typescript PopupAdExample.tsx theme={null}
  import React, { useCallback, useEffect, useMemo, useState } from 'react'
  import { Button, Platform, StyleSheet, Text, View } from 'react-native'
  import {
      type AdropListener,
      AdropPopupAd,
      type AdropPopupAdColors,
  } from 'adrop-ads-react-native'

  const PopupAdExample: React.FC = () => {
      const [popupAd, setPopupAd] = useState<AdropPopupAd>()
      const [isLoaded, setIsLoaded] = useState(false)
      const [isShown, setIsShown] = useState(false)
      const [errorCode, setErrorCode] = useState('')

      const disabledReset = !(errorCode || isShown)

      const unit = useMemo(() => {
          return Platform.OS === 'android'
              ? 'PUBLIC_TEST_UNIT_ID_POPUP_BOTTOM'
              : 'PUBLIC_TEST_UNIT_ID_POPUP_BOTTOM'
      }, [])

      const listener: AdropListener = useMemo(() => {
          return {
              onAdImpression: (ad: AdropPopupAd) =>
                  console.log(
                      `팝업 광고 노출: ${ad.unitId}, ${ad.creativeId}, ${
                          ad.txId
                      }, ${ad.campaignId} ${ad.destinationURL}`
                  ),
              onAdClicked: (ad: AdropPopupAd) => {
                  console.log(
                      `팝업 광고 클릭: ${ad.unitId}, ${ad.destinationURL}`
                  )
                  ad.close()
              },
              onAdReceived: (ad: AdropPopupAd) => {
                  setIsLoaded(true)
                  console.log(`팝업 광고 수신: ${ad.unitId}`)
                  setErrorCode('')
              },
              onAdFailedToReceive: (_: AdropPopupAd, error: any) => {
                  console.log('팝업 광고 수신 실패', error)
                  setErrorCode(error)
              },
              onAdDidDismissFullScreen: (ad: AdropPopupAd) =>
                  console.log(`팝업 광고 닫힘: ${ad.unitId}`),
              onAdDidPresentFullScreen: (ad: AdropPopupAd) =>
                  console.log(`팝업 광고 표시됨: ${ad.unitId}`),
              onAdFailedToShowFullScreen: (_: AdropPopupAd, error: any) =>
                  setErrorCode(error),
          } as AdropListener
      }, [])

      useEffect(() => {
          return () => {
              popupAd?.destroy()
          }
      }, [popupAd])

      const initialize = useCallback(
          (unitId: string) => {
              // 팝업 광고 색상 커스터마이징
              let hideForTodayTextColor = '#456'
              let backgroundColor = 'rgba(53, 255, 63, 0.3)'
              let customColors: AdropPopupAdColors = {
                  hideForTodayTextColor,
                  backgroundColor,
              }

              let adropPopupAd = new AdropPopupAd(unitId, customColors)
              adropPopupAd.listener = listener
              setPopupAd((prev) => {
                  prev?.destroy()
                  return adropPopupAd
              })
          },
          [listener]
      )

      useEffect(() => {
          initialize(unit)
      }, [initialize, unit])

      const load = () => popupAd?.load()
      const show = () => {
          popupAd?.show()
          setIsShown(true)
      }
      const resetTestAd = () => {
          initialize(unit)
          resetState()
      }

      const resetEmptyAd = () => {
          initialize('TEST_UNIT_ID')
          resetState()
      }

      const resetState = () => {
          setIsLoaded(false)
          setIsShown(false)
          setErrorCode('')
      }

      return (
          <View style={styles.container}>
              <View style={styles.button}>
                  <Button title={'팝업 광고 로드'} onPress={load} />
              </View>
              <View style={styles.button}>
                  <Button
                      disabled={!isLoaded}
                      title={'팝업 광고 표시'}
                      onPress={show}
                  />
              </View>
              <View style={styles.button}>
                  <Button
                      disabled={disabledReset}
                      title={'팝업 광고 초기화 (테스트 광고)'}
                      onPress={resetTestAd}
                  />
              </View>
              <Text style={styles.description}>
                  팝업 광고를 초기화한 후, 로드 버튼을 클릭하면 광고가 로드됩니다.
              </Text>
              <View style={styles.button}>
                  <Button
                      disabled={disabledReset}
                      title={'팝업 광고 초기화 (빈 광고)'}
                      onPress={resetEmptyAd}
                  />
              </View>
              <Text style={styles.description}>
                  팝업 광고를 초기화한 후, 로드 버튼을 클릭하면 에러 콜백이 호출됩니다.
              </Text>
              {errorCode && (
                  <Text style={styles.error}>에러 코드: {errorCode}</Text>
              )}
          </View>
      )
  }

  export default PopupAdExample

  const styles = StyleSheet.create({
      container: {
          flex: 1,
          alignItems: 'center',
          marginVertical: 50,
      },
      button: {
          marginVertical: 4,
      },
      description: {
          color: 'black',
          marginBottom: 24,
          paddingHorizontal: 16,
          textAlign: 'center',
      },
      error: {
          color: 'black',
          marginVertical: 2,
      },
  })
  ```
</CodeGroup>

### 주요 기능

* **클래스 기반**: `AdropPopupAd` 클래스 직접 사용
* **색상 커스터마이징**: `AdropPopupAdColors`로 팝업 스타일 설정
* **클릭 시 닫기**: `onAdClicked`에서 `ad.close()` 호출
* **메모리 관리**: `useEffect` cleanup에서 `destroy()` 호출

***

## 타겟팅 설정 예제

광고 타겟팅을 설정하는 예제입니다.

<CodeGroup>
  ```typescript TargetingExample.tsx theme={null}
  import React, { useEffect } from 'react'
  import { View } from 'react-native'
  import { AdropMetrics, AdropProperties, AdropGender } from 'adrop-ads-react-native'

  const TargetingExample: React.FC = () => {
      useEffect(() => {
          // 사용자 성별 설정
          AdropMetrics.setProperty(AdropProperties.GENDER, AdropGender.MALE)

          // 사용자 나이 설정
          AdropMetrics.setProperty(AdropProperties.AGE, 25)

          // 사용자 생년월일 설정
          AdropMetrics.setProperty(AdropProperties.BIRTH, '19980520')

          // 커스텀 속성 설정 (문자열)
          AdropMetrics.setProperty('customKey', 'customValue')

          // 커스텀 속성 설정 (숫자)
          AdropMetrics.setProperty('level', 10)

          // 커스텀 속성 설정 (불린)
          AdropMetrics.setProperty('isPremium', true)

          // 이벤트 전송
          AdropMetrics.sendEvent('purchase', {
              item_id: 'SKU-001',
              price: 29900,
              currency: 'KRW',
          })
      }, [])

      return <View />
  }

  export default TargetingExample
  ```
</CodeGroup>

### 사용 가능한 타겟팅 속성

| 속성                       | 타입                            | 설명                                            |
| ------------------------ | ----------------------------- | --------------------------------------------- |
| `AdropProperties.GENDER` | `AdropGender`                 | 사용자 성별 (`MALE`, `FEMALE`, `OTHER`, `UNKNOWN`) |
| `AdropProperties.AGE`    | `number`                      | 사용자 나이                                        |
| `AdropProperties.BIRTH`  | `string`                      | 사용자 생년월일 (yyyyMMdd)                           |
| 커스텀 키                    | `string \| number \| boolean` | 앱에서 정의한 커스텀 속성                                |

<Note>
  타겟팅 속성은 광고 요청 시 서버로 전송되어 더 관련성 높은 광고를 표시하는 데 사용됩니다.
</Note>

***

## 에러 처리 유틸리티

에러 코드를 사람이 읽을 수 있는 메시지로 변환하는 유틸리티 예제입니다.

<CodeGroup>
  ```typescript ErrorUtils.ts theme={null}
  import { AdropErrorCode } from 'adrop-ads-react-native'

  export const descriptionOf = (errorCode: string): string => {
      switch (errorCode) {
          case AdropErrorCode.network:
              return '네트워크 상태가 불안정합니다'
          case AdropErrorCode.internal:
              return 'SDK 내부 오류가 발생했습니다'
          case AdropErrorCode.initialize:
              return 'Adrop을 먼저 초기화해야 합니다'
          case AdropErrorCode.invalidUnit:
              return '광고 유닛 ID가 유효하지 않습니다'
          case AdropErrorCode.notTargetCountry:
              return '지원되지 않는 국가에서는 SDK를 사용할 수 없습니다'
          case AdropErrorCode.inactive:
              return '활성화된 광고 캠페인이 없습니다'
          case AdropErrorCode.adNoFill:
              return '조건에 맞는 광고를 받을 수 없습니다. 다시 시도해주세요'
          case AdropErrorCode.adDuplicated:
              return '광고 수신 후에는 다시 로드할 수 없습니다'
          case AdropErrorCode.adLoading:
              return '광고 요청 후 서버 응답을 대기 중입니다'
          case AdropErrorCode.adEmpty:
              return '수신된 광고가 없습니다'
          case AdropErrorCode.adShown:
              return '이 광고는 이미 표시되었습니다'
          case AdropErrorCode.adHideForToday:
              return '오늘은 더 이상 로드할 수 없습니다'
          case AdropErrorCode.adLandscapeUnsupported:
              return '가로 모드에서는 광고를 표시할 수 없습니다'
          case AdropErrorCode.backfillNoFill:
              return '백필 광고를 받을 수 없습니다'
          case AdropErrorCode.undefined:
              return '정의되지 않은 오류입니다'
          default:
              return ''
      }
  }
  ```

  ```typescript 사용 예제 theme={null}
  import { descriptionOf } from './ErrorUtils'

  const handleAdFailedToReceive = (unitId: string, errorCode?: string) => {
      if (errorCode) {
          const errorMessage = descriptionOf(errorCode)
          console.log('에러:', errorMessage)
          Alert.alert('광고 로드 실패', errorMessage)
      }
  }
  ```
</CodeGroup>

### 에러 코드 목록

| 에러 코드                    | 설명              |
| ------------------------ | --------------- |
| `network`                | 네트워크 연결 문제      |
| `internal`               | SDK 내부 오류       |
| `initialize`             | SDK 초기화 필요      |
| `invalidUnit`            | 잘못된 유닛 ID       |
| `notTargetCountry`       | 지원되지 않는 국가      |
| `inactive`               | 활성 캠페인 없음       |
| `adNoFill`               | 광고 없음           |
| `adDuplicated`           | 중복 로드 시도        |
| `adLoading`              | 광고 로딩 중         |
| `adEmpty`                | 광고 미수신          |
| `adShown`                | 이미 표시된 광고       |
| `adHideForToday`         | 오늘 하루 보지 않기 선택됨 |
| `adLandscapeUnsupported` | 가로 모드 미지원       |
| `backfillNoFill`         | 백필 광고 없음        |

***

## 전체 통합 예제

모든 광고 형식을 하나의 앱에서 사용하는 예제입니다.

<CodeGroup>
  ```typescript App.tsx theme={null}
  import React, { useEffect } from 'react'
  import { NavigationContainer } from '@react-navigation/native'
  import { createBottomTabNavigator } from '@react-navigation/bottom-tabs'
  import { Adrop } from 'adrop-ads-react-native'
  import BannerExample from './views/BannerExample'
  import NativeAdExample from './views/NativeAdExample'
  import InterstitialAdExample from './views/InterstitialAdExample'
  import RewardedAdExample from './views/RewardedAdExample'
  import PopupAdExample from './views/PopupAdExample'

  const Tab = createBottomTabNavigator()

  const App = () => {
      useEffect(() => {
          // Adrop SDK 초기화
          Adrop.initialize(false) // 테스트 모드: false, 프로덕션: true
      }, [])

      return (
          <NavigationContainer>
              <Tab.Navigator>
                  <Tab.Screen
                      name="배너"
                      component={BannerExample}
                  />
                  <Tab.Screen
                      name="네이티브"
                      component={NativeAdExample}
                  />
                  <Tab.Screen
                      name="전면"
                      component={InterstitialAdExample}
                  />
                  <Tab.Screen
                      name="리워드"
                      component={RewardedAdExample}
                  />
                  <Tab.Screen
                      name="팝업"
                      component={PopupAdExample}
                  />
              </Tab.Navigator>
          </NavigationContainer>
      )
  }

  export default App
  ```
</CodeGroup>

***

## 모범 사례

### 1. 메모리 관리

광고 객체는 사용 후 반드시 정리하세요.

```typescript theme={null}
useEffect(() => {
    const nativeAd = new AdropNativeAd('YOUR_UNIT_ID')

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

### 2. 에러 핸들링

모든 광고 로드 시 에러 처리를 구현하세요.

```typescript theme={null}
const [error, setError] = useState<string | null>(null)

const handleAdFailedToReceive = (unitId: string, errorCode?: string) => {
    setError(errorCode ?? '알 수 없는 오류')
    // 에러 로깅, 대체 콘텐츠 표시 등
}
```

### 3. 상태 관리

Hook을 사용하여 광고 상태를 추적하세요.

```typescript theme={null}
const { isLoaded, isOpened, isReady, errorCode } = useAdropInterstitialAd(unitId)

// 버튼 비활성화
<Button
    disabled={!isLoaded}
    title="광고 표시"
    onPress={show}
/>
```

### 4. 플랫폼 분기

플랫폼별로 다른 유닛 ID를 사용하세요.

```typescript theme={null}
const unitId = useMemo(() => {
    return Platform.OS === 'android'
        ? 'ANDROID_UNIT_ID'
        : 'IOS_UNIT_ID'
}, [])
```

### 5. 테스트 유닛 ID 사용

개발 및 테스트 시에는 항상 테스트 유닛 ID를 사용하세요.

```typescript theme={null}
const isProduction = false

const unitId = isProduction
    ? 'YOUR_PRODUCTION_UNIT_ID'
    : 'PUBLIC_TEST_UNIT_ID_320_50'
```

***

## 다음 단계

<CardGroup cols={2}>
  <Card title="API 레퍼런스" href="/ko/sdk/react-native/reference">
    전체 API 문서 확인하기
  </Card>

  <Card title="배너 광고" href="/ko/sdk/react-native/banner">
    배너 광고 상세 가이드
  </Card>

  <Card title="네이티브 광고" href="/ko/sdk/react-native/native">
    네이티브 광고 상세 가이드
  </Card>

  <Card title="전면 광고" href="/ko/sdk/react-native/interstitial">
    전면 광고 상세 가이드
  </Card>
</CardGroup>
