> ## 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 앱에서 보상형 광고를 구현하는 방법을 안내합니다.

## 개요

보상형 광고는 사용자가 동영상 광고를 끝까지 시청하면 게임 내 재화, 생명, 힌트 등의 보상을 제공하는 전면 동영상 광고입니다.

### 주요 특징

* 전면 화면을 차지하는 동영상 광고
* 사용자가 광고를 완전히 시청한 경우에만 보상 제공
* 사용자가 직접 광고 시청을 선택 (예: "동영상 보고 생명 받기" 버튼)
* 보상 타입과 수량을 설정 가능

<Note>
  개발 환경에서는 테스트 유닛 ID를 사용하세요.
</Note>

***

## 구현 방법

보상형 광고는 두 가지 방식으로 구현할 수 있습니다:

1. **클래스 방식** - `AdropRewardedAd` 클래스를 직접 사용
2. **Hook 방식** - `useAdropRewardedAd` Hook을 사용 (권장)

***

## Hook 방식 구현 (권장)

React Hook을 사용하여 더 간결하고 React스러운 방식으로 구현할 수 있습니다.

### 기본 예제

```tsx theme={null}
import React, { useCallback } from 'react';
import { Button, View, Text, StyleSheet } from 'react-native';
import { useAdropRewardedAd } from 'adrop-ads-react-native';

const RewardedAdScreen = () => {
  const unitId = 'YOUR_UNIT_ID'; // 또는 테스트 유닛 ID

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

  // 컴포넌트 마운트 시 광고 로드
  React.useEffect(() => {
    if (isReady) {
      load();
    }
  }, [isReady, load]);

  // 광고가 닫힌 후 다음 광고 로드
  React.useEffect(() => {
    if (isClosed) {
      console.log('광고가 닫혔습니다');
      // 다음 광고 미리 로드
      reset();
      load();
    }
  }, [isClosed, reset, load]);

  // 보상 처리
  React.useEffect(() => {
    if (isEarnRewarded && reward) {
      console.log(`보상 획득 - 타입: ${reward.type}, 수량: ${reward.amount}`);
      grantReward(reward.type, reward.amount);
    }
  }, [isEarnRewarded, reward]);

  const handleShowAd = useCallback(() => {
    if (isLoaded) {
      show();
    } else {
      console.log('광고가 아직 로드되지 않았습니다');
    }
  }, [isLoaded, show]);

  const grantReward = (type: number, amount: number) => {
    // 사용자에게 보상 지급
    console.log(`보상 지급: 타입=${type}, 수량=${amount}`);
    // 실제 보상 지급 로직 구현
  };

  return (
    <View style={styles.container}>
      <Button
        title="광고 로드"
        onPress={load}
        disabled={!isReady}
      />
      <Button
        title="광고 보기"
        onPress={handleShowAd}
        disabled={!isLoaded}
      />
      {errorCode && (
        <Text style={styles.error}>에러: {errorCode}</Text>
      )}
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    gap: 16,
  },
  error: {
    color: 'red',
  },
});

export default RewardedAdScreen;
```

### useAdropRewardedAd Hook

Hook을 사용하면 광고 상태를 자동으로 관리할 수 있습니다.

#### 파라미터

<ParamField path="unitId" type="string | null">
  애드컨트롤 콘솔에서 발급받은 광고 유닛 ID. `null`을 전달하면 광고 인스턴스가 생성되지 않습니다.
</ParamField>

#### 반환값

<ParamField path="load" type="() => void">
  광고를 요청합니다.
</ParamField>

<ParamField path="show" type="() => void">
  광고를 표시합니다.
</ParamField>

<ParamField path="reset" type="() => void">
  광고 상태를 초기화하고 새로운 광고 인스턴스를 생성합니다.
</ParamField>

<ParamField path="isLoaded" type="boolean">
  광고가 로드되어 표시 가능한 상태인지 여부
</ParamField>

<ParamField path="isOpened" type="boolean">
  광고가 화면에 표시되었는지 여부
</ParamField>

<ParamField path="isClosed" type="boolean">
  광고가 닫혔는지 여부
</ParamField>

<ParamField path="isEarnRewarded" type="boolean">
  사용자가 보상을 획득했는지 여부
</ParamField>

<ParamField path="reward" type="{ type: number, amount: number } | undefined">
  보상 정보 (타입과 수량)
</ParamField>

