> ## 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.

# 전면 광고

> iOS 앱에서 전면 광고를 구현하는 방법을 안내합니다.

## 개요

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

### 특징

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

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

***

## 구현 단계

전면 광고는 다음 4단계로 구현합니다:

1. **초기화** - AdropInterstitialAd 인스턴스 생성
2. **Delegate 설정** - 광고 이벤트 수신을 위한 Delegate 설정
3. **광고 로드** - 광고 요청 및 수신
4. **광고 표시** - 화면에 광고 표시

***

## UIKit 구현

### 기본 구현

<CodeGroup>
  ```swift Swift theme={null}
  import AdropAds

  class ViewController: UIViewController {
      private var interstitialAd: AdropInterstitialAd?

      override func viewDidLoad() {
          super.viewDidLoad()
          loadInterstitialAd()
      }

      // 1. 광고 초기화 및 로드
      private func loadInterstitialAd() {
          interstitialAd = AdropInterstitialAd(unitId: "YOUR_UNIT_ID")
          interstitialAd?.delegate = self
          interstitialAd?.load()
      }

      // 2. 광고 표시
      private func showInterstitialAd() {
          guard let interstitialAd = interstitialAd,
                interstitialAd.isLoaded else { return }
          interstitialAd.show(fromRootViewController: self)
      }
  }
  ```

  ```objc Objective-C theme={null}
  @import AdropAds;

  @interface ViewController () <AdropInterstitialAdDelegate>
  @property (nonatomic, strong) AdropInterstitialAd *interstitialAd;
  @end

  @implementation ViewController

  - (void)viewDidLoad {
      [super viewDidLoad];
      [self loadInterstitialAd];
  }

  // 1. 광고 초기화 및 로드
  - (void)loadInterstitialAd {
      self.interstitialAd = [[AdropInterstitialAd alloc] initWithUnitId:@"YOUR_UNIT_ID"];
      self.interstitialAd.delegate = self;
      [self.interstitialAd load];
  }

  // 2. 광고 표시
  - (void)showInterstitialAd {
      if (self.interstitialAd && self.interstitialAd.isLoaded) {
          [self.interstitialAd showFromRootViewController:self];
      }
  }

  @end
  ```
</CodeGroup>

### isLoaded 프로퍼티

광고가 로드되었는지 확인하는 프로퍼티입니다. `show()` 호출 전에 이 값을 확인하는 것이 좋습니다.

<CodeGroup>
  ```swift Swift theme={null}
  if interstitialAd?.isLoaded == true {
      interstitialAd?.show(fromRootViewController: self)
  }
  ```

  ```objc Objective-C theme={null}
  if (self.interstitialAd.isLoaded) {
      [self.interstitialAd showFromRootViewController:self];
  }
  ```
</CodeGroup>

### Delegate 구현

