메인 콘텐츠로 건너뛰기

개요

팝업 광고(Popup Ad)는 특정 순간에 화면에 나타나는 광고 포맷입니다. 앱 실행 시, 콘텐츠 로드 완료 시, 특정 이벤트 발생 시 등 원하는 타이밍에 표시할 수 있으며, 사용자가 닫기 버튼을 누르거나 “오늘 하루 보지 않기”를 선택하여 종료할 수 있습니다.

특징

  • 화면 중앙 또는 하단에 표시되는 팝업 형태
  • 이미지 및 동영상 광고 지원
  • 닫기, 딤(배경) 클릭, “오늘 하루 보지 않기” 옵션 제공
  • 배경색, 텍스트 색상 등 커스터마이징 가능
  • 비침투적이면서도 효과적인 광고 경험
개발 환경에서는 테스트 유닛 ID를 사용하세요. 테스트 유닛 ID 섹션을 참고하세요.

구현 단계

팝업 광고는 다음 4단계로 구현합니다:
  1. 초기화 - AdropPopupAd 인스턴스 생성
  2. 델리게이트 설정 - 광고 및 닫기 이벤트 수신을 위한 델리게이트 설정
  3. 광고 로드 - 광고 요청 및 수신
  4. 광고 표시 - 화면에 광고 표시

UIKit 구현

기본 구현

import AdropAds

class ViewController: UIViewController {
    private var popupAd: AdropPopupAd?

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

    // 1. 광고 초기화 및 로드
    private func loadPopupAd() {
        popupAd = AdropPopupAd(unitId: "YOUR_POPUP_UNIT_ID")
        popupAd?.delegate = self
        popupAd?.closeDelegate = self
        popupAd?.load()
    }

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

델리게이트 구현

// 광고 델리게이트 구현
extension ViewController: AdropPopupAdDelegate {
    // 광고 수신 성공 (필수)
    func onAdReceived(_ ad: AdropPopupAd) {
        print("팝업 광고 수신 완료")
        // 광고가 준비되면 표시
        showPopupAd()
    }

    // 광고 수신 실패 (필수)
    func onAdFailedToReceive(_ ad: AdropPopupAd, _ errorCode: AdropErrorCode) {
        print("팝업 광고 수신 실패: \(errorCode)")
    }

    // 광고 노출 (선택)
    func onAdImpression(_ ad: AdropPopupAd) {
        print("팝업 광고 노출")
    }

    // 광고 클릭 (선택)
    func onAdClicked(_ ad: AdropPopupAd) {
        print("팝업 광고 클릭")
    }

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

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

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

    // 팝업 광고가 닫힌 직후 (선택)
    func onAdDidDismissFullScreen(_ ad: AdropPopupAd) {
        print("팝업 광고 닫힘")
        // 다음 광고를 미리 로드
        loadPopupAd()
    }

    // 팝업 광고 표시 실패 (선택)
    func onAdFailedToShowFullScreen(_ ad: AdropPopupAd, _ errorCode: AdropErrorCode) {
        print("팝업 광고 표시 실패: \(errorCode)")
    }
}

// 닫기 델리게이트 구현
extension ViewController: AdropPopupAdCloseDelegate {
    // 닫기 버튼 클릭 (선택)
    func onClosed(_ ad: AdropPopupAd) {
        print("팝업 광고 닫기 버튼 클릭")
    }

    // 딤(배경) 클릭 (선택)
    func onDimClicked(_ ad: AdropPopupAd) {
        print("팝업 광고 딤 영역 클릭")
    }

    // "오늘 하루 보지 않기" 클릭 (선택)
    func onTodayOffClicked(_ ad: AdropPopupAd) {
        print("오늘 하루 보지 않기 선택")
        // 오늘 날짜를 저장하여 다음 표시를 제어
        UserDefaults.standard.set(Date(), forKey: "lastPopupAdHiddenDate")
    }
}

SwiftUI 구현

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

ViewModel 패턴

import SwiftUI
import AdropAds

// ViewModel
class PopupAdViewModel: ObservableObject {
    @Published var isAdReady = false
    @Published var isAdShowing = false

    private var popupAd: AdropPopupAd?

    init() {
        loadAd()
    }

