Obsidian Publish 쿠팡 파트너스(배너) 추가 방법 및 오류

요약

  • 목적: gurumii.com에 쿠팡 파트너스 배너를 삽입하고, 광고 차단기 활성 시 빈 공간/깜빡임 없이 완전히 접기(display:none) 및 관련 문구 노출을 제어합니다.
  • 핵심: 로드 성공 시에만 표시(show‑on‑load) + 차단/에러/타임아웃이면 래퍼를 완전히 접고 재삽입을 억제.

문제 정리

  • #page-banner-adad 키워드 식별자는 코스메틱 필터에 쉽게 걸림 → 새 식별자 필요.
  • 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-viewMutationObserver를 두되, 차단이 감지된 세션에서는 재삽입을 중단합니다.

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)

  1. publish.js, publish.css를 커스텀 자산으로 연결.
  2. 캐시 무효화가 필요하면 ?v=20250913처럼 쿼리스트링을 붙여 강제 갱신.
  3. 전체 새로고침(Shift+Reload) 후 체크리스트로 동작 확인.