<CodeGroup>
  ```swift Swift theme={null}
  extension ViewController: AdropInterstitialAdDelegate {
      // 광고 수신 성공 (필수)
      func onAdReceived(_ ad: AdropInterstitialAd) {
          print("전면 광고 수신 완료")
          // 광고가 준비되면 표시
          showInterstitialAd()
      }

      // 광고 수신 실패 (필수)
      func onAdFailedToReceive(_ ad: AdropInterstitialAd, _ errorCode: AdropErrorCode) {
          print("전면 광고 수신 실패: \(errorCode)")
      }

      // 광고 노출 (선택)
      func onAdImpression(_ ad: AdropInterstitialAd) {
          print("전면 광고 노출")
      }

      // 광고 클릭 (선택)
      func onAdClicked(_ ad: AdropInterstitialAd) {
          print("전면 광고 클릭")
      }

      // 전면 광고가 표시되기 직전 (선택)
      func onAdWillPresentFullScreen(_ ad: AdropInterstitialAd) {
          print("전면 광고 표시 직전")
      }

      // 전면 광고가 표시된 직후 (선택)
      func onAdDidPresentFullScreen(_ ad: AdropInterstitialAd) {
          print("전면 광고 표시 완료")
      }

      // 전면 광고가 닫히기 직전 (선택)
      func onAdWillDismissFullScreen(_ ad: AdropInterstitialAd) {
          print("전면 광고 닫히기 직전")
      }

      // 전면 광고가 닫힌 직후 (선택)
      func onAdDidDismissFullScreen(_ ad: AdropInterstitialAd) {
          print("전면 광고 닫힘")
          // 다음 광고를 미리 로드
          loadInterstitialAd()
      }

      // 전면 광고 표시 실패 (선택)
      func onAdFailedToShowFullScreen(_ ad: AdropInterstitialAd, _ errorCode: AdropErrorCode) {
          print("전면 광고 표시 실패: \(errorCode)")
      }
  }
  ```

  ```objc Objective-C theme={null}
  #pragma mark - AdropInterstitialAdDelegate

  // 광고 수신 성공 (필수)
  - (void)onAdReceived:(AdropInterstitialAd *)ad {
      NSLog(@"전면 광고 수신 완료");
      // 광고가 준비되면 표시
      [self showInterstitialAd];
  }

  // 광고 수신 실패 (필수)
  - (void)onAdFailedToReceive:(AdropInterstitialAd *)ad :(AdropErrorCode)errorCode {
      NSLog(@"전면 광고 수신 실패: %ld", (long)errorCode);
  }

  // 광고 노출 (선택)
  - (void)onAdImpression:(AdropInterstitialAd *)ad {
      NSLog(@"전면 광고 노출");
  }

  // 광고 클릭 (선택)
  - (void)onAdClicked:(AdropInterstitialAd *)ad {
      NSLog(@"전면 광고 클릭");
  }

  // 전면 광고가 표시되기 직전 (선택)
  - (void)onAdWillPresentFullScreen:(AdropInterstitialAd *)ad {
      NSLog(@"전면 광고 표시 직전");
  }

  // 전면 광고가 표시된 직후 (선택)
  - (void)onAdDidPresentFullScreen:(AdropInterstitialAd *)ad {
      NSLog(@"전면 광고 표시 완료");
  }

  // 전면 광고가 닫히기 직전 (선택)
  - (void)onAdWillDismissFullScreen:(AdropInterstitialAd *)ad {
      NSLog(@"전면 광고 닫히기 직전");
  }

  // 전면 광고가 닫힌 직후 (선택)
  - (void)onAdDidDismissFullScreen:(AdropInterstitialAd *)ad {
      NSLog(@"전면 광고 닫힘");
      // 다음 광고를 미리 로드
      [self loadInterstitialAd];
  }

  // 전면 광고 표시 실패 (선택)
  - (void)onAdFailedToShowFullScreen:(AdropInterstitialAd *)ad :(AdropErrorCode)errorCode {
      NSLog(@"전면 광고 표시 실패: %ld", (long)errorCode);
  }
  ```
</CodeGroup>

***

## SwiftUI 구현

SwiftUI에서는 `UIViewControllerRepresentable`을 사용하거나, UIWindow에서 rootViewController를 가져와 표시할 수 있습니다.

### 방법 1: ViewModel 패턴

```swift theme={null}
import SwiftUI
import AdropAds

// ViewModel
class InterstitialAdViewModel: NSObject, ObservableObject {
    @Published var isAdReady = false
    @Published var isAdShowing = false

    private var interstitialAd: AdropInterstitialAd?

    init() {
        loadAd()
    }

    func loadAd() {
        interstitialAd = AdropInterstitialAd(unitId: "YOUR_UNIT_ID")
        interstitialAd?.delegate = self
        interstitialAd?.load()
    }

    func showAd() {
        guard let interstitialAd = interstitialAd,
              let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene,
              let rootViewController = windowScene.windows.first?.rootViewController else {
            return
        }

        interstitialAd.show(fromRootViewController: rootViewController)
    }
}

// Delegate
extension InterstitialAdViewModel: AdropInterstitialAdDelegate {
    func onAdReceived(_ ad: AdropInterstitialAd) {
        DispatchQueue.main.async {
            self.isAdReady = true
        }
    }

    func onAdFailedToReceive(_ ad: AdropInterstitialAd, _ errorCode: AdropErrorCode) {
        print("광고 수신 실패: \(errorCode)")
    }

    func onAdDidPresentFullScreen(_ ad: AdropInterstitialAd) {
        DispatchQueue.main.async {
            self.isAdShowing = true
        }
    }

    func onAdDidDismissFullScreen(_ ad: AdropInterstitialAd) {
        DispatchQueue.main.async {
            self.isAdShowing = false
            self.isAdReady = false
        }
        // 다음 광고 미리 로드
        loadAd()
    }
}

// View
struct ContentView: View {
    @StateObject private var adViewModel = InterstitialAdViewModel()

    var body: some View {
        VStack {
            Text("전면 광고 예제")
                .font(.title)

            Button("전면 광고 표시") {
                adViewModel.showAd()
            }
            .disabled(!adViewModel.isAdReady)
            .padding()
        }
    }
}
```