<ParamField path="errorCode" type="string | undefined">
  에러 코드 (에러 발생 시에만 값이 있음)
</ParamField>

<ParamField path="isReady" type="boolean">
  광고 인스턴스가 준비되어 사용 가능한 상태인지 여부
</ParamField>

<ParamField path="isClicked" type="boolean">
  광고가 클릭되었는지 여부
</ParamField>

<ParamField path="isBackPressed" type="boolean">
  광고가 표시된 상태에서 뒤로 가기 버튼이 눌렸는지 여부. **Android 전용.**
</ParamField>

<ParamField path="browserTarget" type="BrowserTarget | undefined">
  로드된 광고의 브라우저 타겟 설정 (`BrowserTarget.EXTERNAL` 또는 `BrowserTarget.INTERNAL`).
</ParamField>

***

## 클래스 방식 구현

`AdropRewardedAd` 클래스를 직접 사용하여 광고를 구현할 수 있습니다.

### 기본 예제

```tsx theme={null}
import React, { useEffect, useState, useCallback } from 'react';
import { Button, View, Text, StyleSheet } from 'react-native';
import { AdropRewardedAd, AdropListener } from 'adrop-ads-react-native';

const RewardedAdScreen = () => {
  const [rewardedAd, setRewardedAd] = useState<AdropRewardedAd | null>(null);
  const [isLoaded, setIsLoaded] = useState(false);

  useEffect(() => {
    // 1. AdropRewardedAd 인스턴스 생성
    const ad = new AdropRewardedAd('YOUR_UNIT_ID');

    // 2. Listener 설정
    const listener: AdropListener = {
      onAdReceived: (ad) => {
        console.log('광고 수신 완료:', ad.unitId);
        setIsLoaded(true);
      },
      onAdFailedToReceive: (ad, errorCode) => {
        console.log('광고 수신 실패:', errorCode);
        setIsLoaded(false);
      },
      onAdDidPresentFullScreen: (ad) => {
        console.log('광고 화면 표시됨:', ad.unitId);
      },
      onAdDidDismissFullScreen: (ad) => {
        console.log('광고 화면 닫힘:', ad.unitId);
        setIsLoaded(false);
        // 다음 광고 미리 로드
        ad.load();
      },
      onAdEarnRewardHandler: (ad, type, amount) => {
        console.log(`보상 획득 - 타입: ${type}, 수량: ${amount}`);
        grantReward(type, amount);
      },
      onAdClicked: (ad) => {
        console.log('광고 클릭됨:', ad.unitId);
      },
      onAdImpression: (ad) => {
        console.log('광고 노출됨:', ad.unitId);
      },
      onAdFailedToShowFullScreen: (ad, errorCode) => {
        console.log('광고 표시 실패:', errorCode);
      },
    };

    ad.listener = listener;
    setRewardedAd(ad);

    // 3. 광고 로드
    ad.load();

    // 컴포넌트 언마운트 시 정리
    return () => {
      ad.destroy();
    };
  }, []);

  const handleShowAd = useCallback(() => {
    if (rewardedAd && isLoaded) {
      rewardedAd.show();
    } else {
      console.log('광고가 아직 로드되지 않았습니다');
    }
  }, [rewardedAd, isLoaded]);

  const grantReward = (type: number, amount: number) => {
    // 사용자에게 보상 지급
    console.log(`보상 지급: 타입=${type}, 수량=${amount}`);
    // 실제 보상 지급 로직 구현
  };

  return (
    <View style={styles.container}>
      <Button
        title="광고 로드"
        onPress={() => rewardedAd?.load()}
      />
      <Button
        title="광고 보기"
        onPress={handleShowAd}
        disabled={!isLoaded}
      />
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    gap: 16,
  },
});

export default RewardedAdScreen;
```

### AdropRewardedAd 클래스

#### 생성자

```typescript theme={null}
new AdropRewardedAd(unitId: string)
```

<ParamField path="unitId" type="string">
  애드컨트롤 콘솔에서 발급받은 광고 유닛 ID
</ParamField>

#### 프로퍼티

<ParamField path="unitId" type="string">
  광고 유닛 ID (읽기 전용)
</ParamField>

<ParamField path="isLoaded" type="boolean">
  광고가 로드되어 표시 가능한 상태인지 여부 (읽기 전용)
</ParamField>

