사이드프로젝트 slecs

iframe 내부 영상 감지 누락 수정으로 감지율 향상

목차

사이트마다 다른 DOM 구조

영상 감지 기능이 일부 페이지에서 침묵하는 제보가 들어옴. 직접 들어가 보니 페이지 자체엔 분명히 플레이어가 떠 있는데 감지기는 0개를 리턴함. 콘솔 찍어보니 원인이 명확했음 — 플레이어가 iframe 안에 들어 있는 케이스였음.

기존 videoDetector는 top window 기준으로만 querySelectorAll('video, source')를 돌리고 있었음. iframe 내부는 별도 document라서 그 셀렉터로는 절대 잡히지 않음.

iframe 순회 추가

iframe을 모두 모은 뒤 contentDocument로 들어가 동일한 셀렉터를 다시 돌리는 방식으로 바꿈. 단, cross-origin iframe은 접근 시 SecurityError가 터지므로 개별 try-catch로 감쌈. 한 프레임 실패가 전체 감지를 막지 않게 함.

function collectVideos(doc) {
  const found = [...doc.querySelectorAll('video, source')];
  for (const frame of doc.querySelectorAll('iframe')) {
    try {
      if (frame.contentDocument) {
        found.push(...collectVideos(frame.contentDocument));
      }
    } catch (e) {
      debug('skip cross-origin iframe', frame.src);
    }
  }
  return found;
}

재귀로 짠 이유는 iframe 안에 또 iframe이 들어가는 사이트가 실제로 있었기 때문. 깊이 제한은 일단 안 걸었는데, 무한 루프 우려는 같은 document를 중복 방문하지 않도록 WeakSet으로 막아둠.

기본 URL 교체

부수적으로 신규 탭에서 열리는 기본 URL을 자주 쓰는 쪽으로 바꿈. 변경 전후 동작 차이는 이렇게 됐음.

항목 변경 전 변경 후
기본 진입점 빈 신규 탭 자주 쓰는 작업 페이지
첫 감지 시도 사용자 이동 후 진입 직후 자동
평균 클릭 수 3회 1회

별것 아닌 변경인데 본인이 매일 30번씩 같은 URL을 붙여넣고 있다는 걸 깨닫고 그냥 바꿔버림.

디버그 로그 정리

이번 작업하면서 가장 효과 본 건 의외로 디버그 로그였음. App 진입 시점, Browser 탭 활성화/비활성화, videoDetector의 셀렉터 매칭 결과를 한 형식으로 통일함.

  • 모든 로그에 [모듈명] 프리픽스 + epoch ms
  • 감지 경로는 top → iframe 깊이까지 표시
  • prod 빌드에서는 __DEBUG__ 플래그로 일괄 컷

flag 하나로 끄고 켤 수 있게 만드니까 사용자에게 로그 켜달라고 부탁하기도 편해짐. 이전엔 console.log를 그때그때 박았다 지웠다 하느라 커밋이 더러웠음.

남은 숙제

  • cross-origin iframe은 여전히 못 잡음. postMessage로 핸드셰이크 하는 방식 검토 중
  • Shadow DOM 안에 들어간 비디오는 별도 처리 필요
  • iframe 깊이가 4단 이상 들어가는 케이스가 실제 있는지 데이터 더 모아봐야 함

iframe 한 줄 추가하니 감지율이 체감으로 1.5배 됐음. 작은 변경이 가장 ROI 좋다는 걸 또 한번 느낌. 끝

댓글 0

첫 댓글 달아줘.