16 KiB
16 KiB
20260427 채팅 탭 Yandex 배너 광고 추가
작업 체크리스트
- 대상 화면 3곳의 구조와 기존 Yandex 광고 패턴을 조사한다.
QA:CharacterTabFragment,OriginalTabFragment,TalkTabFragment,LiveFragment,MyPageFragment, 공식 Yandex adaptive inline banner 문서를 근거로 삽입 위치와 구현 패턴을 설명할 수 있어야 한다. - 화면별 AD_UNIT_ID 분리 전략과 추가 대상 키를 확정한다.
QA:app/build.gradle의debug/release에 각 화면용BuildConfig필드가 필요하다는 판단 근거가 문서에 남아 있어야 한다. app/build.gradle에 Character/Original/Talk 탭용 Yandex inline banner ad unit id를 추가한다.
QA:debug/release모두에서 3개 화면용BuildConfig값이 생성되어야 한다.fragment_character_tab.xml과CharacterTabFragment.kt에 최근 대화한 캐릭터와 인기 캐릭터 사이 배너를 추가한다.
QA:ll_latest_characters다음,ll_popular_characters이전에 배너가 배치되고 기존 상단 콘텐츠 배너는 유지되어야 하며, 배너 최대 높이는 90dp를 넘지 않아야 한다.fragment_original_tab.xml과OriginalTabFragment.kt에 최상단 배너를 추가한다.
QA: 배너가rv_original위에 배치되고, 리스트가 배너 아래부터 시작해야 하며, 프래그먼트 종료 시 리소스가 정리되어야 한다.fragment_talk_tab.xml과TalkTabFragment.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.gradle의debug/releasebuildConfigField로 관리한다. - 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.ktapp/src/main/res/layout/fragment_character_tab.xmlapp/src/main/java/kr/co/vividnext/sodalive/chat/original/OriginalTabFragment.ktapp/src/main/res/layout/fragment_original_tab.xmlapp/src/main/java/kr/co/vividnext/sodalive/chat/talk/TalkTabFragment.ktapp/src/main/res/layout/fragment_talk_tab.xml
- 기존 배너 구현 참고
app/src/main/java/kr/co/vividnext/sodalive/live/LiveFragment.ktapp/src/main/java/kr/co/vividnext/sodalive/mypage/MyPageFragment.ktapp/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 - 계획:
release와debug각각에 아래 키를 추가한다.YANDEX_INLINE_BANNER_CHARACTER_TAB_AD_UNIT_IDYANDEX_INLINE_BANNER_ORIGINAL_TAB_AD_UNIT_IDYANDEX_INLINE_BANNER_TALK_TAB_AD_UNIT_ID
- 실제 값은 아직 제공되지 않았으므로 화면별·빌드타입별 placeholder 문자열을 서로 다르게 사용한다.
- 이유:
- 기존 Yandex 광고가 모두
BuildConfig기반으로 주입되고 있고, 사용자도 페이지별 분리를 명시했기 때문이다.
- 기존 Yandex 광고가 모두
2. Character 탭 중간 배너 추가
- 수정 대상:
app/src/main/res/layout/fragment_character_tab.xmlapp/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.xmlapp/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.xmlapp/src/main/java/kr/co/vividnext/sodalive/chat/talk/TalkTabFragment.kt
- 위치:
- 루트 최상단,
rv_talk위
- 루트 최상단,
- 계획:
- 최상단에
BannerAdView를 추가하고,rv_talk및tv_empty가 배너 아래 레이아웃 기준을 따르도록 constraint를 조정한다. - 빈 상태 문구는 배너와 겹치지 않게 유지한다.
- 프래그먼트 종료 시 배너를 정리한다.
- 최상단에
예상 수정 파일
docs/20260427_채팅탭Yandex배너광고추가.mdapp/build.gradleapp/src/main/res/layout/fragment_character_tab.xmlapp/src/main/java/kr/co/vividnext/sodalive/chat/character/CharacterTabFragment.ktapp/src/main/res/layout/fragment_original_tab.xmlapp/src/main/java/kr/co/vividnext/sodalive/chat/original/OriginalTabFragment.ktapp/src/main/res/layout/fragment_talk_tab.xmlapp/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.gradle의debug/release에 화면별 placeholderBuildConfig키 3개씩을 추가했다.fragment_character_tab.xml은ll_latest_characters와ll_popular_characters사이에BannerAdView를 추가했다.fragment_original_tab.xml과fragment_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()호출 흐름을 유지했다.OriginalTabFragment는ConcatAdapter로 배너 헤더와 기존 그리드 어댑터를 연결하고,GridLayoutManager.SpanSizeLookup및GridSpacingItemDecoration(headerCount = 1)로 헤더가 전체 3열을 차지하게 했다.- Original 그리드는 기존 16dp 아이템 하단 간격을 유지하면서 스크롤 콘텐츠 끝 여백이 24dp가 되도록 RecyclerView 하단 padding을 8dp로 보정했다.
TalkTabFragment는ConcatAdapter로 배너 헤더와 기존 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,.xmlLSP 서버가 현재 환경에 설정되어 있지 않아 정적 진단은 수행하지 못했다. - 실행 명령:
./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,.xmlLSP 서버가 현재 환경에 설정되어 있지 않아 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,.xmlLSP 서버가 현재 환경에 설정되어 있지 않아 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 화면에서 배너가 첫 아이템처럼 함께 스크롤되는지 실제 기기에서 확인하는 것이다.