Files
sodalive-ios/docs/plan-task/20260428_Yandex광고화면배치구현.md

7.4 KiB

20260428 Yandex 광고 화면 배치 구현

작업 체크리스트

  • Yandex 광고 SDK/초기화/기존 인프라 확인
  • 광고 삽입 대상 화면과 정확한 위치 확정
  • 공용 Yandex 배너/전면광고 SwiftUI 브리지 구현
  • LiveView 최근 종료 라이브와 다시 듣기 사이 배너 삽입
  • LiveDetailView 참여자 목록과 크리에이터 프로필 사이 배너 삽입
  • ContentDetailView 오픈예정/theme 표시와 다음화/이전화 사이 배너 삽입
  • ContentDetailPlayView 무료 재생/미리듣기 시작 전 전면광고 삽입
  • 빌드 및 정적 검증 기록 추가

작업 기준

  • 공식 문서:
    • https://ads.yandex.com/helpcenter/ko/dev/ios/adaptive-inline-banner
    • https://ads.yandex.com/helpcenter/ko/dev/ios/interstitial
  • 기존 SDK 상태:
    • SodaLive/Sources/App/AppDelegate.swift
    • Podfile
    • Podfile.lock
  • 수정 대상 예상:
    • SodaLive/Sources/Common/YandexInlineBannerView.swift
    • SodaLive/Sources/Common/YandexInterstitialAdManager.swift
    • SodaLive/Sources/Live/LiveView.swift
    • SodaLive/Sources/Live/Room/Detail/LiveDetailView.swift
    • SodaLive/Sources/Content/Detail/ContentDetailView.swift
    • SodaLive/Sources/Content/Detail/ContentDetailPlayView.swift
    • SodaLive.xcodeproj/project.pbxproj

QA 기준

  • Live 탭에서 최근 종료한 라이브 섹션 아래, 라이브 다시 듣기 섹션 위에 배너가 표시된다.
  • 라이브 상세 바텀시트에서 참여자 영역 아래, 크리에이터 프로필 위에 배너가 표시된다.
  • 콘텐츠 상세에서 오픈예정/theme 정보 아래, 다음화/이전화 버튼 위에 배너가 표시된다.
  • 무료 콘텐츠 재생과 유료 콘텐츠 미리듣기 시작 시 전면광고 표시 이후 오디오 재생이 이어진다.
  • 구매 완료 콘텐츠 등 일반 유료 재생은 전면광고 없이 기존처럼 바로 재생된다.

구현 메모

  • 저장소에 실제 Yandex 운영 ad unit id는 없으므로 SodaLive/Sources/Utils/Constants.swift, SodaLive/Sources/Debug/Utils/Constants.swift에 공식 demo unit(demo-banner-yandex, demo-interstitial-yandex) 상수를 추가했다.
  • 운영 unit 치환은 각 Constants 파일의 placement별 상수(YANDEX_LIVE_TAB_BANNER_AD_UNIT_ID, YANDEX_LIVE_DETAIL_BANNER_AD_UNIT_ID, YANDEX_CONTENT_DETAIL_BANNER_AD_UNIT_ID, YANDEX_CONTENT_DETAIL_INTERSTITIAL_AD_UNIT_ID) 값만 교체하면 되도록 구성한다.
  • 전면광고는 ContentDetailPlayView의 실제 contentPlayManager.playAudio(...) 호출 직전에만 개입하고, 공용 플레이어 매니저 로직은 건드리지 않는다.

