들어가며

블로그를 운영하다 보면 "요즘 어떤 글이 인기 있는지" 방문자에게 보여주고 싶을 때가 있습니다. 사이드바에 "인기글 TOP 5" 같은 위젯을 붙이면 체류 시간도 늘고, 내부 링크 구조도 자연스럽게 좋아지거든요.

처음에는 구글 서치콘솔(Search Console) 대시보드에 보이는 데이터를 그대로 가져오면 될 줄 알았는데, 막상 알아보니 서치콘솔은 "검색 노출/클릭" 데이터지 "실제 조회수"가 아니라는 걸 알게 됐습니다. 그래서 실제 페이지뷰 기준으로 인기글을 뽑으려면 GA4(Google Analytics 4) Data API를 써야 한다는 결론에 도달했고, 이번 글에서는 그 세팅 과정을 정리합니다.

1단계. GA4 속성 만들고 블로그에 태그 심기

Google Analytics에서 속성을 새로 만들고, 웹 스트림에 도메인을 등록하면 측정 ID(G-XXXXXXXXXX)를 받을 수 있습니다.

먼저 계정 이름을 입력합니다. 계정 하나에 여러 속성을 포함할 수 있습니다.

GA4 계정 세부정보 입력 화면 - 계정 이름 lifewithyuzu 입력
계정 이름 입력 후 다음으로 이동

관리 화면에서 + 만들기 → 속성을 선택합니다.

GA4 관리 화면에서 만들기 버튼 클릭 후 속성 선택
+ 만들기 → 속성

속성 이름, 보고 시간대(대한민국), 통화를 설정합니다. 시간대와 통화는 나중에 바꾸기 번거로우니 처음부터 맞춰두는 게 좋습니다.

GA4 속성 만들기 폼 - 속성 이름 lifewithyuzu.com, 보고 시간대 대한민국 설정
속성 이름은 도메인으로, 시간대는 대한민국(GMT+9)으로 설정

비즈니스 세부정보는 업종 인터넷 및 통신, 규모 **작음(직원 1~10명)**으로 선택하면 됩니다.

GA4 비즈니스 세부정보 - 업종 인터넷 및 통신, 규모 작음 선택
개인 블로그 기준 설정값

비즈니스 목표는 웹 또는 앱 트래픽 파악 하나만 선택하면 충분합니다.

GA4 비즈니스 목표 선택 - 웹 또는 앱 트래픽 파악 체크됨
블로그 방문자 분석에는 트래픽 파악 옵션 하나면 충분

데이터 수집 플랫폼은 을 선택합니다.

GA4 데이터 수집 시작하기 화면 - 웹, Android 앱, iOS 앱 중 웹 선택
데이터 수집 → 웹 선택

블로그 도메인과 스트림 이름을 입력합니다.

GA4 웹 스트림 설정 - URL lifewithyuzu.com, 스트림 이름 입력
URL과 스트림 이름 입력 후 스트림 만들기

스트림을 만들면 Google 태그 코드와 측정 ID(G-XXXXXXXXXX)를 확인할 수 있습니다.

GA4 Google 태그 설정 화면 - 직접 설치 탭에 gtag 코드와 측정 ID G-KLKNTG90GQ 표시
직접 설치 탭에서 측정 ID와 태그 코드 확인

태그는 데이터가 소급 적용되지 않기 때문에, API 연동은 나중에 하더라도 태그만큼은 최대한 빨리 심어두는 게 좋습니다.

Next.js라면 @next/third-parties를 쓰는 게 가장 깔끔합니다.

npm install @next/third-parties
// app/layout.tsx
import { GoogleAnalytics } from '@next/third-parties/google'

export default function RootLayout({ children }) {
  return (
    <html lang="ko">
      <body>{children}</body>
      <GoogleAnalytics gaId="G-XXXXXXXXXX" />
    </html>
  )
}

태그는 데이터가 소급 적용되지 않기 때문에, API 연동은 나중에 하더라도 태그만큼은 최대한 빨리 심어두는 게 좋습니다.

