
방문자 수가 궁금했다. 그런데 Google Analytics를 달고 싶지는 않았다. 쿠키 동의 배너, 제3자 데이터 전송, 무거운 스크립트 — 전부 싫었다.
Umami는 셀프호스팅 가능한 오픈소스 웹 분석 도구다. 쿠키를 쓰지 않고, 개인 식별 정보를 수집하지 않아서 GDPR 동의 배너가 필요 없다. 이미 홈랩에 Umami를 운영 중이었으니 museck.com에 연동하기만 하면 됐다. 간단할 줄 알았다.
museck.com은 Cloudflare를 통해 서빙되는 공용 도메인이다. Umami는 홈랩에서 Tailscale을 통해 umami.xssh.org로 접근 가능한데, 이건 사설 네트워크 IP로 해석된다. Chrome의 Private Network Access 정책이 이 조합을 차단한다.
공용 웹사이트(museck.com)가 사설 네트워크의 리소스(umami.xssh.org)를 로딩하려는 것이니 보안상 당연히 막는 게 맞다. 문제는 해결 방법이다.
브라우저가 직접 사설 네트워크에 접근하는 게 문제라면, 서버가 대신 접근하면 된다. Next.js의 rewrites 기능은 클라이언트 요청을 서버에서 다른 URL로 전달해 준다. 클라이언트는 같은 도메인에서 리소스를 받는다고 인식하고, 실제 요청은 서버가 홈랩 네트워크 내에서 처리한다.
// next.config.mjs
async rewrites() {
return [
{
source: '/umami/:path*',
destination: 'https://umami.xssh.org/:path*',
},
]
},/umami/*로 들어오는 모든 요청을 umami.xssh.org로 전달한다. 스크립트 로딩뿐 아니라 이벤트 전송(API 호출)까지 프록시되니 별도 설정이 필요 없다.
레이아웃에 스크립트를 추가하는 것도 간단하다.
// src/app/(frontend)/layout.tsx
<Script
async
src="/umami/script.js"
data-website-id="d38276b1-..."
strategy="afterInteractive"
/>strategy="afterInteractive"는 페이지가 먼저 렌더링된 후 스크립트를 로딩한다. 분석 스크립트가 초기 로딩 속도에 영향을 주지 않는다.
물론 트레이드오프가 있다. GA4의 고급 기능(전환 추적, 이커머스 분석 등)은 없다. 하지만 기술 블로그의 트래픽 분석에는 페이지뷰, 레퍼러, 접속 경로면 충분하다.
설정 2개, 코드 몇 줄이면 프라이버시를 존중하는 웹 분석이 가능하다. 셀프호스팅 인프라가 있다면 Umami + Next.js rewrites 조합을 추천한다. 광고 차단기에도 잘 살아남는 건 덤이다.
Umami는 쿠키를 사용하지 않고 개인 식별 정보를 수집하지 않기 때문에 GDPR 동의 배너 없이 사용할 수 있다. 방문자 데이터는 해시 처리되어 개별 사용자를 추적하지 않는다.
스크립트 로딩은 afterInteractive 전략으로 페이지 렌더링을 블로킹하지 않는다. 프록시 요청은 서버 사이드에서 처리되므로 클라이언트 입장에서는 같은 도메인에서 스크립트를 로딩하는 것과 동일하다.