방문자의 글 페이지와 GoatCounter 사이를 오가는 두 갈래 흐름. 스크립트가 방문을 기록하는 쪽은 기본으로 열려 있고, 글에 조회수를 띄우려고 숫자를 되받아오는 쪽은 사이트 설정을 따로 켜야 한다.

·7분 읽기·업데이트:

방문자 몇 명인지 보려다 구글 애널리틱스를 접었습니다


블로그를 올리고 나서 제일 궁금했던 건 단순했습니다. 누가 오긴 오나?

이게 은근히 확인이 안 됩니다. 지금 블로그는 정적 사이트라 서버가 없고, 서버가 없으니 접속 기록도 없습니다. Cloudflare 대시보드에 요청 수가 뜨긴 하는데, 사람이 온 건지 검색엔진 로봇이 훑고 간 건지 구분이 안 됩니다.

그래서 방문 통계를 붙이기로 했습니다. 처음엔 당연히 구글 애널리틱스를 생각했습니다.

1. GA4를 열어보고 그냥 닫았습니다

가입하고 화면을 봤는데, 제가 알고 싶은 건 “오늘 몇 명 왔고 어떤 글을 봤나” 하나였습니다. 그런데 화면에는 참여 세션, 이벤트 수, 전환, 잠재고객, 탐색 분석 같은 것들이 있었습니다.

큰 서비스를 운영한다면 저게 다 필요한 기능일 겁니다. 글 세 편짜리 개인 블로그에는 아닙니다. 게다가 세 가지가 계속 걸렸습니다.

쿠키 동의 배너. GA4는 쿠키를 씁니다. 방문자 정보를 다루니 개인정보처리방침에 넣을 내용도 늘어나고, 유럽 방문자를 생각하면 동의 배너까지 붙여야 합니다. 글 읽으러 온 사람이 제일 먼저 만나는 게 동의 팝업인 건 좀 그렇습니다.

무게. 애써 이미지 용량을 줄이고 글꼴을 정리해 놓고 분석 스크립트를 무겁게 넣는 건 앞뒤가 안 맞습니다.

“내 방문자 데이터가 구글에 있다.” 이건 취향 문제인데, 저는 제가 만든 걸 제가 들고 있고 싶었습니다.

2. 대신 고른 것

GoatCounter를 붙였습니다. 개인 사이트나 작은 규모의 사이트는 무료로 쓸 수 있습니다.

붙이는 건 이게 전부입니다.

<script
  data-goatcounter="https://내코드.goatcounter.com/count"
  async
  src="https://gc.zgo.at/count.js"
></script>

쿠키를 쓰지 않습니다. 그래서 동의 배너도 필요 없고, 개인정보처리방침에 쓸 내용도 한 줄로 끝납니다. 화면은 딱 필요한 것만 있습니다. 오늘 몇 명, 어떤 글, 어디서 왔는지.

Astro에서는 한 가지만 주의하면 됩니다. 이 스크립트에는 data-goatcounter라는 속성이 붙어 있는데, Astro는 컴포넌트 안의 <script>를 자기 방식대로 묶어서 처리합니다. src 말고 다른 속성이 붙은 스크립트는 건드리지 않는 규칙이 있어서 지금도 동작은 하지만, 그 규칙에 기대기보다는 “손대지 말라”고 적어두는 편이 확실합니다.

<script is:inline data-goatcounter="..." async src="..."></script>

is:inline은 “손대지 말고 그대로 두라”는 표시입니다. 이걸 안 붙여도 지금은 동작하지만, astro check가 힌트를 하나 띄웁니다. 나중에 왜 안 되는지 찾느니 지금 붙여두는 편이 낫습니다.

3. 그런데 통계를 보려면 사이트를 나가야 합니다

붙이고 나니 다음 욕심이 생겼습니다. 글을 읽으러 온 사람도 이 글을 몇 명이 봤는지 볼 수 있으면 좋겠다는 것.

GoatCounter에 그 기능이 있습니다. 글 주소를 붙여서 물어보면 숫자를 돌려줍니다.

https://내코드.goatcounter.com/counter/blog/글주소/.json
{ "count": "1,284", "count_unique": "1,284" }

여기서 첫 번째로 막혔습니다. 아무리 불러도 거부당했습니다.

