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

## 개요

전면 광고(Interstitial Ad)는 앱의 화면 전체를 덮는 형태로 표시되는 광고입니다. 게임의 레벨 전환, 콘텐츠 페이지 전환 등 앱의 자연스러운 전환 시점에 표시하기 적합합니다.

### 특징

* 전체 화면을 덮는 몰입형 광고
* 사용자가 명시적으로 닫기 전까지 유지
* 이미지 및 동영상 광고 지원
* 높은 시각적 주목도

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

***

## 구현 방식

Adrop React Native SDK는 전면 광고를 구현하는 두 가지 방식을 제공합니다:

1. **클래스 방식** - AdropInterstitialAd 클래스를 직접 사용
2. **Hook 방식** - useAdropInterstitialAd Hook 사용 (권장)

***

## AdropInterstitialAd 클래스

### 생성자

AdropInterstitialAd 인스턴스를 생성합니다.

```typescript theme={null}
import { AdropInterstitialAd } from 'adrop-ads-react-native'

const interstitialAd = new AdropInterstitialAd(unitId)
```

<ParamField body="unitId" type="string" required>
  광고 유닛 ID (콘솔에서 발급)
</ParamField>

### 프로퍼티

<ParamField body="isLoaded" type="boolean">
  광고가 로드되었는지 여부를 반환합니다.

  ```typescript theme={null}
  if (interstitialAd.isLoaded) {
    // 광고 표시 가능
  }
  ```
</ParamField>

<ParamField body="unitId" type="string">
  광고 유닛 ID를 반환합니다.

  ```typescript theme={null}
  const unitId = interstitialAd.unitId
  ```
</ParamField>

<ParamField body="creativeId" type="string">
  현재 로드된 광고의 크리에이티브 ID를 반환합니다.

  ```typescript theme={null}
  const creativeId = interstitialAd.creativeId
  ```
</ParamField>

<ParamField body="txId" type="string">
  현재 로드된 광고의 트랜잭션 ID를 반환합니다.

  ```typescript theme={null}
  const txId = interstitialAd.txId
  ```
</ParamField>

<ParamField body="campaignId" type="string">
  현재 로드된 광고의 캠페인 ID를 반환합니다.

  ```typescript theme={null}
  const campaignId = interstitialAd.campaignId
  ```
</ParamField>

<ParamField body="destinationURL" type="string">
  현재 로드된 광고의 도착 URL을 반환합니다.

  ```typescript theme={null}
  const destinationURL = interstitialAd.destinationURL
  ```
</ParamField>

<ParamField body="browserTarget" type="BrowserTarget">
  현재 로드된 광고의 브라우저 타겟 설정을 반환합니다 (`BrowserTarget.EXTERNAL` 또는 `BrowserTarget.INTERNAL`).

  ```typescript theme={null}
  const browserTarget = interstitialAd.browserTarget
  ```
</ParamField>

<ParamField body="listener" type="AdropListener">
  광고 이벤트를 수신하는 리스너를 설정합니다.

  ```typescript theme={null}
  interstitialAd.listener = {
    onAdReceived: (ad) => console.log('광고 수신'),
    onAdFailedToReceive: (ad, errorCode) => console.log('수신 실패', errorCode),
    // ... 기타 콜백
  }
  ```
</ParamField>

### 메서드

<ParamField body="load()" type="() => void">
  광고를 요청하고 로드합니다.

  ```typescript theme={null}
  interstitialAd.load()
  ```
</ParamField>

<ParamField body="show()" type="() => void">
  로드된 광고를 표시합니다. `isLoaded`가 `true`일 때 호출해야 합니다.

  ```typescript theme={null}
  if (interstitialAd.isLoaded) {
    interstitialAd.show()
  }
  ```
</ParamField>

<ParamField body="close()" type="() => void">
  현재 표시 중인 광고를 닫습니다. Android에서 뒤로가기 버튼 처리 시 유용합니다.

  ```typescript theme={null}
  interstitialAd.close()
  ```
</ParamField>