***

## Delegate 메서드

### 필수 메서드

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

<ParamField body="onAdFailedToReceive" type="(AdropInterstitialAd, AdropErrorCode) -> Void">
  광고 수신 실패 시 호출됩니다. 에러 코드를 통해 실패 원인을 확인할 수 있습니다.
</ParamField>

### 선택 메서드

<ParamField body="onAdImpression" type="(AdropInterstitialAd) -> Void">
  광고 노출이 기록되었을 때 호출됩니다.
</ParamField>

<ParamField body="onAdClicked" type="(AdropInterstitialAd) -> Void">
  사용자가 광고를 클릭했을 때 호출됩니다.
</ParamField>

<ParamField body="onAdWillPresentFullScreen" type="(AdropInterstitialAd) -> Void">
  전면 광고가 표시되기 직전에 호출됩니다. 애니메이션 일시정지 등의 작업을 수행할 수 있습니다.
</ParamField>

<ParamField body="onAdDidPresentFullScreen" type="(AdropInterstitialAd) -> Void">
  전면 광고가 화면에 표시된 직후 호출됩니다.
</ParamField>

<ParamField body="onAdWillDismissFullScreen" type="(AdropInterstitialAd) -> Void">
  전면 광고가 닫히기 직전에 호출됩니다.
</ParamField>

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

<ParamField body="onAdFailedToShowFullScreen" type="(AdropInterstitialAd, AdropErrorCode) -> Void">
  광고 표시 실패 시 호출됩니다. 에러 코드를 통해 실패 원인을 확인할 수 있습니다.
</ParamField>

***

## 클로저 콜백

Delegate 대신 클로저 기반 콜백을 사용할 수 있습니다.

```swift theme={null}
let interstitialAd = AdropInterstitialAd(unitId: "YOUR_UNIT_ID")

// 필수
interstitialAd.onAdReceived = { ad in
    print("광고 수신 성공")
}
interstitialAd.onAdFailedToReceive = { ad, errorCode in
    print("광고 수신 실패: \(errorCode)")
}

// 선택
interstitialAd.onAdImpression = { ad in print("광고 노출") }
interstitialAd.onAdClicked = { ad in print("광고 클릭") }
interstitialAd.onAdWillPresentFullScreen = { ad in print("광고 표시 직전") }
interstitialAd.onAdDidPresentFullScreen = { ad in print("광고 표시됨") }
interstitialAd.onAdWillDismissFullScreen = { ad in print("광고 닫기 직전") }
interstitialAd.onAdDidDismissFullScreen = { ad in print("광고 닫힘") }
interstitialAd.onAdFailedToShowFullScreen = { ad, errorCode in print("광고 표시 실패: \(errorCode)") }
```

<Note>
  Delegate와 클로저를 동시에 설정하면 두 가지 모두 호출됩니다.
</Note>

***

## 모범 사례

### 1. 광고 미리 로드

광고를 표시하기 전에 미리 로드하여 사용자 경험을 개선하세요.