<ParamField path="creativeId" type="string">
  로드된 광고의 크리에이티브 ID (읽기 전용)
</ParamField>

<ParamField path="txId" type="string">
  광고 트랜잭션 ID (읽기 전용)
</ParamField>

<ParamField path="campaignId" type="string">
  로드된 광고의 캠페인 ID (읽기 전용)
</ParamField>

<ParamField path="destinationURL" type="string">
  로드된 광고의 랜딩 URL (읽기 전용)
</ParamField>

<ParamField path="browserTarget" type="BrowserTarget">
  로드된 광고의 브라우저 타겟 설정 (`BrowserTarget.EXTERNAL` 또는 `BrowserTarget.INTERNAL`) (읽기 전용)
</ParamField>

<ParamField path="listener" type="AdropListener | undefined">
  광고 이벤트를 수신할 리스너
</ParamField>

#### 메서드

<ParamField path="load()" type="void">
  광고를 요청합니다. 광고 로드 결과는 리스너의 `onAdReceived` 또는 `onAdFailedToReceive`로 전달됩니다.
</ParamField>

<ParamField path="show()" type="void">
  광고를 표시합니다.
</ParamField>

<ParamField path="destroy()" type="void">
  광고 리소스를 해제합니다. 컴포넌트 언마운트 시 호출해야 합니다.
</ParamField>

***

## AdropListener 인터페이스

모든 콜백은 선택 사항입니다. 필요한 콜백만 설정하세요.

### 콜백

<ParamField path="onAdReceived(ad: AdropAd)" type="void">
  광고 수신에 성공했을 때 호출됩니다. 이 시점부터 `show()` 메서드로 광고를 표시할 수 있습니다.
</ParamField>

<ParamField path="onAdFailedToReceive(ad: AdropAd, errorCode?: any)" type="void">
  광고 수신에 실패했을 때 호출됩니다. 에러 코드를 통해 실패 원인을 확인할 수 있습니다.
</ParamField>

<ParamField path="onAdImpression(ad: AdropAd)" type="void">
  광고가 노출되어 노출 기록이 전송되었을 때 호출됩니다.
</ParamField>

<ParamField path="onAdClicked(ad: AdropAd)" type="void">
  사용자가 광고를 클릭했을 때 호출됩니다.
</ParamField>

<ParamField path="onAdWillPresentFullScreen(ad: AdropAd)" type="void">
  광고 화면이 표시되기 직전에 호출됩니다.
</ParamField>

<ParamField path="onAdDidPresentFullScreen(ad: AdropAd)" type="void">
  광고 화면이 완전히 표시된 후 호출됩니다.
</ParamField>

<ParamField path="onAdWillDismissFullScreen(ad: AdropAd)" type="void">
  광고 화면이 닫히기 직전에 호출됩니다.
</ParamField>

<ParamField path="onAdDidDismissFullScreen(ad: AdropAd)" type="void">
  광고 화면이 완전히 닫힌 후 호출됩니다. 다음 광고를 미리 로드할 수 있습니다.
</ParamField>

<ParamField path="onAdFailedToShowFullScreen(ad: AdropAd, errorCode?: any)" type="void">
  광고 표시에 실패했을 때 호출됩니다. 에러 코드를 통해 실패 원인을 확인할 수 있습니다.
</ParamField>

<ParamField path="onAdBackButtonPressed(ad: AdropAd)" type="void">
  광고가 표시된 상태에서 사용자가 뒤로 가기 버튼을 눌렀을 때 호출됩니다. **Android 전용.**
</ParamField>

### 리워드 전용 콜백

<ParamField path="onAdEarnRewardHandler(ad: AdropAd, type: number, amount: number)" type="void">
  사용자가 광고를 끝까지 시청하여 보상을 획득했을 때 호출됩니다.

  * `type`: 애드컨트롤 콘솔에서 설정한 보상 타입 (정수 값)
  * `amount`: 애드컨트롤 콘솔에서 설정한 보상 수량 (정수 값)
</ParamField>

***

## 보상 처리

### Hook 방식에서 보상 처리

```tsx theme={null}
const RewardedAdScreen = () => {
  const { isEarnRewarded, reward } = useAdropRewardedAd('YOUR_UNIT_ID');

  useEffect(() => {
    if (isEarnRewarded && reward) {
      // 보상 지급 처리
      console.log(`보상 획득 - 타입: ${reward.type}, 수량: ${reward.amount}`);
      grantReward(reward.type, reward.amount);
    }
  }, [isEarnRewarded, reward]);

  const grantReward = (type: number, amount: number) => {
    // 사용자에게 보상 지급
    // 예: 게임 재화 추가, 생명 회복 등
  };

  // ...
};
```