<ParamField body="destroy()" type="() => void">
  광고 인스턴스를 파괴하고 리소스를 해제합니다. 컴포넌트 언마운트 시 반드시 호출해야 합니다.

  ```typescript theme={null}
  useEffect(() => {
    return () => {
      interstitialAd?.destroy()
    }
  }, [interstitialAd])
  ```
</ParamField>

***

## AdropListener 인터페이스

광고 이벤트를 수신하기 위한 콜백 인터페이스입니다.

### 권장 콜백

<ParamField body="onAdReceived" type="(ad: AdropAd) => void">
  광고 수신 성공 시 호출됩니다. 이 시점에서 `show()`를 호출하여 광고를 표시할 수 있습니다.

  ```typescript theme={null}
  onAdReceived: (ad) => {
    console.log('광고 수신 완료:', ad.unitId)
    // 광고 표시 준비 완료
  }
  ```
</ParamField>

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

  ```typescript theme={null}
  onAdFailedToReceive: (ad, errorCode) => {
    console.log('광고 수신 실패:', errorCode)
  }
  ```
</ParamField>

### 선택 콜백

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

  ```typescript theme={null}
  onAdImpression: (ad) => {
    console.log('광고 노출됨')
  }
  ```
</ParamField>

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

  ```typescript theme={null}
  onAdClicked: (ad) => {
    console.log('광고 클릭됨')
  }
  ```
</ParamField>

<ParamField body="onAdWillPresentFullScreen" type="(ad: AdropAd) => void">
  전면 광고가 표시되기 직전에 호출됩니다. 게임 일시정지 등의 작업을 수행할 수 있습니다.

  ```typescript theme={null}
  onAdWillPresentFullScreen: (ad) => {
    console.log('광고 표시 직전')
    // 게임 일시정지, 음악 중지 등
  }
  ```
</ParamField>

<ParamField body="onAdDidPresentFullScreen" type="(ad: AdropAd) => void">
  전면 광고가 화면에 표시된 직후 호출됩니다.

  ```typescript theme={null}
  onAdDidPresentFullScreen: (ad) => {
    console.log('광고 표시 완료')
  }
  ```
</ParamField>

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

  ```typescript theme={null}
  onAdWillDismissFullScreen: (ad) => {
    console.log('광고 닫히기 직전')
  }
  ```
</ParamField>

<ParamField body="onAdDidDismissFullScreen" type="(ad: AdropAd) => void">
  전면 광고가 닫힌 직후 호출됩니다. 다음 광고를 미리 로드하기 좋은 시점입니다.

  ```typescript theme={null}
  onAdDidDismissFullScreen: (ad) => {
    console.log('광고 닫힘')
    // 게임 재개, 다음 광고 로드 등
  }
  ```
</ParamField>

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

  ```typescript theme={null}
  onAdFailedToShowFullScreen: (ad, errorCode) => {
    console.log('광고 표시 실패:', errorCode)
  }
  ```
</ParamField>

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

  ```typescript theme={null}
  onAdBackButtonPressed: (ad) => {
    console.log('뒤로가기 버튼 눌림')
  }
  ```
</ParamField>

***

## 클래스 방식 구현 예제

AdropInterstitialAd 클래스를 직접 사용하는 방식입니다.