검증 기록

  • 2026-04-28 / 사전 조사

    • 무엇: SDK 초기화 여부, 광고 인프라 존재 여부, 삽입 위치, Yandex 공식 배너/전면광고 API 요구사항을 확인했다.
    • 왜: 이미 연결된 SDK를 재설정하지 않고 최소 변경 경로로 광고 삽입을 구현하기 위해서다.
    • 어떻게:
      • AppDelegate.swift, Podfile, Podfile.lock, 대상 SwiftUI 화면 파일을 확인했다.
      • background explore/librarian로 내부 광고 패턴 부재와 Yandex 공식 API(AdView, InterstitialAdLoader)를 교차 검증했다.
    • 결과:
      • SDK 초기화와 plist 준비는 완료돼 있었고, 광고 전용 SwiftUI 브리지는 아직 없었다.
      • 구현은 공용 브리지 추가 + 세 화면 삽입 + 재생 트리거 가드 추가로 수렴했다.
  • 2026-04-28 / 구현 및 빌드 검증

    • 무엇: 공용 Yandex 광고 지원 파일 추가, 세 화면 배너 삽입, 콘텐츠 재생 전면광고 가드, 빌드 모드별 unit id 조회 경로를 구현했다.
    • 왜: 기존 SDK 초기화 상태를 유지하면서 요청한 위치와 트리거에만 광고를 정확히 추가하기 위해서다.
    • 어떻게:
      • SodaLive/Sources/Common/YandexAdSupport.swiftBannerAdView, InterstitialAdLoader.loadAd(with:completion:), InterstitialAdDelegate 기반 공용 로직을 추가했다.
      • LiveView, LiveDetailView, ContentDetailView, ContentDetailPlayView를 최소 변경으로 수정했다.
      • SodaLive/Sources/Utils/Constants.swift, SodaLive/Sources/Debug/Utils/Constants.swiftYANDEX_BANNER_AD_UNIT_ID, YANDEX_INTERSTITIAL_AD_UNIT_ID 상수를 추가했다.
      • xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive-dev" -configuration Debug build
      • xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive" -configuration Debug build
      • plutil -lint "SodaLive/Resources/Info.plist"
      • plutil -lint "SodaLive/Resources/Debug/SodaLive-dev-Info.plist"
      • 각 빌드 타깃에서 상수 참조와 컴파일 성공 여부를 확인했다.
    • 결과:
      • SodaLive-dev Debug 빌드 성공
      • SodaLive Debug 빌드 성공
      • 두 plist 문법 검증 성공
      • 두 타깃 모두 Constants 기반 unit id 참조 상태로 빌드 성공
      • SourceKit lsp_diagnosticsYandexMobileAds, Kingfisher, RefreshableScrollView 외부 모듈을 단독 해석하지 못해 모듈 미해결 오류를 보고했으나, 실제 xcodebuild 실컴파일은 통과했다.
  • 2026-04-28 / unit id 저장 위치 Constants 전환

    • 무엇: Yandex 광고 unit id 저장 위치를 Info.plist에서 Constants.swift/Debug/Utils/Constants.swift로 이동했다.
    • 왜: 요청대로 unit id를 앱 상수 레이어에서 타깃별로 관리하고, plist에는 저장하지 않기 위해서다.
    • 어떻게:
      • SodaLive/Sources/Utils/Constants.swiftYANDEX_BANNER_AD_UNIT_ID, YANDEX_INTERSTITIAL_AD_UNIT_ID 추가
      • SodaLive/Sources/Debug/Utils/Constants.swift에 동일 상수 추가
      • SodaLive/Sources/Common/YandexAdSupport.swiftBundle.main.object(forInfoDictionaryKey:) 제거
      • 두 plist에서 Yandex*AdUnitID* 키 제거
      • grep로 남은 Yandex Info.plist 조회/키 참조가 없는지 확인
      • xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive-dev" -configuration Debug build
      • xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive" -configuration Debug build
      • plutil -lint "SodaLive/Resources/Info.plist"
      • plutil -lint "SodaLive/Resources/Debug/SodaLive-dev-Info.plist"
    • 결과:
      • Yandex unit id의 plist 저장/조회 흔적 제거 완료
      • SodaLive-dev Debug 빌드 성공
      • SodaLive Debug 빌드 성공
      • 두 plist 문법 검증 성공
  • 2026-04-28 / placement별 광고 ID 및 Sendable 경고 대응

    • 무엇: 공용 광고 ID를 placement별 상수로 분리하고, interstitial preload를 async/await 기반으로 변경했다.
    • 왜: Live 탭/라이브 상세/콘텐츠 상세/콘텐츠 상세 전면광고가 서로 다른 광고 ID를 사용해야 하고, @Sendable completion closure의 self 캡처 경고도 제거해야 했기 때문이다.
    • 어떻게:
      • YandexAdSupport.swiftYandexBannerPlacement, YandexInterstitialPlacement를 추가했다.
      • 배너는 placement별 AdRequest(adUnitID:)를 사용하도록 변경했다.
      • interstitial은 @MainActor + try await interstitialAdLoader.loadAd(with:) 패턴으로 변경했다.
      • LiveView, LiveDetailView, ContentDetailView, ContentDetailPlayView에서 각 placement를 명시적으로 전달하도록 수정했다.
    • 결과:
      • 페이지별 광고 ID를 독립적으로 설정할 수 있는 구조로 전환됨
      • completion closure 기반 self 캡처 경고 제거 대상 구조를 async/await로 대체함