```swift theme={null}
class GameViewController: UIViewController {
    private var interstitialAd: AdropInterstitialAd?
    private var isAdReady = false

    override func viewDidLoad() {
        super.viewDidLoad()
        // 화면 진입 시 미리 로드
        preloadInterstitialAd()
    }

    private func preloadInterstitialAd() {
        interstitialAd = AdropInterstitialAd(unitId: "YOUR_UNIT_ID")
        interstitialAd?.delegate = self
        interstitialAd?.load()
    }

    func onGameLevelComplete() {
        // 레벨 완료 시 즉시 표시
        if isAdReady {
            interstitialAd?.show(fromRootViewController: self)
        }
    }
}

extension GameViewController: AdropInterstitialAdDelegate {
    func onAdReceived(_ ad: AdropInterstitialAd) {
        isAdReady = true
    }

    func onAdFailedToReceive(_ ad: AdropInterstitialAd, _ errorCode: AdropErrorCode) {
        print("광고 로드 실패: \(errorCode)")
    }

    func onAdDidDismissFullScreen(_ ad: AdropInterstitialAd) {
        isAdReady = false
        // 다음 광고 미리 로드
        preloadInterstitialAd()
    }
}
```

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

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

```swift theme={null}
// ✅ 좋은 예: 게임 레벨 전환
func onLevelComplete() {
    saveProgress()
    showInterstitialAd()
    loadNextLevel()
}

// ✅ 좋은 예: 콘텐츠 읽기 완료
func onArticleFinished() {
    showInterstitialAd()
}

// ❌ 나쁜 예: 사용자 액션 중간
func onButtonTap() {
    showInterstitialAd() // 사용자 경험 저해
    performAction()
}
```

### 3. 닫기 후 재로드

광고가 닫힌 후 다음 광고를 미리 로드하세요.

```swift theme={null}
func onAdDidDismissFullScreen(_ ad: AdropInterstitialAd) {
    // 즉시 다음 광고 로드
    loadInterstitialAd()
}
```

### 4. 에러 처리

광고 로드 실패에 대비한 처리를 구현하세요.

```swift theme={null}
func onAdFailedToReceive(_ ad: AdropInterstitialAd, _ errorCode: AdropErrorCode) {
    switch errorCode {
    case .ERROR_CODE_NETWORK:
        print("네트워크 오류: 나중에 다시 시도")
        retryAfterDelay()
    case .ERROR_CODE_AD_NO_FILL:
        print("표시할 광고 없음")
        continueWithoutAd()
    default:
        print("광고 로드 실패: \(errorCode)")
    }
}

private func retryAfterDelay() {
    DispatchQueue.main.asyncAfter(deadline: .now() + 30) {
        self.loadInterstitialAd()
    }
}
```

### 5. 빈도 제한

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

```swift theme={null}
class AdFrequencyManager {
    private var lastAdShownTime: Date?
    private let minimumInterval: TimeInterval = 180 // 3분

    func canShowAd() -> Bool {
        guard let lastTime = lastAdShownTime else {
            return true
        }

        return Date().timeIntervalSince(lastTime) >= minimumInterval
    }

    func recordAdShown() {
        lastAdShownTime = Date()
    }
}

// 사용 예시
let frequencyManager = AdFrequencyManager()

func showInterstitialIfAllowed() {
    guard frequencyManager.canShowAd() else {
        print("광고 표시 간격이 너무 짧음")
        return
    }

    interstitialAd?.show(fromRootViewController: self)
}

func onAdDidPresentFullScreen(_ ad: AdropInterstitialAd) {
    frequencyManager.recordAdShown()
}
```

***

## 다음 단계

<CardGroup cols={2}>
  <Card title="보상형 광고" href="/ko/sdk/ios/rewarded">
    보상형 광고로 사용자 인게이지먼트 향상
  </Card>

  <Card title="배너 광고" href="/ko/sdk/ios/banner">
    배너 광고 구현하기
  </Card>

  <Card title="타겟팅 설정" href="/ko/sdk/ios/targeting">
    사용자 속성 및 문맥 타겟팅
  </Card>

  <Card title="레퍼런스" href="/ko/sdk/ios/reference">
    API 레퍼런스 문서
  </Card>
</CardGroup>