```typescript theme={null}
import React, { useCallback, useEffect, useMemo, useState } from 'react'
import { Button, StyleSheet, Text, View } from 'react-native'
import { AdropInterstitialAd, type AdropListener } from 'adrop-ads-react-native'

const InterstitialAdScreen: React.FC = () => {
  const [interstitialAd, setInterstitialAd] = useState<AdropInterstitialAd>()
  const [isLoaded, setIsLoaded] = useState(false)
  const [errorCode, setErrorCode] = useState('')

  // 광고 이벤트 리스너 설정
  const listener: AdropListener = useMemo(() => ({
    onAdReceived: (ad) => {
      console.log('전면 광고 수신 완료:', ad.unitId)
      setIsLoaded(true)
      setErrorCode('')
    },
    onAdFailedToReceive: (ad, error) => {
      console.log('전면 광고 수신 실패:', error)
      setErrorCode(error || 'Unknown error')
      setIsLoaded(false)
    },
    onAdClicked: (ad) => {
      console.log('전면 광고 클릭됨')
    },
    onAdImpression: (ad) => {
      console.log('전면 광고 노출됨')
    },
    onAdWillPresentFullScreen: (ad) => {
      console.log('전면 광고 표시 직전')
      // 게임 일시정지, 음악 중지 등
    },
    onAdDidPresentFullScreen: (ad) => {
      console.log('전면 광고 표시 완료')
    },
    onAdWillDismissFullScreen: (ad) => {
      console.log('전면 광고 닫히기 직전')
    },
    onAdDidDismissFullScreen: (ad) => {
      console.log('전면 광고 닫힘')
      setIsLoaded(false)
      // 게임 재개, 다음 광고 미리 로드 등
    },
    onAdFailedToShowFullScreen: (ad, error) => {
      console.log('전면 광고 표시 실패:', error)
      setErrorCode(error || 'Unknown error')
      setIsLoaded(false)
    },
    onAdBackButtonPressed: (ad) => {
      console.log('뒤로가기 버튼 눌림')
      ad.close() // 뒤로가기 버튼으로 광고 닫기 (Android 전용)
    },
  }), [])

  // 광고 인스턴스 초기화
  useEffect(() => {
    const ad = new AdropInterstitialAd('YOUR_UNIT_ID')
    ad.listener = listener
    setInterstitialAd(ad)

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

  // 광고 로드
  const loadAd = useCallback(() => {
    interstitialAd?.load()
  }, [interstitialAd])

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

  return (
    <View style={styles.container}>
      <Button
        title="광고 로드"
        onPress={loadAd}
      />
      <Button
        title="광고 표시"
        onPress={showAd}
        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',
    marginTop: 16,
  },
})

export default InterstitialAdScreen
```

***

## useAdropInterstitialAd Hook

React Hook을 사용하여 전면 광고를 더 간편하게 구현할 수 있습니다.

### Hook 사용법

```typescript theme={null}
import { useAdropInterstitialAd } from 'adrop-ads-react-native'

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

<ParamField body="unitId" type="string | null" required>
  광고 유닛 ID. `null`을 전달하면 광고가 해제됩니다.
</ParamField>

### 반환값

<ParamField body="load" type="() => void">
  광고를 로드합니다. `isReady`가 `true`일 때만 동작합니다.

  ```typescript theme={null}
  const handleLoad = () => {
    if (isReady) {
      load()
    }
  }
  ```
</ParamField>

<ParamField body="show" type="() => void">
  로드된 광고를 표시합니다.

  ```typescript theme={null}
  const handleShow = () => {
    if (isLoaded) {
      show()
    }
  }
  ```
</ParamField>

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

  ```typescript theme={null}
  const handleReset = () => {
    reset()
  }
  ```
</ParamField>

<ParamField body="isReady" type="boolean">
  광고 인스턴스가 준비되었는지 여부입니다.
</ParamField>

<ParamField body="isLoaded" type="boolean">
  광고가 성공적으로 로드되었는지 여부입니다.
</ParamField>

<ParamField body="isOpened" type="boolean">
  광고가 화면에 표시되었는지 여부입니다.
</ParamField>

<ParamField body="isClosed" type="boolean">
  광고가 닫혔는지 여부입니다.
</ParamField>

<ParamField body="isClicked" type="boolean">
  광고가 클릭되었는지 여부입니다.
</ParamField>

<ParamField body="errorCode" type="string | undefined">
  광고 로드 또는 표시 중 발생한 에러 코드입니다.
</ParamField>

<ParamField body="isBackPressed" type="boolean">
  광고 표시 중 뒤로가기 버튼이 눌렸는지 여부입니다. **Android 전용.**
</ParamField>

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

***

## Hook 방식 구현 예제

useAdropInterstitialAd Hook을 사용하는 방식입니다 (권장).

```typescript theme={null}
import React, { useCallback, useMemo } from 'react'
import { Button, StyleSheet, Text, View } from 'react-native'
import { useAdropInterstitialAd } from 'adrop-ads-react-native'