원인은 설정이었습니다. 이 기능은 기본이 꺼져 있습니다. 사이트 설정에 “Allow adding visitor counts on your website”라는 항목이 있고, 이걸 켜야 열립니다. 방문 통계가 의도치 않게 공개되는 걸 막으려고 그렇게 해둔 거라, 켜는 순간 “이 숫자는 누구나 볼 수 있다”는 데 동의하는 셈입니다. 개인 블로그 조회수라 저는 켰습니다.

4. 그리고 “조회 0”

설정을 켜고 다시 배포했더니, 이번엔 숫자가 나왔습니다. 아직 아무도 안 본 글에도요.

조회 0.

처음 쓴 코드와 고친 코드 비교. 처음 코드는 응답값이 비었는지만 확인했는데 문자열 "0"이 참이라 걸러지지 않아 화면에 조회 0이 표시됐고, 고친 코드는 숫자로 바꿔서 0이면 그 줄 자체를 감춘다.

제가 쓴 코드는 이랬습니다.

const raw = data.count;
if (!raw) return;
target.textContent = `조회 ${raw}`;

값이 없으면 그냥 넘어가라는 뜻으로 쓴 줄인데, 안 걸렸습니다. count가 숫자가 아니라 문자열이기 때문입니다. 1284가 아니라 "1,284"로 옵니다. 천 단위 쉼표를 찍어서 주려고 그렇게 되어 있어요.

그러면 조회수가 0일 때 오는 값은 숫자 0이 아니라 문자열 "0" 입니다. 그리고 JavaScript에서 빈 문자열이 아닌 문자열은 전부 참입니다. "0"도 참입니다. 그래서 if (!raw)를 그냥 통과했습니다.

const n = Number(String(raw).replace(/[^0-9]/g, ''));
if (!n) return;
target.textContent = `조회 ${raw}`;

숫자가 아닌 문자를 다 떼어내고 숫자로 바꾼 다음에 판단하게 했습니다. 쉼표가 낀 "1,284"도 이러면 1284가 됩니다. 0이면 그 줄 자체를 안 보여줍니다.

아무도 안 본 글에 “조회 0”을 붙여두는 건, 굳이 안 해도 되는 자기소개입니다.

5. 목록 페이지에는 안 넣었습니다

글 목록에도 조회수를 띄울까 하다가 그만뒀습니다.

이 숫자는 글 하나당 요청 하나입니다. 목록에 글이 스무 편이면 목록을 여는 순간 요청이 스무 번 나갑니다. 목록은 사람들이 제일 자주 여는 화면인데, 거기에 요청 스무 개를 얹는 건 얻는 것보다 잃는 게 큽니다.

그리고 하나 더. 응답은 최대 4시간까지 캐시됩니다. 방금 들어온 조회는 바로 안 보입니다. 처음에 이걸 모르고 “왜 숫자가 안 오르지” 하면서 새로고침을 계속 눌렀습니다. 실시간 카운터가 아니라 “대략 이만큼 읽혔다”는 표시로 보는 게 맞습니다.

6. 정리

개인 블로그에 필요한 건 대시보드가 아니라 답 하나였습니다. “오늘 누가 오긴 왔나.”

도구를 고를 때 기능이 많은 쪽을 고르기 쉬운데, 안 쓰는 기능은 그냥 안 쓰고 끝나는 게 아니라 쿠키 배너, 긴 개인정보처리방침, 무거운 스크립트 같은 걸 데리고 옵니다. 저는 그걸 감당할 만큼 방문자가 많지 않습니다.

붙이시려면 순서는 이렇습니다.

  1. GoatCounter 가입 (코드 하나 정하면 끝)
  2. 스크립트 한 줄 추가, Astro면 is:inline 같이
  3. 조회수를 글에 띄울 거면 사이트 설정에서 “Allow adding visitor counts on your website” 켜기
  4. 응답의 count는 문자열이라는 것만 기억

4번에서 걸리는 사람이 저 말고도 있을 것 같아서 굳이 적어둡니다.

고친 곳

2026년 9월 29일, 글에 붙일 참고 문서를 하나씩 다시 열어보다가 본문과 어긋나는 곳을 찾아 고쳤습니다.

  • 무료 조건을 고쳤습니다. GoatCounter는 비상업 사이트만이 아니라 작은 규모의 사이트도 무료로 쓸 수 있습니다.
  • is:inline 설명을 고쳤습니다. 속성이 붙은 스크립트는 Astro가 원래 처리하지 않아서, 속성이 사라지는 일은 실제로는 일어나지 않습니다.

참고한 문서


댓글

로그인도 이메일도 필요 없습니다. 이름만 적고 편하게 남겨주세요.