통계를 티스토리 서브도메인까지 덮으려다 — 아직 못 덮었습니다
apex(birchholt.com) 아래에 티스토리 블로그 두 개를 서브도메인으로 붙여 운영합니다. apex 는 앞에 아무것도 안 붙은 기본 주소이고, 서브도메인은 그 앞에 이름을 하나 더 붙인 주소입니다. 통계는 셋을 한 대시보드에서 보려 했습니다. Cloudflare Web Analytics 는 같은 apex 면 site tag 하나를 재사용할 수 있어서 토큰 하나면 끝날 줄 알았습니다. site tag 는 어느 사이트의 방문인지 구분해 주는 식별값입니다.
재사용 규칙은 공식 FAQ 에 적혀 있습니다 — “if the apex domain … is the same, you can
use the same site tag … we validate the hostname with postfix matching”. 접미사 비교라
fooexample.com 처럼 문자열 끝만 겹쳐도 통과한다는 단서도 문서가 함께 달아 둡니다.
Cloudflare Web Analytics FAQ
(2026-09-02 본문 확인).

결과부터 말하면 아직 못 덮었습니다. apex 는 잡히는데 티스토리 쪽은 비콘이 404 로 떨어집니다. 비콘은 방문 기록을 통계 서버로 보내는 작은 스크립트입니다. 후보를 둘 잘라냈고 셋째는 시험해보기 전입니다.
(그 셋째 가설은 나중에 시험해봤고 맞았습니다 — 무엇을 바꿔서 덮었고 대신 무엇을 잃었는지는 뒤에 적었습니다.)
먼저 틀렸던 것 — 토큰이 비어 있는데 통계는 쌓이고 있었습니다

2026-09-01 에 템플릿에 비콘 자리만 만들어 두고 토큰 값(cfAnalyticsToken)은 비워뒀습니다.
토큰이 비어 있으면 비콘 태그 자체가 출력되지 않게 짜 뒀으니, apex 통계도 아직 0 일 거라고
생각했습니다.
2026-09-02 에 대시보드를 열어보니 birchholt.com 이 8일 전부터 Automatic setup 으로
등록돼 있었고 최근 24시간 기준 20 PV / 6 visits 가 이미 쌓여 있었습니다.
PV 는 페이지가 열린 횟수, visits 는 방문 횟수입니다.
라이브 HTML 을 브라우저인 것처럼 요청해 받아 </body> 직전을 봤더니 제가 넣지 않은 태그가
있었습니다. Cloudflare 가 응답이 자기 서버를 지나가는 동안 직접 끼워 넣은 태그였습니다.
<script type="module"
src=".../beacon.min.js/v3d52b479..."
integrity="sha512-d9sL6GJLXn6..."
data-cf-beacon='{"token":"732288da...","r":1}'></script>
| 자동 주입 | 수동 삽입 | |
|---|---|---|
| 스크립트 URL | 버전 고정 URL + SRI 동반(받은 파일이 바뀌었는지 검사) | 버전 없는 beacon.min.js → SRI 불가 |
type="module" | 자동 부착 | 직접 부착 |
| 닿는 범위 | Cloudflare 를 지나는 요청만 | HTML 에 넣은 곳 전부 |
type="module" 은 수동일 때 빼먹으면 안 된다고 공식 문서 원문에 적혀 있습니다.
“For customers using the manual embed approach, you will need to add
type="module"to the<script>tag manually.”
출처: Cloudflare Web Analytics FAQ (2026-09-02 본문 확인). 같은 FAQ 가 수동 삽입에는 무결성 검사를 붙일 방법이 없다고도 못박습니다 — 비콘 파일에 버전을 고정해 주지 않기 때문입니다.
module 은 기본이 defer 라 defer 속성은 붙이지 않았습니다. HTML 을 다 읽은 뒤에
실행한다는 뜻입니다. 공백과 줄바꿈을 지워 파일을 줄이는 minify 를 거친 뒤에도
태그가 살아 있는 것을 만들어진 HTML 로 확인했습니다.
2026-09-22 재확인 — 라이브 HTML 을 받아 비콘 <script> 태그만 뽑아 보면 minify 로
속성 따옴표까지 지워진 상태에서 type=module 이 그대로 남아 있습니다.
티스토리에는 자동 주입이 닿지 않습니다

티스토리에 개인 도메인을 붙이려면 Cloudflare 프록시를 꺼야 합니다(앞선 글에 적었습니다). 프록시는 방문자의 요청이 Cloudflare 서버를 한 번 거쳐 가게 하는 설정입니다. 프록시가 꺼져 있으면 요청이 Cloudflare 를 통과하지 않고 응답 HTML 을 만질 주체가 없습니다.
그래서 각 스킨(블로그 화면을 만드는 HTML 틀)의 </body> 직전에 같은 토큰으로
비콘을 직접 넣었습니다.
여기서 막혔습니다. 비콘이 쏘는 https://cloudflareinsights.com/cdn-cgi/rum 이
POST 404 를 돌려줍니다.
메서드로 1번을, 토큰으로 2번을 잘라냈습니다