    func loadAd() {
        popupAd = AdropPopupAd(unitId: "YOUR_POPUP_UNIT_ID")
        popupAd?.delegate = self
        popupAd?.closeDelegate = self
        popupAd?.load()
    }

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

        popupAd.show(fromRootViewController: rootViewController)
    }

    func canShowTodayOffAd() -> Bool {
        guard let lastHiddenDate = UserDefaults.standard.object(forKey: "lastPopupAdHiddenDate") as? Date else {
            return true
        }

        return !Calendar.current.isDateInToday(lastHiddenDate)
    }
}

// 광고 델리게이트
extension PopupAdViewModel: AdropPopupAdDelegate {
    func onAdReceived(_ ad: AdropPopupAd) {
        DispatchQueue.main.async {
            self.isAdReady = true
        }
    }

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

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

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

// 닫기 델리게이트
extension PopupAdViewModel: AdropPopupAdCloseDelegate {
    func onClosed(_ ad: AdropPopupAd) {
        print("팝업 광고 닫기")
    }

    func onDimClicked(_ ad: AdropPopupAd) {
        print("팝업 광고 딤 클릭")
    }

    func onTodayOffClicked(_ ad: AdropPopupAd) {
        print("오늘 하루 보지 않기")
        UserDefaults.standard.set(Date(), forKey: "lastPopupAdHiddenDate")
    }
}

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

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

            Button("팝업 광고 표시") {
                if adViewModel.canShowTodayOffAd() {
                    adViewModel.showAd()
                } else {
                    print("오늘은 이미 '하루 보지 않기'를 선택했습니다")
                }
            }
            .disabled(!adViewModel.isAdReady)
            .padding()
        }
        .onAppear {
            // 앱 시작 시 자동 표시
            if adViewModel.isAdReady && adViewModel.canShowTodayOffAd() {
                adViewModel.showAd()
            }
        }
    }
}

커스터마이징

팝업 광고의 외형을 커스터마이징할 수 있습니다.

배경색 및 텍스트 색상 설정

private func loadPopupAd() {
    popupAd = AdropPopupAd(unitId: "YOUR_POPUP_UNIT_ID")
    popupAd?.delegate = self
    popupAd?.closeDelegate = self

    // 배경색 설정
    popupAd?.backgroundColor = UIColor.black.withAlphaComponent(0.8)

    // "오늘 하루 보지 않기" 텍스트 색상
    popupAd?.hideForTodayTextColor = UIColor.white

    // 닫기 버튼 텍스트 색상
    popupAd?.closeTextColor = UIColor.white

    popupAd?.load()
}

커스터마이징 옵션

속성타입설명기본값
backgroundColorUIColor?팝업 배경(딤) 색상검은색 (투명도 0.5)
hideForTodayTextColorUIColor?”오늘 하루 보지 않기” 텍스트 색상흰색
closeTextColorUIColor?닫기 버튼 텍스트 색상흰색

델리게이트 메서드

AdropPopupAdDelegate (광고 이벤트)

필수 메서드

onAdReceived
(AdropPopupAd) -> Void
광고 수신 성공 시 호출됩니다. 이 시점에서 show()를 호출하여 광고를 표시할 수 있습니다.
onAdFailedToReceive
(AdropPopupAd, AdropErrorCode) -> Void
광고 수신 실패 시 호출됩니다. 에러 코드를 통해 실패 원인을 확인할 수 있습니다.

선택 메서드

onAdImpression
(AdropPopupAd) -> Void
광고 노출이 기록되었을 때 호출됩니다.
onAdClicked
(AdropPopupAd) -> Void
사용자가 광고를 클릭했을 때 호출됩니다.
onAdWillPresentFullScreen
(AdropPopupAd) -> Void
팝업 광고가 표시되기 직전에 호출됩니다.
onAdDidPresentFullScreen
(AdropPopupAd) -> Void
팝업 광고가 화면에 표시된 직후 호출됩니다.
onAdWillDismissFullScreen
(AdropPopupAd) -> Void
팝업 광고가 닫히기 직전에 호출됩니다.
onAdDidDismissFullScreen
(AdropPopupAd) -> Void
팝업 광고가 닫힌 직후 호출됩니다. 다음 광고를 미리 로드하기 좋은 시점입니다.
onAdFailedToShowFullScreen
(AdropPopupAd, AdropErrorCode) -> Void
광고 표시 실패 시 호출됩니다. 에러 코드를 통해 실패 원인을 확인할 수 있습니다.

