광고 유닛 전면 재도입 (RES-004)
· 약 3분
작업 날짜: 2026-07-29 브랜치:
feature/1.54.0-ad-units
📋 작업 개요
작업 유형: 기능 추가 (광고 재도입) 담당: jsg3121 · claude
DS 반응형 개편(A~F 그룹) 과정에서 각 페이지의 UA 분기 2벌 구조를 반응형 단일로 통합하며 제거·보류했던 AdSense 광고를, 데이터 기반 우선순위에 따라 전 페이지에 다시 도입했다. 배치 전략 보고서는 .claude/research/reports/RES-004-ad-placement-strategy.md.
🎯 작업 목표
DS 개편으로 사라진 광고 수익을 회복하되, 단순 복원이 아니라 3지표(GA4 조회·서치콘솔 검색·애드센스 수익, 2026-04~07)를 종합해 트래픽·수익 기여가 큰 페이지부터 재도입한다. 배치는 실측 데이터에 근거하고, 반응형 단일 뷰 구조를 깨지 않으면서 기기별 성과를 분리 추적할 수 있게 한다.
✨ 주요 변경사항
배치 원칙 (전 페이지 공통)
- UA별 슬롯 분리: 기기별 성과를 분리 추적하기 위해 모바일·데스크톱 슬롯을 나눈다. 각 광고 컴포넌트가 내부에서
useDevice(서버가 layout에서 주입한isMobile)로 조건부 렌더한다. 미노출 유닛을 DOM에 넣고 CSS로 숨기는 것은 AdSense 정책 위반이므로, CSS 분기 대신null반환(조건부 렌더)을 쓴다. 서버 값 기반이라 CSR 전환이 없다. - 콘텐츠 반응형 단일 유지: 뷰 레이아웃은 반응형 단일 그대로 두고, 그 안의 광고 슬롯만 기기별로 갈라 렌더한다.
- 미매칭 시 접힘:
useAdSlotEffect훅이MutationObserver로data-ad-status="unfilled"를 감지해, 광고가 안 채워지면 컨테이너를 접어 빈 공간을 없앤다(고정 height 슬롯의 빈 영역 방지). 전역 적용. - 슬롯 상수 SSOT: 슬롯 ID를
src/constants/adSense.ts에 상수로 모아 관리한다(하드코딩 지양).
페이지별 배치
| 페이지 | 위치 | 형식 |
|---|---|---|
| 상세(detail) | 능력치 후 / 기술표 후 / 최하단 3지점 | 320×100·728×90 / 반응형 |
| 상성계산기(type-effectiveness) | 타입 선택↔결과 사이 1개 | PC 인아티클 / 모바일 320×100 |
| 기술도감 목록(moves) | 페이지 헤더 아래 | PC 970×250 / 모바일 320×100 |
| 기술도감 상세(moves/[id]) | 설명 아래 상단(디스플레이) + 그리드 뒤 하단(인아티클) | — |
| 상세 기술탭(detail/[id]/moves) | 히어로 아래·탭 위 | 970×250 / 320×100 |
| 챔피언스(홈·도감·티어·상세·대회) | 각 콘텐츠 소비 지점(상단 재배치) | PC 인아티클/300×250 / 모바일 320×100 |
| 도감 리스트(list) | 필터바 아래 | PC 인피드 / 모바일 320×100 |
| 특성 도감(ability 목록·상세) | 페이지 헤더 아래 | PC 970×250 / 모바일 320×100 |
| 퀴즈(quiz 허브·4종 결과) | 허브 헤더 아래 / 결과 상단 | 가로형 / 320×100 |
데이터 기반 판단 사례
- 상단 vs 하단: 상세 페이지 실측에서 모바일 하단 배너 CTR 2.02%(수익 1위) vs 상단 배너 CTR 0.06%로 34배 차이가 났다. 이를 근거로 detail은 "콘텐츠 소비 후 섹션 사이"에 배치했다. 다만 챔피언스처럼 노출 절대량이 부족한 페이지는 노출×RPM 관점에서 상단 조기 노출로 재배치해 개선을 시도했다(CTR 저조 원인이 위치인지 유입 부족인지 단정할 수 없으므로 배포 후 데이터로 검증).
- 인피드 제외: moves·list의 카드 사이 인피드는 과거 커버리지·CTR이 붕괴(PC $0.08·모바일 $0.17)해 재도입하지 않고 상단 배너로 대체했다.
- 상성계산기 하단 제거: 도구성 페이지라 표 끝까지 스크롤해 하단에 도달하는 사용자가 거의 없어(PC 하단 클릭 0) 상단 1개만 유지했다.
🔧 기술적 세부사항
- 신규 광고 컴포넌트: 페이지별 통합 컴포넌트(
DetailStatsBanner·TypeEffectivenessTopBanner·MovesListTopBanner·ChampionsInContentBanner·ListTopBanner·AbilityListTopBanner·QuizResultTopBanner등) — 내부useDevice분기. - 슬롯 상수:
DETAIL_INCONTENT_SLOTS·MOVES_DETAIL_TOP/BOTTOM_SLOTS·DETAIL_MOVES_SLOTS·CHAMPIONS_SLOTS·QUIZ_RESULT_SLOTS등을adSense.ts에 정의. - 훅:
useAdSlotEffect에 unfilled 컨테이너 접힘 로직 추가(전역). - 레거시 정리: 각 페이지 재도입 시 사용처 없이 남아있던 기존
adSlot컴포넌트(Desktop/Mobile 2벌)를 삭제하고 통합 컴포넌트로 대체. - layout.tsx: AdSense 스크립트를 다른 스크립트보다 먼저 로드하도록 순서 조정.
📌 참고 사항
- 개발 환경(
NODE_ENV !== production)에서는 AdSense 스크립트가 로드되지 않아 실제 광고가 표시되지 않는다. 배치 위치·규격 확인은 각 페이지에 대응하는 콘솔 미리보기 스니펫으로 수행했다. - 신규 슬롯은 발급 완료 후 상수에 반영했으며, 미발급 슬롯('')은 컴포넌트가
null을 반환해 렌더되지 않는다(빈 광고 요청 방지). ads.txt는 CloudFront에서 이미 정상 서빙 중(publisherca-pub-6481622724376761)이라 별도 조치하지 않았다.