### 클래스 방식에서 보상 처리

```tsx theme={null}
const listener: AdropListener = {
  onAdEarnRewardHandler: (ad, type, amount) => {
    console.log(`보상 획득 - 타입: ${type}, 수량: ${amount}`);
    grantReward(type, amount);
  },
  // 기타 콜백들...
};

const grantReward = (type: number, amount: number) => {
  // 사용자에게 보상 지급
  // 예: 게임 재화 추가, 생명 회복 등
};
```

## 서버 측 검증

서버에서 보상 지급을 검증하여 부정 행위를 방지할 수 있습니다. `setServerSideVerificationOptions()`를 사용하여 서버 측 검증 콜백에 포함될 사용자 및 커스텀 데이터를 전달합니다.

<Note>
  서버에서 SSV 콜백을 수신하려면 콘솔 **\[관리] > \[연동] > 리워드 광고 SSV**에서 콜백 URL을 등록해야 해요. 여기서 설정한 `userId`와 `customData`는 해당 URL로 전송되는 암호화 페이로드에 포함됩니다. 페이로드 복호화 및 설정 방법은 [리워드 광고 SSV 가이드](/ko/integrations/ssv)를 참고하세요.
</Note>

### 설정

```tsx theme={null}
import { AdropRewardedAd } from 'adrop-ads-react-native'

const rewardedAd = new AdropRewardedAd('YOUR_UNIT_ID')

// 광고를 표시하기 전에 서버 측 검증 옵션 설정
rewardedAd.setServerSideVerificationOptions({
  userId: 'user_12345',
  customData: 'extra_info',
})

rewardedAd.listener = {
  onAdReceived: (ad) => {
    ad.show()
  },
  onAdEarnRewardHandler: (ad, type, amount) => {
    // 클라이언트 측 콜백 (선택사항)
    // 서버 측 검증 콜백도 전송됩니다
    console.log(`보상 획득: type=${type}, amount=${amount}`)
  },
}

rewardedAd.load()
```

### ServerSideVerificationOptions

```typescript theme={null}
type ServerSideVerificationOptions = {
  userId?: string
  customData?: string
}
```

**속성:**

* `userId` (string, optional): 서버 콜백에 전송되는 사용자 식별자
* `customData` (string, optional): 서버 콜백에 전송되는 커스텀 데이터

<Note>
  `setServerSideVerificationOptions()`는 `load()` 전에 호출해야 합니다. 옵션은 사용자가 보상을 획득할 때 서버로 전송됩니다.
</Note>

***

## 테스트

### 테스트 유닛 ID

개발 중에는 항상 테스트 유닛 ID를 사용하세요. 실제 유닛 ID로 테스트하면 무효 트래픽으로 간주되어 계정이 정지될 수 있습니다.

```tsx theme={null}
// Hook 방식
const unitId = __DEV__ ? 'TEST_UNIT_ID' : 'YOUR_PRODUCTION_UNIT_ID';
const rewardedAd = useAdropRewardedAd(unitId);

// 클래스 방식
const unitId = __DEV__ ? 'TEST_UNIT_ID' : 'YOUR_PRODUCTION_UNIT_ID';
const ad = new AdropRewardedAd(unitId);
```

***

## 에러 처리

### Hook 방식에서 에러 처리

```tsx theme={null}
const RewardedAdScreen = () => {
  const { load, errorCode, reset } = useAdropRewardedAd('YOUR_UNIT_ID');

  useEffect(() => {
    if (errorCode) {
      console.log('광고 에러:', errorCode);
      // 에러 타입에 따른 처리
      if (errorCode === AdropErrorCode.network) {
        // 네트워크 에러: 재시도
        setTimeout(() => {
          reset();
          load();
        }, 3000);
      }
    }
  }, [errorCode, reset, load]);

  // ...
};
```

### 클래스 방식에서 에러 처리

