frontend
Next.js App Router에서 Google Analytics 4 설정하는 방법 — 페이지뷰와 이벤트 추적까지
UA 종료 후 GA4로 전환한 환경에서 Next.js App Router에 Google Analytics 4를 연동하는 방법을 정리했다. next/script 로드, usePathname 페이지뷰 추적, 커스텀 이벤트까지 다룬다.

- ·Google Analytics 4는 2023년 7월 Universal Analytics 종료 후 표준이 됨
- ·GA4 측정 ID 형식: G-XXXXXXXXXX
- ·Next.js SPA에서 클라이언트 이동 시 pageview 이벤트는 수동으로 전송해야 함
- ·NEXT_PUBLIC_ 접두사가 있는 환경변수만 클라이언트 사이드에서 접근 가능
UA가 종료되고 GA4로 전환하면서 기존에 쓰던 패키지가 GA4를 제대로 지원하지 않아서 직접 설정하게 됐다. next/script로 gtag를 로드하고 페이지 전환 시 pageview 이벤트를 수동으로 보내는 방법을 찾는 데 시간이 꽤 걸렸는데, App Router에서는 usePathname 훅으로 경로 변경을 감지하면 됐다. 설정 후 GA4 실시간 보고서에서 방문자가 찍히는 걸 보는 게 소소한 재미가 있다.
Next.js에서 Google Analytics 4를 설정해야 하는 이유
Google Analytics 4와 기존 UA의 차이점 — Next.js 적용 방식이 달라진 이유
구글은 2023년 7월 Universal Analytics(UA)를 종료하고 Google Analytics 4(GA4)로 전환을 완료했다. UA는 히트 기반으로 페이지뷰와 이벤트를 별도로 추적했는데, GA4는 모든 상호작용을 이벤트로 통일해서 추적한다. 페이지뷰도 이벤트의 일종이라는 개념으로 바뀌었다. UA를 Next.js에 연동할 때는 페이지 이동마다 pageview 히트를 보내는 방식이었다. GA4도 기술적으로 비슷하지만 gtag.js 스크립트를 로드하는 방식과 이벤트 스키마가 달라졌다. 기존에 쓰던 react-ga 같은 라이브러리들이 GA4를 완전히 지원하지 않거나, 구버전 문서가 검색에 많이 걸려서 틀린 방법으로 삽질하기 쉽다. Next.js App Router로 전환한 이후에는 Pages Router 방식의 _app.tsx에서 router.events를 구독하던 패턴도 쓸 수 없다. App Router에서는 usePathname 훅으로 경로 변경을 감지하고 pageview 이벤트를 수동으로 보내는 방식이 가장 깔끔하다. 직접 구현하면 외부 라이브러리 의존 없이 GA4 연동이 완성된다.
Next.js App Router에서 Google Analytics 4 스크립트를 로드하는 올바른 방식
GA4 스크립트를 Next.js에 넣는 방법은 크게 두 가지다. 첫 번째는 next/script의 Script 컴포넌트를 사용하는 방식이다. strategy prop으로 스크립트 로드 타이밍을 제어할 수 있다. GA4 같은 외부 분석 스크립트는 strategy afterInteractive를 쓰는 게 적합하다. 페이지가 인터랙티브 상태가 된 이후에 로드되기 때문에 메인 번들 로딩을 방해하지 않는다. lazyOnload는 브라우저가 완전히 유휴 상태일 때 로드되어 첫 페이지뷰가 누락될 수 있으므로 GA4에는 afterInteractive를 써야 한다. 두 번째는 @next/third-parties 패키지의 GoogleAnalytics 컴포넌트를 사용하는 방식이다. Next.js 14.0.2부터 공식 지원되며 gaId prop에 측정 ID만 전달하면 자동으로 스크립트가 로드된다. 직접 구현 없이 빠르게 연동하고 싶다면 이 방법이 가장 간단하다. 단, 페이지뷰 이벤트는 자동으로 처리되지 않는 경우가 있어서 SPA 페이지 전환 추적은 별도로 확인이 필요하다. 커스텀 이벤트가 없다면 @next/third-parties를 쓰고, 세밀한 제어가 필요하다면 직접 구현이 낫다.
Next.js App Router에서 GA4 설정하기
Next.js에 Google Analytics 4 스크립트를 추가하는 방법
GA4 측정 ID는 Google Analytics 관리 화면 → 관리 → 데이터 스트림에서 확인할 수 있다. G-XXXXXXXXXX 형태다. 이 ID를 환경변수로 관리하는 게 좋다. .env.local에 NEXT_PUBLIC_GA_ID=G-XXXXXXXXXX를 추가하면 process.env.NEXT_PUBLIC_GA_ID로 읽을 수 있다. NEXT_PUBLIC_ 접두사가 있어야 클라이언트 사이드에서도 접근 가능하다. app/layout.tsx에서 next/script의 Script 컴포넌트를 import하고 gtag.js 스크립트를 strategy afterInteractive로 로드한다. 인라인 스크립트로 window.dataLayer를 초기화하고 gtag 함수를 정의하는 부분도 추가해야 한다. 이 설정은 모든 페이지에 공통으로 적용되기 때문에 layout.tsx 한 곳에만 추가하면 전체 사이트에 GA4가 활성화된다. 프로덕션 환경에서만 GA4를 로드하고 개발 환경에서는 건너뛰고 싶다면 process.env.NODE_ENV === 'production' 조건으로 감싸면 된다. 개발 중 불필요한 트래픽이 GA4 데이터에 섞이는 걸 막을 수 있다.
// app/layout.tsx
import Script from 'next/script'
const GA_ID = process.env.NEXT_PUBLIC_GA_ID
export default function RootLayout({ children }) {
return (
<html lang="ko">
<body>
{GA_ID && (
<>
<Script
strategy="afterInteractive"
src={`https://www.googletagmanager.com/gtag/js?id=${GA_ID}`}
/>
<Script id="ga-init" strategy="afterInteractive">
{`window.dataLayer=window.dataLayer||[];function gtag(){dataLayer.push(arguments);}gtag('js',new Date());gtag('config','${GA_ID}');`}
</Script>
</>
)}
{children}
</body>
</html>
)
}Next.js App Router에서 Google Analytics 4 페이지뷰를 추적하는 방법
GA4는 SPA 방식으로 동작하는 Next.js에서 페이지 이동 시 pageview 이벤트를 자동으로 보내지 않는다. 브라우저 URL이 바뀌어도 페이지 전체를 새로 로드하지 않는 클라이언트 사이드 내비게이션의 경우 gtag가 페이지 전환을 감지하지 못하기 때문이다. App Router에서는 usePathname 훅으로 현재 경로를 추적하고, 경로가 바뀔 때마다 pageview 이벤트를 수동으로 보내야 한다. usePathname은 클라이언트 컴포넌트에서만 쓸 수 있기 때문에 'use client'를 선언한 별도 컴포넌트로 분리한다. useEffect 안에서 pathname이 바뀔 때마다 gtag('event', 'page_view', { page_path: pathname })을 호출하도록 작성한다. 이 컴포넌트를 layout.tsx에 추가하면 모든 경로 변경에 대해 pageview가 GA4에 기록된다. Pages Router에서 _app.tsx의 router.events.on('routeChangeComplete')으로 처리하던 것과 역할은 같지만 구현 방식이 다르다. 직접 설정해보면 이 부분을 빠뜨리면 첫 진입 페이지만 기록되고 이후 이동한 페이지는 GA4에 잡히지 않는다는 걸 확인할 수 있다.
'use client'
import { usePathname } from 'next/navigation'
import { useEffect } from 'react'
export function GAPageview({ gaId }: { gaId: string }) {
const pathname = usePathname()
useEffect(() => {
window.gtag?.('event', 'page_view', { page_path: pathname })
}, [pathname])
return null
}Next.js GA4 이벤트 추적과 동작 확인
Next.js에서 Google Analytics 4 커스텀 이벤트를 추적하는 방법
GA4에서 커스텀 이벤트는 gtag('event', 이벤트명, 파라미터) 형태로 전송한다. 버튼 클릭, 폼 제출, 스크롤 깊이 등 분석하고 싶은 상호작용에 이벤트를 추가할 수 있다. Next.js에서는 gtag 함수를 직접 호출하거나, 유틸리티 함수로 래핑해서 타입 안전성을 확보하는 방식이 많이 쓰인다. lib/analytics.ts 파일을 만들어서 이벤트 타입을 정의하고 gtag 호출을 추상화하면 프로젝트 전체에서 일관된 이벤트 이름을 사용할 수 있다. 예를 들어 블로그 포스트 공유 버튼 클릭을 추적하고 싶다면 trackEvent('share', { content_type: 'post', item_id: slug }) 형태로 쓰는 함수를 정의하고 버튼의 onClick에서 호출한다. GA4의 이벤트 파라미터는 최대 25개까지 추가할 수 있고, 파라미터 이름은 40자, 값은 100자 이내여야 한다. 이벤트를 추가하고 나면 GA4 대시보드의 Events 메뉴에서 확인하는 데 최대 24~48시간이 걸릴 수 있다. 즉시 확인이 필요하면 GA4 실시간 보고서를 활용하거나, Chrome 확장 프로그램 GA Debugger를 설치하면 이벤트가 즉시 표시된다.
Google Analytics 4 실시간 보고서로 Next.js 추적 동작을 확인하는 방법
GA4 설정이 완료됐는지 확인하는 가장 빠른 방법은 GA4 실시간 보고서를 열고 해당 사이트에 직접 접속해보는 것이다. GA4 관리 화면에서 보고서 → 실시간을 클릭하면 현재 활성 사용자와 최근 이벤트를 실시간으로 볼 수 있다. 브라우저에서 사이트에 접속하면 수 초 안에 실시간 보고서에 방문자가 찍히고, 페이지를 이동할 때마다 page_view 이벤트가 기록된다. 이벤트가 보이지 않는다면 세 가지를 확인한다. 측정 ID가 정확한지, 브라우저 광고 차단 익스텐션이 GA4 스크립트를 막고 있는지, NODE_ENV 조건으로 프로덕션에서만 로드하도록 설정했는지다. uBlock Origin 같은 차단기가 GA4 스크립트를 막는 경우가 있어서 다른 브라우저로 테스트해보는 게 빠르다. GA4의 DebugView 기능을 활용하면 개발 환경에서도 이벤트 전송 내역을 실시간으로 확인할 수 있다. 관리 화면에서 DebugView를 활성화하고 사이트에 접속하면 이벤트가 시간 순서대로 표시된다. 처음 설정을 완료하고 실시간 보고서에서 page_view 이벤트가 찍히는 순간에 설정이 제대로 됐다는 걸 확신할 수 있다.
자주 묻는 질문
next/script의 strategy 중 lazyOnload와 afterInteractive 중 GA4에는 어느 게 맞나요?+
afterInteractive가 맞습니다. lazyOnload는 브라우저가 완전히 유휴 상태일 때 로드되어 초기 pageview가 누락될 수 있습니다. afterInteractive는 페이지가 인터랙티브 상태가 되면 로드되어 첫 방문에서도 이벤트가 제대로 기록됩니다.
GA4 측정 ID를 환경변수 없이 코드에 직접 써도 되나요?+
기능적으로는 됩니다. GA4 측정 ID는 공개 저장소에 올라가도 보안 문제가 생기는 값은 아닙니다. 다만 개발/프로덕션 환경별로 다른 측정 ID를 쓰고 싶다면 환경변수로 관리하는 게 편리합니다.
Next.js 정적 사이트(output: export)에서도 GA4가 동작하나요?+
네. GA4는 클라이언트 사이드에서 동작하는 스크립트이기 때문에 정적 사이트여도 문제없이 동작합니다. next/script의 Script 컴포넌트도 클라이언트에서 렌더링됩니다.
GA4 실시간 보고서에 방문자가 안 잡히는데 어떻게 확인하나요?+
브라우저 광고 차단 익스텐션을 먼저 끄고 테스트해보세요. 그래도 안 잡힌다면 브라우저 개발자 도구 네트워크 탭에서 google-analytics.com으로 가는 요청이 있는지 확인합니다. 요청이 없다면 Script 컴포넌트가 실제로 렌더링되고 있는지, 측정 ID가 올바른지 확인하세요.
관련 글
Next.js App Router 메타데이터 완벽 가이드 — generateMetadata로 SEO 최적화하는 방법
Next.js App Router에서는 Head 컴포넌트 대신 Metadata API를 써야 한다. layout.tsx 전역 설정부터 포스트별 generateMetadata, robots.ts와 sitemap.ts까지 정리했다.
Next.js 정적 사이트를 Jenkins로 자동 배포하는 방법 — Jenkinsfile로 빌드부터 배포까지
매번 수동으로 빌드하고 서버에 올리던 Next.js 정적 사이트 배포를 Jenkins 파이프라인으로 자동화한 방법을 정리했다. Checkout부터 scp 배포까지 단계별로 설명한다.