AdropPopupAdCloseDelegate (닫기 이벤트)

모든 메서드가 선택사항입니다.
onClosed
(AdropPopupAd) -> Void
사용자가 닫기 버튼을 클릭했을 때 호출됩니다.
onDimClicked
(AdropPopupAd) -> Void
사용자가 팝업 외부(딤 영역)를 클릭했을 때 호출됩니다.
onTodayOffClicked
(AdropPopupAd) -> Void
사용자가 “오늘 하루 보지 않기”를 선택했을 때 호출됩니다. 이 콜백에서 날짜를 저장하여 하루 동안 광고를 표시하지 않도록 구현할 수 있습니다.

”오늘 하루 보지 않기” 구현

사용자가 “오늘 하루 보지 않기”를 선택했을 때 적절히 처리하는 방법입니다.

UserDefaults를 이용한 구현

class PopupAdManager {
    private let todayOffKey = "popupAd_todayOff_date"
    private var popupAd: AdropPopupAd?

    // 오늘 광고를 표시할 수 있는지 확인
    func canShowAdToday() -> Bool {
        guard let lastHiddenDate = UserDefaults.standard.object(forKey: todayOffKey) as? Date else {
            return true // 한 번도 숨기지 않았으면 표시 가능
        }

        // 저장된 날짜가 오늘인지 확인
        return !Calendar.current.isDateInToday(lastHiddenDate)
    }

    // 광고 로드 및 표시
    func loadAndShowAd(from viewController: UIViewController) {
        guard canShowAdToday() else {
            print("오늘은 광고를 표시하지 않습니다")
            return
        }

        popupAd = AdropPopupAd(unitId: "YOUR_POPUP_UNIT_ID")
        popupAd?.delegate = self
        popupAd?.closeDelegate = self
        popupAd?.load()
    }
}

extension PopupAdManager: AdropPopupAdDelegate {
    func onAdReceived(_ ad: AdropPopupAd) {
        // 광고 수신 후 자동 표시
        if let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene,
           let rootViewController = windowScene.windows.first?.rootViewController {
            ad.show(fromRootViewController: rootViewController)
        }
    }

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

extension PopupAdManager: AdropPopupAdCloseDelegate {
    func onTodayOffClicked(_ ad: AdropPopupAd) {
        // 오늘 날짜를 저장
        UserDefaults.standard.set(Date(), forKey: todayOffKey)
        print("오늘 하루 팝업 광고를 표시하지 않습니다")
    }
}

사용 예시

class AppDelegate: UIResponder, UIApplicationDelegate {
    let popupAdManager = PopupAdManager()

    func applicationDidBecomeActive(_ application: UIApplication) {
        // 앱이 활성화될 때 팝업 광고 표시 시도
        if let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene,
           let rootViewController = windowScene.windows.first?.rootViewController {
            popupAdManager.loadAndShowAd(from: rootViewController)
        }
    }
}

베스트 프랙티스

1. 적절한 표시 시점

팝업 광고는 다음 시점에 표시하는 것이 효과적입니다:
// ✅ 좋은 예: 앱 시작 시
func applicationDidFinishLaunching() {
    loadAndShowPopupAd()
}

// ✅ 좋은 예: 콘텐츠 로드 완료 시
func onContentLoaded() {
    if shouldShowPopupAd() {
        showPopupAd()
    }
}

// ✅ 좋은 예: 특정 이벤트 완료 시
func onAchievementUnlocked() {
    showPopupAd()
}

// ❌ 나쁜 예: 사용자가 작업 중일 때
func onUserTyping() {
    showPopupAd() // 사용자 경험 저해
}

2. “오늘 하루 보지 않기” 존중

사용자가 “오늘 하루 보지 않기”를 선택했다면 반드시 준수하세요.
func shouldShowPopupAd() -> Bool {
    // 오늘 하루 보지 않기 확인
    guard canShowAdToday() else {
        return false
    }

    // 다른 조건 확인
    return true
}

3. 빈도 제한

팝업 광고를 너무 자주 표시하지 마세요.
class PopupAdFrequencyManager {
    private let lastShownKey = "popupAd_lastShown"
    private let minimumInterval: TimeInterval = 3600 // 1시간