const InterstitialAdScreen: React.FC = () => {
  const unitId = 'YOUR_UNIT_ID'

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

  // 광고 로드
  const handleLoad = useCallback(() => {
    if (isReady) {
      load()
    }
  }, [isReady, load])

  // 광고 표시
  const handleShow = useCallback(() => {
    if (isLoaded) {
      show()
    }
  }, [isLoaded, show])

  // 광고 리셋
  const handleReset = useCallback(() => {
    reset()
  }, [reset])

  return (
    <View style={styles.container}>
      <Button
        title="광고 로드"
        onPress={handleLoad}
        disabled={!isReady}
      />

      <Button
        title="광고 표시"
        onPress={handleShow}
        disabled={!isLoaded}
      />

      <Button
        title="광고 리셋"
        onPress={handleReset}
        disabled={!(isOpened || errorCode)}
      />

      {/* 상태 표시 */}
      <View style={styles.statusContainer}>
        <Text>준비됨: {isReady ? '예' : '아니오'}</Text>
        <Text>로드됨: {isLoaded ? '예' : '아니오'}</Text>
        <Text>표시됨: {isOpened ? '예' : '아니오'}</Text>
        <Text>닫힘: {isClosed ? '예' : '아니오'}</Text>
        <Text>클릭됨: {isClicked ? '예' : '아니오'}</Text>
      </View>

      {errorCode && (
        <Text style={styles.error}>오류: {errorCode}</Text>
      )}
    </View>
  )
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    gap: 16,
  },
  statusContainer: {
    marginTop: 24,
    padding: 16,
    backgroundColor: '#f0f0f0',
    borderRadius: 8,
  },
  error: {
    color: 'red',
    marginTop: 16,
  },
})

export default InterstitialAdScreen
```

***

## 테스트 유닛 ID

개발 및 테스트 환경에서는 반드시 테스트 유닛 ID를 사용하세요.

```typescript theme={null}
// 테스트용
const TEST_UNIT_ID = 'PUBLIC_TEST_UNIT_ID_INTERSTITIAL'

// 개발/프로덕션 환경 분리
const unitId = __DEV__
  ? 'PUBLIC_TEST_UNIT_ID_INTERSTITIAL'
  : 'YOUR_PRODUCTION_UNIT_ID'
```

<Warning>
  프로덕션 빌드에서는 반드시 실제 유닛 ID를 사용해야 합니다. 테스트 유닛 ID로 발생한 수익은 정산되지 않습니다.
</Warning>

***

## 에러 처리

광고 로드 및 표시 중 발생할 수 있는 에러를 적절히 처리해야 합니다.

### 에러 코드

| 에러 코드                        | 설명            | 대응 방법            |
| ---------------------------- | ------------- | ---------------- |
| `AdropErrorCode.network`     | 네트워크 오류       | 네트워크 연결 확인 후 재시도 |
| `AdropErrorCode.internal`    | 내부 오류         | 재시도 또는 고객 지원 문의  |
| `AdropErrorCode.initialize`  | SDK 초기화 실패    | SDK 초기화 코드 확인    |
| `AdropErrorCode.invalidUnit` | 유효하지 않은 유닛 ID | 유닛 ID 확인         |
| `AdropErrorCode.adNoFill`    | 광고 인벤토리 부족    | 정상, 나중에 재시도      |
| `AdropErrorCode.adLoading`   | 이미 로드 중       | 로드 완료 후 재시도      |
| `AdropErrorCode.adEmpty`     | 로드된 광고 없음     | 광고 로드 후 표시       |
| `AdropErrorCode.adShown`     | 이미 표시된 광고     | 새 광고 로드 필요       |

### 에러 처리 예제

```typescript theme={null}
const { load, show, errorCode, isLoaded } = useAdropInterstitialAd(unitId)

