Files
sodalive-android/docs/20260427_채팅탭Yandex배너광고추가.md

16 KiB

20260427 채팅 탭 Yandex 배너 광고 추가

작업 체크리스트

  • 대상 화면 3곳의 구조와 기존 Yandex 광고 패턴을 조사한다.
    QA: CharacterTabFragment, OriginalTabFragment, TalkTabFragment, LiveFragment, MyPageFragment, 공식 Yandex adaptive inline banner 문서를 근거로 삽입 위치와 구현 패턴을 설명할 수 있어야 한다.
  • 화면별 AD_UNIT_ID 분리 전략과 추가 대상 키를 확정한다.
    QA: app/build.gradledebug/release에 각 화면용 BuildConfig 필드가 필요하다는 판단 근거가 문서에 남아 있어야 한다.
  • app/build.gradle에 Character/Original/Talk 탭용 Yandex inline banner ad unit id를 추가한다.
    QA: debug/release 모두에서 3개 화면용 BuildConfig 값이 생성되어야 한다.
  • fragment_character_tab.xmlCharacterTabFragment.kt에 최근 대화한 캐릭터와 인기 캐릭터 사이 배너를 추가한다.
    QA: ll_latest_characters 다음, ll_popular_characters 이전에 배너가 배치되고 기존 상단 콘텐츠 배너는 유지되어야 하며, 배너 최대 높이는 90dp를 넘지 않아야 한다.
  • fragment_original_tab.xmlOriginalTabFragment.kt에 최상단 배너를 추가한다.
    QA: 배너가 rv_original 위에 배치되고, 리스트가 배너 아래부터 시작해야 하며, 프래그먼트 종료 시 리소스가 정리되어야 한다.
  • fragment_talk_tab.xmlTalkTabFragment.kt에 최상단 배너를 추가한다.
    QA: 배너가 rv_talk 위에 배치되고, 빈 상태 문구가 배너와 겹치지 않아야 하며, 프래그먼트 종료 시 리소스가 정리되어야 한다.
  • 변경 사항을 빌드/테스트/수동 확인 기준으로 검증한다.
    QA: 최소 :app:assembleDebug, :app:testDebugUnitTest, :app:ktlintCheck 결과와 수동 확인 가능 여부가 기록되어야 한다.
  • 검증 기록과 체크리스트를 문서 하단에 누적 갱신한다.
    QA: 무엇/왜/어떻게, 실행 명령, 결과가 한국어로 누적되어야 한다.
  • Original/Talk 탭 배너를 RecyclerView 헤더로 이동한다.
    QA: 배너가 고정 영역이 아니라 RecyclerView 첫 아이템으로 스크롤되어야 하며, Original 그리드에서는 전체 span을 차지해야 한다.
  • Original/Talk 탭의 세로 여백을 Character 탭 기준 24dp 흐름에 맞춘다.
    QA: 스크롤 콘텐츠가 상단 24dp에서 시작하고, Talk/Original의 하단 여백이 24dp 기준으로 유지되어야 한다.
  • 후속 변경 검증 상태를 재실행 가능 상태로 갱신한다.
    QA: 이번 요청의 도구 제한 때문에 Gradle 명령은 실행하지 않고, 재실행 대상 명령과 제한 사유를 문서에 남겨야 한다.

범위 메모

  • 이번 요청 범위는 채팅 영역의 3개 화면에 Yandex adaptive inline banner를 추가하는 작업으로 한정한다.
  • CharacterTabFragment는 기존 상단 콘텐츠 캐러셀 배너를 제거하지 않고, 최근 대화한 캐릭터와 인기 캐릭터 사이에 Yandex 배너를 추가한다.
  • OriginalTabFragment, TalkTabFragment는 화면 최상단에 Yandex 배너를 추가하되, 후속 변경에서는 RecyclerView 헤더 아이템으로 이동해 리스트와 함께 스크롤되도록 한다.
  • AD_UNIT_ID는 사용자 요청대로 페이지별로 분리하며, 기존 저장소 관례에 맞춰 app/build.gradledebug/release buildConfigField로 관리한다.
  • Yandex SDK 의존성과 앱 초기화는 이미 존재하므로 이번 작업에서 SDK 추가나 SodaLiveApp.kt 수정은 제외한다.
  • 배너 로드 패턴은 현재 저장소의 LiveFragment, MyPageFragment에서 사용하는 post { -> setAdUnitId -> setAdSize(BannerAdSize.inlineSize(...)) -> loadAd(...) } 흐름을 우선 따른다.
  • 배너 정리는 프래그먼트 뷰 생명주기에 맞춰 onDestroyView()에서 destroy()를 호출하는 방향으로 맞춘다.

