크로스 오리진 iframe 비디오 감지율을 절반 이상 끌어올린 방법
목차
iframe 안의 비디오, 왜 못 잡나
부모 document에서 querySelectorAll('video') 돌리면 같은 오리진 iframe 안의 비디오까지는 그래도 contentDocument로 파고 들어갈 수 있음. 근데 크로스 오리진 iframe은 브라우저가 막아놔서 접근 자체가 불가. 외부 임베드 페이지가 많은 사이트일수록 감지율이 뚝 떨어짐. 이번에 작업하면서 누락률 측정해보니 임베드 비중 큰 페이지에서 절반 이상 못 잡고 있었음.
postMessage 릴레이로 우회
각 iframe 컨텍스트에 감지 스크립트를 주입해두고, 부모로 메시지 쏘는 방식으로 풀었음.
// iframe 측 — 감지되면 부모에 보고
const payload = { type: 'video:detected', src, duration, currentTime };
window.parent.postMessage(payload, '*');
// 부모 측 — origin 화이트리스트 확인 후 릴레이
window.addEventListener('message', (e) => {
if (!ALLOWED_ORIGINS.has(e.origin)) return;
if (e.data?.type !== 'video:detected') return;
detector.merge(e.data);
});
릴레이 도입하면서 신경 쓴 포인트:
*로 보내되 부모는 origin 검증 필수 (안 그러면 아무 사이트나 페이로드 위조)- 같은 비디오 중복 보고 막으려고 src + duration 해시로 dedup
- iframe 깊이 2단 이상 중첩 케이스도 한 번에 떠오르도록 root까지 bubbling
수동 스캔 버튼이 의외로 효자
자동 감지를 mutation observer + interval로 돌리는데도 SPA에서 라우팅된 직후나 lazy load 케이스에서 놓치는 경우가 남았음. 디버깅하다가 그냥 사용자가 누르면 즉시 다시 훑게 하는 버튼을 박았는데, 이게 fallback 그 이상으로 잘 먹힘. 자동이 못 잡은 케이스 리포트 보내달라고 할 때도 "버튼 한 번 누르고 다시 시도" 한 줄로 끝남.
| 케이스 | 자동 감지 | postMessage 릴레이 | 수동 버튼 |
|---|---|---|---|
same-origin <video> |
즉시 | - | 보강 |
| 크로스 오리진 iframe | 불가 | 처리 | 보강 |
| SPA 라우팅 직후 | 일부 누락 | 일부 누락 | 강제 재스캔 |
| 동적 lazy load | 타이밍 의존 | 타이밍 의존 | 즉시 |
남은 숙제
- iframe 주입 스크립트 실패 시 부모가 그걸 알 길이 없음 → heartbeat 핑 추가 검토
- origin 화이트리스트가 하드코딩이라, 파트너 추가될 때마다 빌드 필요. 런타임 설정으로 빼야 함
- 수동 버튼이 너무 잘 먹는 게 오히려 신호 — 자동 감지의 누락 패턴을 텔레메트리로 더 모아서 자동 쪽을 끌어올리는 게 다음 목표
iframe 보안 모델 우회는 결국 "메시지 채널을 정해서 양쪽이 합의하는 것"으로 귀결됨. 보안과 기능이 팽팽한 영역이라 감지 욕심으로 origin 검증 느슨하게 풀면 바로 사고 나는 부분이라 조심.
다음
댓글 0
첫 댓글 달아줘.