Obsidian Publish 쿠팡 파트너스(배너) 추가 방법 및 오류
요약
- 목적: gurumii.com에 쿠팡 파트너스 배너를 삽입하고, 광고 차단기 활성 시 빈 공간/깜빡임 없이 완전히 접기(display:none) 및 관련 문구 노출을 제어합니다.
- 핵심: 로드 성공 시에만 표시(show‑on‑load) + 차단/에러/타임아웃이면 래퍼를 완전히 접고 재삽입을 억제.
문제 정리
#page-banner-ad 등 ad 키워드 식별자는 코스메틱 필터에 쉽게 걸림 → 새 식별자 필요.
- iframe 차단 시에도 관찰/재삽입 로직이 있으면 깜빡임이 생기거나 래퍼가 공간을 차지해 빈 칸이 남음.
목표
- 광고 차단 시 자리를 전혀 차지하지 않음(display:none).
- 배너가 보일 때만 디스클레이머(파트너스 안내 문구)를 노출.
- 식별자 중립화로 코스메틱 필터 매칭 최소화.
적용 파일
publish.js: 배너 주입, 로드/차단 감지, 사이징, 억제 로직.
publish.css: 래퍼 레이아웃, 디스클레이머 스타일, 접기 규칙.
구현 구조
1) 식별자 중립화
- ID:
page-partner-slot
- 클래스:
.partner-wrapper (래퍼), .partner-disclaimer (디스클레이머)
2) 삽입 위치
- 본문 컨테이너(
.markdown-reading-view/.markdown-preview-view)의 첫 번째 h1 바로 뒤에 삽입합니다.
3) Show‑on‑load & 차단 대응
- iframe을 동적으로 생성하되 초기 크기를
width=0, height=0(inline style 포함)으로 두고, load 이벤트가 오기 전까지는 래퍼를 접은 상태로 유지합니다.
load 도착 후 **코스메틱 차단 여부(display/visibility)**를 한 번 더 점검하고, 정상 노출 가능할 때만 래퍼 표시 및 실제 사이징을 수행합니다.
error 또는 타임아웃(1.8s) 발생 시에는 래퍼를 완전히 접고(display:none) 현재 뷰 세션 동안 재삽입을 억제합니다.
4) 크리에이티브 선택 로직
- 모바일: 320×50, 데스크톱: 728×90.
- 내부 콘텐츠 폭이 320px 초과면 데스크톱, 아니면 모바일을 선택합니다.
5) 사이징(리사이즈 대응 포함)
- 현재 iframe의
id(모바일/데스크톱)에 맞춘 **종횡비(320×50 / 728×90)**로 계산해 inline width/height를 갱신합니다.
- src의
width/height 쿼리를 함께 업데이트하되 변화가 미미하면 리로드를 피하며(깜빡임 감소) CSS 높이도 일치시킵니다.
- 래퍼에
ResizeObserver를 연결해 콘텐츠 폭 변화(레이아웃/폰트/뷰포트 변경 등)에도 크기를 유지합니다.
6) 이벤트/옵저버
- 초기 1회 시도 +
hashchange, popstate, orientationchange, pageshow, resize에서 재검사/리사이징.
.markdown-preview-view에 MutationObserver를 두되, 차단이 감지된 세션에서는 재삽입을 중단합니다.
DOM 삽입 위치(요약)
- 컨테이너 탐색:
.markdown-reading-view/.markdown-preview-view → 내부 .markdown-reading-view-content 또는 .markdown-preview-sizer 우선, 없으면 뷰 루트.
- 삽입 지점: 첫
h1의 다음 형제 노드.
CSS 규칙
/* 래퍼: 콘텐츠 폭을 채우고 디스클레이머 공간 확보 */
#page-partner-slot.partner-wrapper {
margin: 16px 0;
width: 100%;
display: block;
line-height: 0; /* iframe 주변 baseline 간격 제거 */
padding-bottom: 0.75rem; /* 디스클레이머 공간 확보 (margin-collapsing 회피) */
}
/* iframe: JS가 px 단위로 inline 사이징 → 기본은 auto */
#page-partner-slot.partner-wrapper iframe {
display: block; /* baseline 간격 방지 */
margin: 0 auto; /* 콘텐츠 컬럼 중앙 정렬 */
border: none;
width: auto; /* JS가 정확한 px width 지정 */
max-width: 100%; /* 컬럼 넘침 방지 */
height: auto; /* JS가 정확한 px height 지정 */
}
/* 디스클레이머(배너 하단 안내 문구) */
#page-partner-slot .partner-disclaimer {
margin-top: 1px;
margin-bottom: 0;
color: var(--text-faint);
font-size: 0.8125rem;
line-height: 1.25;
text-align: left;
}
@media (min-width: 600px) {
#page-partner-slot.partner-wrapper { padding-bottom: 1rem; }
}
/* JS가 data-collapsed=true를 달면 완전 접기 */
#page-partner-slot[data-collapsed="true"] { display: none !important; }
/* :has 지원 시, iframe이 0 크기면 자동 접기 (점진적 향상) */
#page-partner-slot.partner-wrapper:has(> iframe[width="0"]),
#page-partner-slot.partner-wrapper:has(> iframe[height="0"]) { display: none !important; }
검증 체크리스트
- 광고차단 ON: 빈 공간/깜빡임 없음, 래퍼는
display:none(접힘), 디스클레이머 비노출.
- 광고차단 OFF: 배너 정상 노출 및 리사이징, 디스클레이머 표시.
배포(Obsidian Publish)
publish.js, publish.css를 커스텀 자산으로 연결.
- 캐시 무효화가 필요하면
?v=20250913처럼 쿼리스트링을 붙여 강제 갱신.
- 전체 새로고침(Shift+Reload) 후 체크리스트로 동작 확인.