404 하나를 놓고 의심할 것이 셋이었습니다.
- 이 호스트명(misiq.birchholt.com 같은 주소)이 사이트에 등록되지 않았다
- 토큰이 틀렸거나 서브도메인에 안 먹는다
- 수집 경로 자체가 이 사이트에서 안 열려 있다
셋을 한 번에 볼 수 없으니 한 번에 하나씩만 바꿔 쐈습니다(방법은 앞선
글에서 데면서 배웠습니다).
쏜 호스트는 서브도메인 하나(misiq)입니다. 나머지 한 곳에도 같은 코드 조각을 넣었으니
결과도 같으리라고 봤을 뿐, 따로 쏴서 확인하지는 않았습니다.
curl -i -X OPTIONS https://cloudflareinsights.com/cdn-cgi/rum \
-H 'Origin: https://misiq.birchholt.com' \
-H 'Access-Control-Request-Method: POST'
# → 200
# → access-control-allow-origin: https://misiq.birchholt.com
200 이고 access-control-allow-origin 에 제 서브도메인이 그대로 실려 옵니다.
이 OPTIONS 요청은 preflight 입니다. 브라우저가 진짜 요청을 보내기 전에 「보내도 되느냐」를
먼저 묻는 확인 요청이고, 여기에는 토큰이 실리지 않으니 이 응답은 토큰과 무관합니다.
등록되지 않은 호스트라면 이렇게 되돌려줄 이유가 없을 겁니다. 요청을 보낸 출처를
그대로 되비추는 구현도 있으니 이것만으로 확정할 수는 없습니다. 호스트명 등록도, 주소
뒷부분을 맞춰보는 판정도 정상으로 보고 1번을 내렸습니다. 같은 주소에서 OPTIONS 만 200,
POST 만 404 라면 요청이 들어가는 길은 살아 있고 뒤에서 받아 처리하는 쪽이 안 열려 있습니다.
측정: 2026-09-02. 2026-09-22 에 같은 명령을 다시 보내도 HTTP/2 200 과 같은
access-control-allow-origin 값이 그대로 돌아옵니다.
다음은 토큰만 바꿨습니다. 아무 값이나 넣어도 진짜 토큰과 똑같이 404 였습니다. 토큰이 원인이면 응답이 달라야 합니다. 응답이 같았으니 애초에 토큰을 보지 않고 끊습니다(2번 탈락).
| 바꾼 축 | 고정한 것 | 결과 | 읽히는 것 |
|---|---|---|---|
| 메서드 → OPTIONS | URL·요청 출처(토큰 없음) | 200 + 허용 출처에 내 서브도메인 | 호스트 등록·주소 대조 정상으로 추정 |
| 토큰 → 가짜 값 | URL·메서드·본문 형식 | 404(진짜와 동일) | 토큰을 보지 않음 |
URL 3종(맨 주소·?token=·끝 슬래시) | 메서드·토큰 | 전부 404 | 주소 오타 아님 |
요청 형태는 beacon.min.js 원본에 맞췄습니다 — content-type: application/json,
보내는 본문의 키 이름은 siteToken, 성공 시 204 기대(sendObjectBeacon 구현 확인).
보내는 쪽 문제는 아닙니다.
남은 가설은 하나인데, 아직 확인하지 못했습니다

남은 3번은 사이트가 Automatic setup 이라 수동 수집 경로가 열려 있지 않다는 가설입니다.
자동은 자기 도메인의 /cdn-cgi/rum 으로 쏘고 프록시가 그 자리에서 처리합니다.
수동은 cloudflareinsights.com 으로 쏘는데 티스토리는 수동밖에 못 씁니다.
이 두 줄은 공식 FAQ 에 각각 있습니다 — 자동은 “report stats back to your own domain’s /cdn-cgi/rum endpoint”, 수동은 “report back to cloudflareinsights.com/cdn-cgi/rum endpoint”. 프록시를 안 거치는 DNS-only 도메인은 자동 설치를 쓸 수 없다는 문답도 따로 있습니다. Cloudflare Web Analytics FAQ (2026-09-02 본문 확인). 다만 “그래서 404 가 난다"까지 이어 붙여 놓은 문장은 문서에 없습니다 — 여기부터는 제 추정입니다.
대시보드 Manage site 에서 「Enable with JS Snippet installation」 으로 바꾸면 풀릴 것 같은데 아직 안 바꿔봐서 미확정입니다.
모드를 바꾸는 순간 자동 주입이 멈추므로, apex 토큰을 채워 배포하는 쪽을 먼저 하고 전환을 나중에 두기로 했습니다. 반대로 하면 그 사이 apex 통계가 빌 수 있습니다.
이 순서 논증은 검증해보지 못했습니다. 구멍이 둘 보입니다. 3번 가설이
맞다면 미리 배포해둔 apex 의 수동 비콘도 전환 전까지는 똑같이 404 라 공백을 못 메웁니다.
그리고 손으로 넣은 비콘은 <head> 안에, 자동 주입 태그는 </body> 직전에
들어갑니다. 문서 순서로는 수동이 먼저 실행됩니다. 아래 줄이 정말 두 번째 실행을
막는 것이라면, 막히는 쪽이 멀쩡히 돌던 자동 비콘일 수 있습니다.
중복 집계가 날까 싶어 beacon.min.js 를 열었다가 이 줄이 눈에 걸렸습니다.
if(v&&"single"===v.load)return;
두 번째 실행을 막아주는 장치처럼 보여서 겹치는 상태로 배포하기로 했습니다. 다만 v 가
어디서 채워지고 load 를 누가 "single" 로 채워 넣는지까지는 못 짚었고 두 태그가 실제로 한 번만
집계되는지도 대시보드로 들여다보지 못했습니다.
정리

- 자동 설정은 프록시가 있어야 닿습니다. 프록시를 끈 티스토리에는 안 들어갑니다
- 가짜 값과 진짜 값의 응답이 같으면 그 값은 판정에 쓰이지 않습니다
- 배포 순서를 정한 근거가 미확인 가설에 기대고 있으면 그 순서도 검증되지 않았습니다
- 남은 가설은 아직 확인하지 못했습니다. 지금 대시보드에 잡히는 것은 apex 뿐입니다