```tsx theme={null}
const listener: AdropListener = {
  onAdFailedToReceive: (ad, errorCode) => {
    console.log('광고 수신 실패:', errorCode);
    if (errorCode === AdropErrorCode.network) {
      // 네트워크 에러: 3초 후 재시도
      setTimeout(() => {
        ad.load();
      }, 3000);
    }
  },
  onAdFailedToShowFullScreen: (ad, errorCode) => {
    console.log('광고 표시 실패:', errorCode);
    Alert.alert('알림', '광고를 표시할 수 없습니다. 나중에 다시 시도해주세요.');
  },
  // 기타 콜백들...
};
```

***

## 모범 사례

### 1. 광고 미리 로드하기

사용자 경험을 위해 광고를 미리 로드해두는 것이 좋습니다.

```tsx theme={null}
// Hook 방식
const RewardedAdScreen = () => {
  const { load, isClosed, reset, isReady } = useAdropRewardedAd('YOUR_UNIT_ID');

  // 컴포넌트 마운트 시 광고 로드
  useEffect(() => {
    if (isReady) {
      load();
    }
  }, [isReady, load]);

  // 광고가 닫힌 후 다음 광고 미리 로드
  useEffect(() => {
    if (isClosed) {
      reset();
      load();
    }
  }, [isClosed, reset, load]);

  // ...
};
```

### 2. 광고 준비 상태 확인

광고가 로드되었는지 확인하고 UI를 업데이트합니다.

```tsx theme={null}
const RewardedAdScreen = () => {
  const { isLoaded, show } = useAdropRewardedAd('YOUR_UNIT_ID');

  return (
    <View>
      <Button
        title={isLoaded ? "동영상 보고 생명 받기" : "광고 로딩중..."}
        onPress={show}
        disabled={!isLoaded}
      />
    </View>
  );
};
```

### 3. 메모리 관리

컴포넌트 언마운트 시 광고 리소스를 정리합니다.

```tsx theme={null}
// Hook 방식은 자동으로 정리됨
const { ... } = useAdropRewardedAd('YOUR_UNIT_ID');

// 클래스 방식은 수동으로 정리 필요
useEffect(() => {
  const ad = new AdropRewardedAd('YOUR_UNIT_ID');
  // ...

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

### 4. 에러 핸들링

적절한 에러 처리로 사용자 경험을 개선합니다.

```tsx theme={null}
const RewardedAdScreen = () => {
  const { errorCode, reset, load } = useAdropRewardedAd('YOUR_UNIT_ID');

  useEffect(() => {
    if (errorCode) {
      // 사용자에게 에러 알림
      Alert.alert('알림', '광고를 불러올 수 없습니다.');

      // 네트워크 에러인 경우 재시도
      if (errorCode === AdropErrorCode.network) {
        setTimeout(() => {
          reset();
          load();
        }, 3000);
      }
    }
  }, [errorCode, reset, load]);

  // ...
};
```

***

## 완전한 예제

### Hook 방식 완전한 예제

```tsx theme={null}
import React, { useEffect, useCallback } from 'react';
import {
  Button,
  View,
  Text,
  StyleSheet,
  Alert,
  ActivityIndicator
} from 'react-native';
import { useAdropRewardedAd } from 'adrop-ads-react-native';