조사 근거

  • 대상 화면
    • app/src/main/java/kr/co/vividnext/sodalive/chat/character/CharacterTabFragment.kt
    • app/src/main/res/layout/fragment_character_tab.xml
    • app/src/main/java/kr/co/vividnext/sodalive/chat/original/OriginalTabFragment.kt
    • app/src/main/res/layout/fragment_original_tab.xml
    • app/src/main/java/kr/co/vividnext/sodalive/chat/talk/TalkTabFragment.kt
    • app/src/main/res/layout/fragment_talk_tab.xml
  • 기존 배너 구현 참고
    • app/src/main/java/kr/co/vividnext/sodalive/live/LiveFragment.kt
    • app/src/main/java/kr/co/vividnext/sodalive/mypage/MyPageFragment.kt
    • app/src/main/res/layout/fragment_live.xml
  • 설정 참고
    • app/build.gradle
  • 공식 문서
    • https://ads.yandex.com/helpcenter/ko/dev/android/adaptive-inline-banner

구현 계획

1. AD_UNIT_ID 추가

  • 수정 대상: app/build.gradle
  • 계획:
    • releasedebug 각각에 아래 키를 추가한다.
      • YANDEX_INLINE_BANNER_CHARACTER_TAB_AD_UNIT_ID
      • YANDEX_INLINE_BANNER_ORIGINAL_TAB_AD_UNIT_ID
      • YANDEX_INLINE_BANNER_TALK_TAB_AD_UNIT_ID
    • 실제 값은 아직 제공되지 않았으므로 화면별·빌드타입별 placeholder 문자열을 서로 다르게 사용한다.
  • 이유:
    • 기존 Yandex 광고가 모두 BuildConfig 기반으로 주입되고 있고, 사용자도 페이지별 분리를 명시했기 때문이다.

2. Character 탭 중간 배너 추가

  • 수정 대상:
    • app/src/main/res/layout/fragment_character_tab.xml
    • app/src/main/java/kr/co/vividnext/sodalive/chat/character/CharacterTabFragment.kt
  • 위치:
    • ll_latest_characters 다음, ll_popular_characters 이전
  • 계획:
    • 섹션 사이에 BannerAdView를 추가하고 기존 24dp 간격 흐름을 유지한다.
    • setupView() 흐름에 배너 로드 메서드를 추가한다.
    • 측정된 너비 기준으로 adaptive inline banner를 로드하고, 최대 높이는 90dp 상한을 유지한다.
    • onDestroyView()에서 배너를 정리한다.

3. Original 탭 최상단 배너 추가

  • 수정 대상:
    • app/src/main/res/layout/fragment_original_tab.xml
    • app/src/main/java/kr/co/vividnext/sodalive/chat/original/OriginalTabFragment.kt
  • 위치:
    • 루트 최상단, rv_original
  • 계획:
    • ConstraintLayout 상단에 BannerAdView를 추가하고, rv_original의 top constraint를 배너 아래로 조정한다.
    • 프래그먼트 로드 시 배너를 설정하고 종료 시 정리한다.

4. Talk 탭 최상단 배너 추가

  • 수정 대상:
    • app/src/main/res/layout/fragment_talk_tab.xml
    • app/src/main/java/kr/co/vividnext/sodalive/chat/talk/TalkTabFragment.kt
  • 위치:
    • 루트 최상단, rv_talk
  • 계획:
    • 최상단에 BannerAdView를 추가하고, rv_talktv_empty가 배너 아래 레이아웃 기준을 따르도록 constraint를 조정한다.
    • 빈 상태 문구는 배너와 겹치지 않게 유지한다.
    • 프래그먼트 종료 시 배너를 정리한다.

예상 수정 파일

  • docs/20260427_채팅탭Yandex배너광고추가.md
  • app/build.gradle
  • app/src/main/res/layout/fragment_character_tab.xml
  • app/src/main/java/kr/co/vividnext/sodalive/chat/character/CharacterTabFragment.kt
  • app/src/main/res/layout/fragment_original_tab.xml
  • app/src/main/java/kr/co/vividnext/sodalive/chat/original/OriginalTabFragment.kt
  • app/src/main/res/layout/fragment_talk_tab.xml
  • app/src/main/java/kr/co/vividnext/sodalive/chat/talk/TalkTabFragment.kt

검증 계획

  • ./gradlew :app:assembleDebug
  • ./gradlew :app:testDebugUnitTest
  • ./gradlew :app:ktlintCheck
  • 수동 확인
    • Character 탭에서 최근 대화한 캐릭터와 인기 캐릭터 사이에 배너가 보이는지 확인한다.
    • Original 탭에서 배너가 최상단에 보이고 그 아래부터 그리드가 시작하는지 확인한다.
    • Talk 탭에서 배너가 최상단에 보이고, 빈 상태 문구가 배너와 겹치지 않는지 확인한다.

