GTM과 GA4로 방문자는 이미 보고 있었습니다. 그런데 그 숫자를 관리자 대시보드가 아니라 사이트 화면(각 글 카드와 상세)에 직접 띄우고 싶었습니다. 당연히 백엔드나 DB가 필요할 줄 알았는데, 아니었습니다. 그 과정의 기록입니다.
1. GTM은 "모으기"만 한다
오해: GTM 태그를 심었으니 조회수도 GTM에서 꺼내 쓰면 될 줄 알았습니다.사실: GTM은 수집 신호를 흘려보내는 통로일 뿐이고, 숫자가 실제로 쌓이는 곳은 GA4입니다. 그래서 화면에 숫자를 표시하려면 GA4에 쌓인 값을 읽어오는 별도 통로, GA4 Data API가 필요합니다.정리하면 흐름은 이렇습니다: 방문 → GTM(수집) → GA4(저장·집계) → Data API(읽기) → 내 화면.2. 함정 두 개: 다른 ID, 그리고 안 켜진 API
측정 ID와 속성 ID는 다르다: 흔히 보는 G-XXXXXXX는 "측정 ID"라서 데이터를 넣을 때 씁니다. 정작 Data API로 숫자를 꺼낼 때는 숫자로 된 "속성 ID"가 필요합니다. 둘은 완전히 다른 값이라, 여기서 한 번 헤맸습니다.API는 프로젝트에서 따로 켜야 한다: 서비스 계정도 만들고 권한도 줬는데 이런 에러가 났습니다.7 PERMISSION_DENIED: Google Analytics Data API has not been used
in project ... before or it is disabled.
해결: GCP 콘솔에서 "Google Analytics Data API"를 활성화하면 끝납니다. 이름이 비슷한 Admin API나 Reporting API가 아니라 정확히 Data API입니다. 켜고 1~2분 반영을 기다려야 합니다.3. 카드마다 부르지 않기
문제: 목록에 카드가 20개면 카드마다 API를 부를 판이었습니다. 느리고 쿼터도 아깝습니다.해결: 경로별 조회수를 한 번의 요청으로 { 경로: 조회수 } 맵으로 받아두고, 각 카드는 자기 경로로 맵에서 찾기만 합니다.캐시: GA4 집계는 하루 단위로 갱신되니 실시간으로 부를 이유가 없습니다. Next.js unstable_cache로 1시간 캐시를 걸어 호출을 줄였습니다.4. DB가 필요 없는 이유
조회수의 원본 저장소는 GA4 그 자체입니다. 내가 따로 카운터 테이블을 만들 필요가 없습니다.요람일지는 이미 Next.js 서버가 도니, 이 서버가 GA4에서 숫자를 받아 페이지를 그려 내려주면 됩니다. 별도 서버도 DB도 없이 조회수 표시가 완성됩니다.공개값과 시크릿 나누기: 속성 ID와 서비스 계정 이메일은 그 자체로는 아무 권한이 없는 식별자라 코드 상수로 두고, 진짜 비밀인 개인키(private_key)만 환경변수에 넣었습니다. "공개돼도 되는 값은 상수, 진짜 비밀만 env"라는 기준을 지켰습니다.5. 솔직한 한계: 이건 실측이 아니다
하루 지연: GA4 집계 특성상 방금 들어온 조회는 바로 잡히지 않습니다.애드블록: 광고·추적 차단을 쓰는 방문자는 GA4에 잡히지 않습니다. 개발자 유입이 많은 사이트라면 실제보다 낮게 나옵니다.그래서: 이 숫자는 "정확한 카운터"가 아니라 "대략적인 누적 조회"입니다. 조회 기록이 없는 글은 숨기지 않고 0으로 표시해, 숫자의 의미를 솔직하게 뒀습니다.진짜 정확한 실시간 카운터가 필요하면 그때는 내 DB로 직접 세야 합니다. 지금 목적(살아있는 사이트라는 감각)에는 이걸로 충분합니다.6. (덤) 1025~1280px에서 여백이 사라지던 버그
오래 거슬리던 반응형 버그도 같이 잡았습니다.
증상: 화면 폭이 큰데도 목록의 좌우 여백이 사라지고 콘텐츠가 화면 끝에 딱 붙었습니다.원인: 컨테이너에 max-lg:px-5가 걸려 있었습니다. 이건 "1024px 미만에서만" 좌우 패딩을 준다는 뜻이라, 1025~1280px 구간에서 패딩이 0이 됐습니다(1280을 넘으면 max-width로 가운데 정렬되며 여백이 다시 생김).해결: 패딩을 전 구간으로 바꿨습니다.- max-lg:px-5
+ px-5 lg:px-8
결과
블로그와 포트폴리오의 목록 카드와 상세 페이지 모두에 게시물별 누적 조회수 표시별도 서버·DB 없음: 원본은 GA4, 읽기는 서버 컴포넌트에서 한 번에 받아 캐시지금 이 글의 조회수도 이 방식으로 함께 올라갑니다