const RewardedAdScreen = () => {
  const unitId = __DEV__ ? 'TEST_UNIT_ID' : 'YOUR_PRODUCTION_UNIT_ID';

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

  // 컴포넌트 마운트 시 광고 로드
  useEffect(() => {
    if (isReady) {
      console.log('광고 인스턴스 준비 완료, 광고 로드 시작');
      load();
    }
  }, [isReady, load]);

  // 광고가 표시될 때
  useEffect(() => {
    if (isOpened) {
      console.log('광고가 표시되었습니다');
      // 배경 음악 일시정지 등
    }
  }, [isOpened]);

  // 광고가 닫힌 후 다음 광고 미리 로드
  useEffect(() => {
    if (isClosed) {
      console.log('광고가 닫혔습니다');
      // 배경 음악 재개 등

      // 다음 광고 미리 로드
      reset();
      load();
    }
  }, [isClosed, reset, load]);

  // 보상 처리
  useEffect(() => {
    if (isEarnRewarded && reward) {
      console.log(`보상 획득 - 타입: ${reward.type}, 수량: ${reward.amount}`);
      grantReward(reward.type, reward.amount);
    }
  }, [isEarnRewarded, reward]);

  // 에러 처리
  useEffect(() => {
    if (errorCode) {
      console.log('광고 에러:', errorCode);

      // 네트워크 에러인 경우 재시도
      if (errorCode === AdropErrorCode.network) {
        Alert.alert(
          '네트워크 오류',
          '광고를 불러올 수 없습니다. 3초 후 재시도합니다.',
          [{ text: '확인' }]
        );

        setTimeout(() => {
          reset();
          load();
        }, 3000);
      } else {
        Alert.alert('오류', `광고 오류: ${errorCode}`);
      }
    }
  }, [errorCode, reset, load]);

  const handleShowAd = useCallback(() => {
    if (isLoaded) {
      show();
    } else {
      Alert.alert('알림', '광고가 아직 로드되지 않았습니다.');
    }
  }, [isLoaded, show]);

  const grantReward = (type: number, amount: number) => {
    // 사용자에게 보상 지급
    Alert.alert(
      '보상 획득!',
      `타입: ${type}, 수량: ${amount}`,
      [{ text: '확인' }]
    );

    // 실제 보상 지급 로직 구현
    // 예: 게임 재화 추가, 생명 회복 등
  };

  return (
    <View style={styles.container}>
      <Text style={styles.title}>보상형 광고</Text>

      {!isReady && (
        <View style={styles.loadingContainer}>
          <ActivityIndicator size="large" color="#0000ff" />
          <Text style={styles.loadingText}>광고 초기화 중...</Text>
        </View>
      )}

      <View style={styles.buttonContainer}>
        <Button
          title="광고 로드"
          onPress={load}
          disabled={!isReady}
        />
      </View>

      <View style={styles.buttonContainer}>
        <Button
          title={isLoaded ? "동영상 보고 생명 받기" : "광고 로딩중..."}
          onPress={handleShowAd}
          disabled={!isLoaded}
        />
      </View>

      <View style={styles.statusContainer}>
        <Text style={styles.statusText}>
          상태: {isLoaded ? '준비됨' : '로딩중'}
        </Text>
        {errorCode && (
          <Text style={styles.errorText}>에러: {errorCode}</Text>
        )}
      </View>
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    padding: 20,
    backgroundColor: '#f5f5f5',
  },
  title: {
    fontSize: 24,
    fontWeight: 'bold',
    marginBottom: 30,
  },
  loadingContainer: {
    alignItems: 'center',
    marginBottom: 20,
  },
  loadingText: {
    marginTop: 10,
    color: '#666',
  },
  buttonContainer: {
    width: '100%',
    marginVertical: 8,
  },
  statusContainer: {
    marginTop: 30,
    alignItems: 'center',
  },
  statusText: {
    fontSize: 16,
    color: '#333',
  },
  errorText: {
    fontSize: 14,
    color: 'red',
    marginTop: 8,
  },
});

export default RewardedAdScreen;
```

***

## 백필 광고

<Info>백필 광고를 사용하려면 네이티브 플랫폼(Android/iOS)에 백필 의존성이 추가되어 있어야 합니다.</Info>

백필 광고가 활성화되면 직광고를 사용할 수 없을 때 SDK가 자동으로 백필 광고로 폴백합니다. 리스너에서 백필 관련 에러 코드를 처리할 수 있습니다.

```tsx theme={null}
rewardedAd.listener = {
  onAdReceived: (ad) => {
    console.log('광고 로드됨:', ad.creativeId)
  },
  onAdFailedToReceive: (ad, errorCode) => {
    switch (errorCode) {
      case AdropErrorCode.adNoFill:
        console.log('직광고 없음, 백필 광고 요청 중...')
        break
      case AdropErrorCode.backfillNoFill:
        console.log('백필 광고도 없습니다')
        break
      default:
        console.log('광고 로드 실패:', errorCode)
    }
  },
}
```

***

## 관련 문서

<CardGroup cols={2}>
  <Card title="전면 광고" href="/ko/sdk/react-native/interstitial" icon="rectangle-ad">
    전면 광고 구현 가이드
  </Card>

  <Card title="팝업 광고" href="/ko/sdk/react-native/popup" icon="window-maximize">
    팝업 광고 구현 가이드
  </Card>

  <Card title="네이티브 광고" href="/ko/sdk/react-native/native" icon="image">
    네이티브 광고 구현 가이드
  </Card>

  <Card title="에러 코드" href="/ko/sdk/react-native/reference#error-codes" icon="triangle-exclamation">
    에러 코드 레퍼런스
  </Card>
</CardGroup>