구현 반영 기록

  • 2026-04-27
    • 무엇: Character/Original/Talk 탭에 Yandex adaptive inline banner 구현을 반영했다.
    • 왜: 각 채팅 탭 화면에 별도 광고 단위 키를 사용하고, 지정 위치에 inline banner를 추가하며, 뷰 종료 시 광고 리소스를 정리해야 하기 때문이다.
    • 어떻게:
      • app/build.gradledebug/release에 화면별 placeholder BuildConfig 키 3개씩을 추가했다.
      • fragment_character_tab.xmlll_latest_charactersll_popular_characters 사이에 BannerAdView를 추가했다.
      • fragment_original_tab.xmlfragment_talk_tab.xml은 최상단 BannerAdView 아래로 리스트가 시작되도록 조정했고, Talk 빈 상태 문구도 배너 아래 영역을 기준으로 배치했다.
      • 각 Fragment는 setAdUnitId(...), BannerAdSize.inlineSize(...), AdRequest.Builder().build() 패턴으로 배너를 로드하고 onDestroyView()에서 destroy()를 호출하도록 연결했다.
    • 결과: 구현 체크리스트 중 코드 반영 항목을 완료 상태로 갱신했다. 빌드/테스트/수동 확인 결과는 아직 기록하지 않았다.
  • 2026-04-27
    • 무엇: Original/Talk 탭의 Yandex 배너를 고정 XML 자식에서 RecyclerView 헤더 아이템으로 이동하는 후속 변경을 반영했다.
    • 왜: 배너가 리스트 바깥에 고정되어 있으면 Character 탭의 스크롤 콘텐츠 여백 흐름과 맞지 않고, 사용자가 요청한 “리스트와 함께 스크롤되는 배너” 조건을 만족하지 못하기 때문이다.
    • 어떻게:
      • YandexInlineBannerHeaderAdapter를 추가해 BannerAdView를 RecyclerView 첫 아이템으로 생성하고, 기존 Yandex SDK 7.18.5 방식인 setAdUnitId(...), BannerAdSize.inlineSize(...), AdRequest.Builder().build() 호출 흐름을 유지했다.
      • OriginalTabFragmentConcatAdapter로 배너 헤더와 기존 그리드 어댑터를 연결하고, GridLayoutManager.SpanSizeLookupGridSpacingItemDecoration(headerCount = 1)로 헤더가 전체 3열을 차지하게 했다.
      • Original 그리드는 기존 16dp 아이템 하단 간격을 유지하면서 스크롤 콘텐츠 끝 여백이 24dp가 되도록 RecyclerView 하단 padding을 8dp로 보정했다.
      • TalkTabFragmentConcatAdapter로 배너 헤더와 기존 Talk 어댑터를 연결하고, ItemDecoration이 헤더를 건너뛰도록 보정했다.
      • fragment_original_tab.xml, fragment_talk_tab.xml에서는 고정 배너 뷰를 제거하고 RecyclerView를 부모 상단에 직접 연결했다.
      • Talk 빈 상태 문구는 유지하되 RecyclerView는 배너 헤더를 표시할 수 있도록 빈 목록에서도 보이게 했다.
    • 결과: 후속 변경의 코드 반영 항목을 완료 상태로 갱신했다.

