iframe 안의 분석 스크립트: 자사 사이트를 창으로 띄웠을 때 생기는 일
저희 홈페이지를 저희가 만든 브라우저 안 데스크톱(os.duolabs.co.kr)에 창 하나로 띄웠습니다. 데모를 한 번 열어 본 사람이 방문 기록에는 두 번 찍혔습니다. 처음에는 창을 두 개 여니까 그렇겠거니 했는데, 세어 보니 문제는 개수가 아니라 그 숫자가 우리 통계 전부를 통과하고 있다는 쪽이었습니다.
창 하나를 열었을 뿐인데 방문이 두 건
iframe은 화면 한 칸을 빌려주는 장치가 아닙니다. 그 안에서 페이지 전체가 처음부터 다시 살아납니다. 스크립트도 예외가 아닙니다.
저희 홈페이지에는 집계가 네 가지 붙어 있습니다. 자체 방문 기록, GA4, 네이버 검색광고 전환 스크립트, Vercel 분석입니다. 네 곳 어디에도 지금 프레임 안인지 보는 코드가 없었습니다. 그럴 이유가 없었기 때문입니다. 우리 사이트를 창에 띄우는 것도 우리였고, 그 창을 만든 날에는 아무도 통계를 떠올리지 않았습니다.
데스크톱으로 넘어오면 소개 페이지 창과 폰 시뮬레이터 두 개가 함께 열립니다. 방문 한 번이 시작부터 두 건입니다.
유입 경로가 자기 서브도메인으로 덮이는 자리
숫자가 부풀려지는 것은 사실 덜 아픈 쪽입니다. 더 아픈 것은 그 방문에 붙는 꼬리표입니다.
창 안에서 열린 페이지의 리퍼러는 데스크톱 쪽 주소입니다. 광고를 보고 들어온 사람이 데스크톱을 구경하는 순간, 그 사람의 유입 경로가 우리 서브도메인에서 온 것처럼 바뀔 수 있습니다. 광고비를 어디에 썼는지 판단하는 근거가 우리 자신의 화면 조작으로 덮이는 셈입니다.
가장 위험한 쪽은 광고 전환
GA4 숫자가 틀리면 보고서를 잘못 읽습니다. 그건 사람이 알아채면 됩니다. 네이버 검색광고 전환 스크립트는 다릅니다. 전환 신호는 광고 플랫폼이 다음 노출을 결정하는 데 씁니다. 잘못된 전환이 쌓이면 보고서가 아니라 돈 쓰는 방향이 틀어집니다.
검색 순위와 무관한 이유
이 작업은 호출이 늘어나면 오히려 SEO에 좋은 것 아니냐는 질문에서 시작했습니다. 아닙니다.
검색 순위는 크롤러가 직접 받아 가는 페이지로 정해집니다. 우리가 심은 스크립트가 보내는 숫자는 거기에 들어가지 않습니다. 구글이 순위에 쓰는 실사용 속도 데이터도 마찬가지입니다. 그 데이터는 최상위 페이지 이동만 세기 때문에, 창 안에서 일어난 로딩은 애초에 집계 대상이 아닙니다. 순위에는 득도 실도 없고, 통계에만 실이 남습니다.
네 곳을 각각 다르게 막은 까닭
판정은 한 줄입니다. window.self !== window.top이면 남의 페이지 안입니다. 우리 데스크톱 안인지까지 가릴 필요는 없었습니다. 다른 사이트가 우리를 품은 경우도 우리 방문자는 아니니까요.
막는 자리는 넷이 다 달랐습니다.
| 대상 | 막은 자리 |
|---|---|
| 자체 방문 기록 | 기록 함수에 들어가기 전에 멈춤 |
| GA4 | 페이지뷰를 내보내는 설정 호출을 건너뜀 |
| 네이버 전환 | 방문 알림 함수를 부르지 않음 |
| Vercel 분석 | 보내기 직전에 이벤트를 버림 |
처음에는 넷 다 똑같이 하려고 했습니다. 프레임이면 컴포넌트를 아예 그리지 않으면 되지 않나 싶었습니다. 두 가지가 걸렸습니다. 서버가 그린 결과와 브라우저가 그린 결과가 달라져 화면이 어긋나고, 그 시점에는 이미 스크립트가 실려 첫 집계를 보낸 뒤일 수 있습니다. 그래서 Vercel 쪽만 보내는 순간에 거르는 방식으로 갈라졌습니다. 같은 목적이라고 같은 방법이 되지는 않았습니다.
로컬에서 재현되지 않은 것
고치고 나서 로컬에서 확인하려 했는데 되지 않았습니다. 개발 서버를 프레임에 넣으면 안쪽 페이지의 자바스크립트가 끝까지 올라오지 않았습니다. 그러면 막아서 안 나간 것과 애초에 실행되지 않은 것이 구분되지 않습니다. 로컬에서 확인한 것은 최상위에서 기존 집계가 그대로 나간다는 사실 하나였습니다. 새 코드가 정상 방문자까지 막아 버리지는 않았다는 것만 본 셈입니다.
나머지는 배포한 뒤 운영에서 한 번 열어 확인했습니다. 창 안에서는 데이터 전송이 0건이었고, 같은 브라우저로 홈페이지를 직접 열었을 때는 자체 기록과 구글 수집 요청이 그대로 나갔습니다. 대조군을 같이 본 것이 이번 확인에서 가장 중요한 부분이었습니다. 안 나간다는 것만 보면 전부 막혔을 가능성을 배제하지 못합니다.
여전히 내려받는 두 파일
데이터는 0건이지만 스크립트 파일 자체는 여전히 내려받습니다. gtag.js와 wcslog.js 두 개입니다. 이것까지 없애려면 스크립트 태그를 조건부로 넣어야 하고, 그러면 앞에서 피한 화면 어긋남 문제로 되돌아갑니다. 창 하나당 요청 두 건이라 지금은 두기로 했습니다. 나중에 창을 여는 사람이 많아지면 다시 볼 자리입니다.
함께 읽기
- WebP가 JPEG보다 커질 때: 사진 종류별 WebP·AVIF 실측인쇄기 롤러 견적 사이트를 만들면서 화면에 나가는 사진을 전부 WebP로 정했습니다. 제품 사진 네 장으로 재 보고 내린 결론이었습니다. 그 뒤에 설계도 사진 세 장이 들어왔고, 같은 스크립트에 그대로 태웠습니다. 이 글을 쓰려고 다시 재 보니 그중 두 장은 WebP가 JPEG보다 컸습니다.
- 웹 퍼블리셔와 프론트엔드 개발자 차이: 산출물이 갈리는 지점견적서에 이런 두 줄이 나란히 놓이는 경우가 있습니다.
- GA4 쿠키 없이 쓰기: client_id를 직접 넘기는 구성방문 분석은 하고 싶은데 쿠키 동의 팝업은 만들기 싫었습니다. 배너를 하나 붙이면 화면에 층이 하나 더 생기고, 동의 상태를 저장하고 갱신하고 철회까지 받는 코드가 따라옵니다. 방문자가 하루 수십 명인 회사 사이트에 그만한 장치를 두는 것은 과합니다.
- Next.js 웹앱을 Electron 데스크톱 앱으로 만들기 전에 따져볼 것사내 웹 도구를 쓰다 보면 어느 순간 "이거 그냥 데스크톱 앱으로 만들면 안 되나"라는 말이 나옵니다.
- Leaflet 지도가 느려지는 3가지 원인: React key, SVG 렌더러, 가드 위치지도 위에 H3 육각 격자를 얹은 화면을 만들었습니다. 셀을 누르면 인접한 여섯 셀이 함께 칠해지는, 영업 구역을 나눠 보는 화면입니다.