    func canShowAd() -> Bool {
        // 오늘 하루 보지 않기 확인
        guard canShowAdToday() else {
            return false
        }

        // 최소 시간 간격 확인
        guard let lastShown = UserDefaults.standard.object(forKey: lastShownKey) as? Date else {
            return true
        }

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

    func recordAdShown() {
        UserDefaults.standard.set(Date(), forKey: lastShownKey)
    }
}

4. 광고 미리 로드

사용자 경험을 위해 광고를 미리 로드하세요.
class ViewController: UIViewController {
    private var popupAd: AdropPopupAd?
    private var isAdReady = false

    override func viewDidLoad() {
        super.viewDidLoad()
        // 미리 로드
        preloadPopupAd()
    }

    private func preloadPopupAd() {
        popupAd = AdropPopupAd(unitId: "YOUR_POPUP_UNIT_ID")
        popupAd?.delegate = self
        popupAd?.closeDelegate = self
        popupAd?.load()
    }

    func onAdReceived(_ ad: AdropPopupAd) {
        isAdReady = true
    }

    func showPopupAdIfReady() {
        if isAdReady {
            popupAd?.show(fromRootViewController: self)
        }
    }
}

테스트 유닛 ID

개발 및 테스트 시 다음 테스트 유닛 ID를 사용하세요.
광고 타입테스트 유닛 ID
팝업 (하단 이미지)PUBLIC_TEST_UNIT_ID_POPUP_BOTTOM
팝업 (중앙 이미지)PUBLIC_TEST_UNIT_ID_POPUP_CENTER
팝업 비디오 (하단 16:9)PUBLIC_TEST_UNIT_ID_POPUP_BOTTOM_VIDEO_16_9
팝업 비디오 (하단 9:16)PUBLIC_TEST_UNIT_ID_POPUP_BOTTOM_VIDEO_9_16
팝업 비디오 (중앙 16:9)PUBLIC_TEST_UNIT_ID_POPUP_CENTER_VIDEO_16_9
팝업 비디오 (중앙 9:16)PUBLIC_TEST_UNIT_ID_POPUP_CENTER_VIDEO_9_16

테스트 광고 사용 예시

import AdropAds

// 테스트 환경과 프로덕션 환경 분리
#if DEBUG
let popupUnitId = AdropUnitId.PUBLIC_TEST_UNIT_ID_POPUP_BOTTOM
#else
let popupUnitId = "YOUR_PRODUCTION_UNIT_ID"
#endif

popupAd = AdropPopupAd(unitId: popupUnitId)
실제 배포 시에는 반드시 애드컨트롤 콘솔에서 생성한 실제 유닛 ID를 사용하세요.

문제 해결

광고가 표시되지 않음

  • SDK가 초기화되었는지 확인
  • 유닛 ID가 올바른지 확인
  • 네트워크 연결 상태 확인
  • production 모드 설정 확인 (배포 시 true)
  • 에러 코드를 확인하여 원인 파악
  • 테스트 환경에서는 production: false 설정
  • 광고 인벤토리 부족 시 나중에 재시도
  • onAdReceived 콜백 이후에 show()를 호출했는지 확인
  • rootViewController가 유효한지 확인
  • 다른 뷰 컨트롤러가 이미 present되어 있지 않은지 확인

”오늘 하루 보지 않기”가 작동하지 않음

// 날짜 비교 로직 확인
func isDateInToday(_ date: Date) -> Bool {
    let calendar = Calendar.current
    let today = calendar.startOfDay(for: Date())
    let targetDate = calendar.startOfDay(for: date)
    return today == targetDate
}

// 사용
func canShowAdToday() -> Bool {
    guard let lastHiddenDate = UserDefaults.standard.object(forKey: "lastPopupAdHiddenDate") as? Date else {
        return true
    }

    return !isDateInToday(lastHiddenDate)
}

관련 문서