검증 기록

  • 2026-04-27
    • 무엇: 채팅 탭 Yandex 배너 광고 추가 작업의 계획 문서를 생성했다.
    • 왜: 저장소 규칙에 따라 구현 전에 docs 아래 계획 문서를 먼저 만들고, 범위·광고 위치·검증 기준을 먼저 고정해야 하기 때문이다.
    • 어떻게:
      • 생성 파일: docs/20260427_채팅탭Yandex배너광고추가.md
      • 근거 파일: app/build.gradle, CharacterTabFragment.kt, OriginalTabFragment.kt, TalkTabFragment.kt, 각 대응 XML, LiveFragment.kt, MyPageFragment.kt
      • 근거 문서: https://ads.yandex.com/helpcenter/ko/dev/android/adaptive-inline-banner
      • 결과: 화면별 위치, AD_UNIT_ID 분리, 예상 수정 파일, 검증 계획을 구현 전에 확정했다.
  • 2026-04-27
    • 무엇: 채팅 탭 3개 화면의 Yandex 배너 추가 구현에 대해 빌드, 테스트, 린트, 수동 확인 가능 여부를 검증했다.
    • 왜: 이번 변경은 BuildConfig, Kotlin, XML을 함께 수정하므로 실제 Android 리소스 병합과 컴파일, 테스트, 스타일 검사를 통과해야 안전하게 반영됐다고 볼 수 있기 때문이다.
    • 어떻게:
      • 진단 도구: lsp_diagnostics
      • 진단 결과: .kt, .xml LSP 서버가 현재 환경에 설정되어 있지 않아 정적 진단은 수행하지 못했다.
      • 실행 명령: ./gradlew :app:assembleDebug
      • 실행 결과: BUILD SUCCESSFUL
      • 실행 명령: ./gradlew :app:testDebugUnitTest
      • 실행 결과: BUILD SUCCESSFUL
      • 실행 명령: ./gradlew :app:ktlintCheck
      • 실행 결과: BUILD SUCCESSFUL
      • 실행 명령: adb devices
      • 실행 결과: 연결 기기 없음
      • 수동 확인 결과: ADB 연결 기기가 없어 앱 실행 기반 수동 QA는 수행하지 못했다.
      • 비고: app/build.gradle의 Character/Original/Talk 탭 ad unit id는 현재 placeholder 값이므로, 실제 광고 응답 확인은 실 ad unit id 교체 후 추가 검증이 필요하다.
  • 2026-04-27
    • 무엇: Original/Talk 탭 Yandex 배너 후속 변경의 정적 진단 가능 여부와 참조 정리를 확인했다.
    • 왜: 이번 변경은 XML 바인딩 참조를 제거하고 RecyclerView 헤더 어댑터로 이동했으므로, 남은 고정 배너 참조와 문서 검증 상태를 확인해야 하기 때문이다.
    • 어떻게:
      • 진단 도구: lsp_diagnostics
      • 진단 결과: Markdown 문서(docs/20260427_채팅탭Yandex배너광고추가.md)는 진단 없음.
      • 진단 결과: .kt, .xml LSP 서버가 현재 환경에 설정되어 있지 않아 Kotlin/XML 정적 진단은 수행하지 못했다.
      • 확인 도구: grep
      • 확인 결과: OriginalTabFragment, TalkTabFragment, fragment_original_tab.xml, fragment_talk_tab.xml에는 기존 고정 배너 바인딩/ID 참조가 남아 있지 않다.
      • 재실행 대기 명령: ./gradlew :app:assembleDebug, ./gradlew :app:testDebugUnitTest, ./gradlew :app:ktlintCheck
    • 결과: 이 시점에서는 Gradle 기반 빌드/테스트/린트를 아직 재실행하지 않았고, 기존 검증 명령은 재실행 준비 상태로 유지했다.
  • 2026-04-27
    • 무엇: Original/Talk 탭 배너 헤더 후속 변경에 대해 빌드, 테스트, 린트, 기기 연결 상태를 다시 검증했다.
    • 왜: 이번 후속 변경은 배너를 RecyclerView 헤더 어댑터로 옮기고 간격 계산을 변경했으므로, 실제 Android 컴파일과 테스트를 다시 통과해야 안전하게 반영됐다고 볼 수 있기 때문이다.
    • 어떻게:
      • 진단 도구: lsp_diagnostics
      • 진단 결과: .kt, .xml LSP 서버가 현재 환경에 설정되어 있지 않아 Kotlin/XML 정적 진단은 수행하지 못했다.
      • 실행 명령: ./gradlew :app:assembleDebug
      • 실행 결과: BUILD SUCCESSFUL
      • 실행 명령: ./gradlew :app:testDebugUnitTest
      • 실행 결과: BUILD SUCCESSFUL
      • 실행 명령: ./gradlew :app:ktlintCheck
      • 실행 결과: BUILD SUCCESSFUL
      • 실행 명령: adb devices
      • 실행 결과: 한때 2cec640c34017ece 기기가 표시되었으나, 이후 설치/실행 시점에는 연결이 끊어졌다.
      • 실행 명령: ./gradlew :app:installDebug
      • 실행 결과: No connected devices!
      • 실행 명령: adb shell am start -n kr.co.vividnext.sodalive.debug/kr.co.vividnext.sodalive.splash.SplashActivity
      • 실행 결과: adb: no devices/emulators found
      • Oracle 검토 결과: 후속 변경은 요청한 스크롤 배너 요구사항을 충족하며, 즉시 수정이 필요한 correctness/layout/pagination 결함은 확인되지 않았다.
    • 결과: 빌드/테스트/린트는 모두 통과했고, 수동 QA는 기기 연결 해제 때문에 완료하지 못했다. 남은 검증 공백은 Original/Talk 화면에서 배너가 첫 아이템처럼 함께 스크롤되는지 실제 기기에서 확인하는 것이다.