useEffect(() => {
  if (errorCode) {
    switch (errorCode) {
      case AdropErrorCode.network:
        console.log('네트워크 오류: 연결 확인 필요')
        // 30초 후 재시도
        setTimeout(() => load(), 30000)
        break

      case AdropErrorCode.adNoFill:
        console.log('표시할 광고 없음')
        // 광고 없이 계속 진행
        break

      case AdropErrorCode.invalidUnit:
        console.error('유효하지 않은 유닛 ID')
        break

      default:
        console.log('광고 오류:', errorCode)
        break
    }
  }
}, [errorCode, load])
```

***

## 모범 사례

### 1. 적절한 표시 시점

앱의 자연스러운 전환 시점에 광고를 표시하세요.

```typescript theme={null}
// ✅ 좋은 예: 게임 레벨 전환
const handleLevelComplete = () => {
  saveProgress()
  if (isLoaded) {
    show() // 자연스러운 전환 시점
  }
  navigateToNextLevel()
}

// ✅ 좋은 예: 콘텐츠 읽기 완료
const handleArticleFinished = () => {
  if (isLoaded) {
    show()
  }
}

// ❌ 나쁜 예: 사용자 액션 중간
const handleButtonClick = () => {
  show() // 사용자 경험 저해
  performAction()
}
```

### 2. 사전 로드

광고를 미리 로드하여 사용자 대기 시간을 최소화하세요.

```typescript theme={null}
const InterstitialAdScreen: React.FC = () => {
  const { load, show, isLoaded, isClosed } = useAdropInterstitialAd(unitId)

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

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

  return (
    // ...
  )
}
```

### 3. 빈도 제한

너무 자주 광고를 표시하지 않도록 제한하세요.

```typescript theme={null}
const InterstitialAdScreen: React.FC = () => {
  const { show, isLoaded } = useAdropInterstitialAd(unitId)
  const [lastShownTime, setLastShownTime] = useState(0)
  const MIN_INTERVAL = 3 * 60 * 1000 // 3분

  const showAdWithFrequencyLimit = useCallback(() => {
    const now = Date.now()
    if (now - lastShownTime < MIN_INTERVAL) {
      console.log('광고 표시 간격이 너무 짧습니다')
      return
    }

    if (isLoaded) {
      show()
      setLastShownTime(now)
    }
  }, [isLoaded, show, lastShownTime])

  return (
    // ...
  )
}
```

### 4. 게임 일시정지 처리

클래스 방식에서 리스너를 사용하여 게임 상태를 관리하세요.

```typescript theme={null}
const listener: AdropListener = useMemo(() => ({
  onAdWillPresentFullScreen: (ad) => {
    // 게임 일시정지
    pauseGame()
    pauseBackgroundMusic()
  },
  onAdDidDismissFullScreen: (ad) => {
    // 게임 재개
    resumeGame()
    resumeBackgroundMusic()
  },
}), [])
```

### 5. 메모리 관리

컴포넌트 언마운트 시 반드시 리소스를 해제하세요.

```typescript theme={null}
// Hook 방식 - 자동 관리됨
const { load, show } = useAdropInterstitialAd(unitId)

// 클래스 방식 - 수동 정리 필요
useEffect(() => {
  const ad = new AdropInterstitialAd(unitId)
  setInterstitialAd(ad)

  return () => {
    ad.destroy() // 필수!
  }
}, [unitId])
```

***

## 플랫폼별 고려사항

### iOS

* iOS에서는 앱이 백그라운드로 이동할 때 광고가 자동으로 닫힙니다
* `onAdDidDismissFullScreen` 콜백이 호출됩니다

### Android

* Android의 뒤로가기 버튼으로 광고를 닫을 수 있습니다
* 하드웨어 가속이 필요할 수 있습니다

***

## 백필 광고

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

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

```tsx theme={null}
interstitialAd.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/rewarded">
    보상형 광고로 사용자 인게이지먼트 향상
  </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/popup">
    팝업 광고 구현하기
  </Card>
</CardGroup>
