From 51ffe0912548d492c3bce78eede276f6e204057d Mon Sep 17 00:00:00 2001 From: Yu Sung Date: Thu, 30 Apr 2026 14:38:59 +0900 Subject: [PATCH] =?UTF-8?q?fix(yandex-ads):=20=EA=B4=91=EA=B3=A0=20?= =?UTF-8?q?=ED=9B=84=20=EC=9E=AC=EC=83=9D=20=EC=95=A1=EC=85=98=EC=9D=84=20?= =?UTF-8?q?=EC=9C=A0=EC=A7=80=ED=95=9C=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- SodaLive/Sources/Common/YandexAdSupport.swift | 4 +- docs/20260430_콘텐츠상세광고후재생수정.md | 40 +++++++++++++++++++ 2 files changed, 42 insertions(+), 2 deletions(-) create mode 100644 docs/20260430_콘텐츠상세광고후재생수정.md diff --git a/SodaLive/Sources/Common/YandexAdSupport.swift b/SodaLive/Sources/Common/YandexAdSupport.swift index ff22db8..6e27161 100644 --- a/SodaLive/Sources/Common/YandexAdSupport.swift +++ b/SodaLive/Sources/Common/YandexAdSupport.swift @@ -238,6 +238,7 @@ final class YandexInterstitialAdManager: NSObject { return } + loadedAd.delegate = self interstitialAd = loadedAd } catch { if currentPlacement == placement { @@ -259,14 +260,13 @@ final class YandexInterstitialAdManager: NSObject { } pendingAction = action - self.interstitialAd = nil - interstitialAd.delegate = self interstitialAd.show(from: presenter) } private func completePendingAction() { let action = pendingAction pendingAction = nil + interstitialAd = nil action?() if let currentPlacement { diff --git a/docs/20260430_콘텐츠상세광고후재생수정.md b/docs/20260430_콘텐츠상세광고후재생수정.md new file mode 100644 index 0000000..d1f7b90 --- /dev/null +++ b/docs/20260430_콘텐츠상세광고후재생수정.md @@ -0,0 +1,40 @@ +# 콘텐츠 상세 광고 후 재생 수정 + +## 작업 계획 +- [x] 콘텐츠 상세 미리듣기/무료 콘텐츠 재생 경로 확인 +- [x] 전면광고 종료/실패 콜백 이후 재생 액션 호출 여부 확인 +- [x] 광고 이후 재생이 시작되도록 최소 수정 적용 +- [x] 수정 파일 진단 및 가능한 빌드/수동 QA 수행 + +## 완료 기준 +- 미리듣기 또는 무료 콘텐츠 재생 전 전면광고가 표시된 경우, 광고 종료 후 기존 재생 액션이 호출된다. +- 전면광고 표시 실패 시에도 기존 fallback 재생 액션이 호출된다. +- 변경 범위는 콘텐츠 상세 재생/광고 흐름에 한정한다. + +## 검증 기록 + +- 2026-04-30 / 원인 조사 및 구현 + - 무엇: 콘텐츠 상세의 미리듣기/무료 콘텐츠 재생 전면광고 흐름을 확인하고, 광고 종료/표시 실패 후 재생 액션이 안정적으로 실행되도록 수정했다. + - 왜: Yandex 공식 문서가 전면광고 객체와 loader를 사용 주기 동안 strong reference로 유지하라고 안내하는데, 기존 구현은 `show(from:)` 직전에 `interstitialAd` 참조를 해제해 dismiss/fail 콜백 기반 `pendingAction` 실행이 유실될 수 있었기 때문이다. + - 어떻게: + - `ContentDetailPlayView.handlePlayTap()`의 `showAdIfAvailable(... then: playAction)` 흐름을 확인했다. + - `YandexInterstitialAdManager`에서 preload 성공 시 `loadedAd.delegate = self`를 설정하고, 광고 표시 중에는 `interstitialAd` 참조를 유지하도록 변경했다. + - `interstitialAdDidDismiss`/`didFailToShow`에서 `completePendingAction()`이 호출될 때 `pendingAction` 실행 후 `interstitialAd`를 정리하도록 변경했다. + - Yandex 공식 문서(`https://ads.yandex.com/helpcenter/en/dev/ios/interstitial`)의 strong reference 유지 권장 사항과 dismiss/fail 콜백 용도를 확인했다. + - 결과: + - 광고 표시 직후 객체 참조를 끊던 경로 제거 완료 + - 광고 종료/표시 실패 콜백 이후 기존 재생 액션 실행 경로 유지 + +- 2026-04-30 / 검증 + - 무엇: 수정 파일 정적 진단, 콜백 경로 확인, 두 앱 스킴 Debug 빌드를 수행했다. + - 왜: 공통 광고 지원 파일 변경이 `SodaLive`와 `SodaLive-dev` 양쪽에 영향을 주기 때문이다. + - 어떻게: + - `lsp_diagnostics` on `SodaLive/Sources/Common/YandexAdSupport.swift` + - `ast-grep`로 `showAdIfAvailable` 내 광고 표시 전 참조 해제 코드 제거 여부 확인 + - `xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive-dev" -configuration Debug build` + - `xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive" -configuration Debug build` + - 결과: + - `SodaLive-dev` Debug 빌드 성공 + - `SodaLive` Debug 빌드 성공 + - `lsp_diagnostics`는 SourceKit 단독 해석에서 `YandexMobileAds` 모듈 미해결을 보고했으나, 실제 Xcode 빌드는 두 스킴 모두 성공했다. + - 실제 기기에서 광고 시청 후 오디오가 시작되는 수동 QA는 이 환경에서 앱 로그인/콘텐츠/광고 표시 조작이 불가해 수행하지 못했다.