2단계. GA4 Data API용 서비스 계정 발급

API로 데이터를 읽어오려면 서비스 계정이 필요합니다.

  1. Google Cloud Console에서 프로젝트 생성
  2. API 및 서비스 → 라이브러리에서 "Google Analytics Data API" 검색 후 사용 설정
  3. API 및 서비스 → 사용자 인증 정보 → 서비스 계정 만들기
  4. 생성된 서비스 계정 → 키 → 키 추가 → JSON 으로 키 파일 다운로드
  5. JSON 안의 client_email 값을 복사해서, GA4 관리자 → 속성 액세스 관리에서 뷰어 권한으로 추가

이 마지막 권한 추가를 빼먹으면 API 호출 시 권한 오류가 나니 꼭 확인해야 합니다.

3단계. 환경변수 등록

다운로드한 JSON 파일에서 아래 두 값을 꺼냅니다.

GA_CLIENT_EMAIL=xxx@xxx.iam.gserviceaccount.com
GA_PRIVATE_KEY="-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----\n"
GA_PROPERTY_ID=123456789

GA_PROPERTY_ID는 GA4 관리자 → 속성 설정에서 확인할 수 있는 숫자값입니다. 태그 설치할 때 쓰는 측정 ID(G-XXXXXXXXXX)와는 다른 값이라 헷갈리지 않도록 주의합니다.

GA4 속성 세부정보 페이지 - 상단에 속성 ID 숫자값 표시
관리 → 속성 세부정보 → 시설 세부정보 상단의 속성 ID(숫자)가 GA_PROPERTY_ID

Vercel을 쓰는 경우 프로젝트 Settings → Environment Variables에 그대로 등록하면 됩니다.

4단계. API 연동 코드 작성

npm install @google-analytics/data
// lib/ga.ts
import { BetaAnalyticsDataClient } from '@google-analytics/data'

const client = new BetaAnalyticsDataClient({
  credentials: {
    client_email: process.env.GA_CLIENT_EMAIL,
    private_key: process.env.GA_PRIVATE_KEY?.replace(/\\n/g, '\n'),
  },
})

export async function getPopularPosts(limit = 5) {
  const [response] = await client.runReport({
    property: `properties/${process.env.GA_PROPERTY_ID}`,
    dateRanges: [{ startDate: '30daysAgo', endDate: 'today' }],
    dimensions: [{ name: 'pagePath' }, { name: 'pageTitle' }],
    metrics: [{ name: 'screenPageViews' }],
    orderBys: [{ metric: { metricName: 'screenPageViews' }, desc: true }],
    limit,
  })

  return response.rows?.map(row => ({
    path: row.dimensionValues?.[0].value,
    title: row.dimensionValues?.[1].value,
    views: Number(row.metricValues?.[0].value),
  })) ?? []
}

5단계. 캐싱해서 위젯으로 노출

매 요청마다 API를 부르면 느리고 쿼터도 낭비되므로, 1시간 단위로 캐싱합니다.

// app/api/popular-posts/route.ts
import { getPopularPosts } from '@/lib/ga'
import { NextResponse } from 'next/server'

export const revalidate = 3600 // 1시간마다 갱신

export async function GET() {
  const posts = await getPopularPosts(5)
  return NextResponse.json(posts)
}

이 API를 사이드바나 홈 화면 컴포넌트에서 fetch해서 "인기글 TOP 5" 형태로 렌더링하면 됩니다.

마치며

정리하면 흐름은 ① GA4 태그 설치 → ② 데이터 쌓이는 기간 → ③ 서비스 계정/API 세팅 → ④ 위젯으로 노출 순서입니다. 태그는 소급 적용이 안 되니 지금 당장 심어두고, 최소 1~2주 정도 트래픽 데이터가 쌓인 뒤에 인기글 랭킹을 노출하는 걸 추천합니다.


(이후 실제 적용 스크린샷, 위젯 디자인 등 추가 예정)