해당 글에서는 React 환경에서 GA4를 이해하고 설정하여 데이터를 수집하는 방법에 대해 알아봅니다.
1) Google Analytics(GA4)
💡 Google Analytics(GA4)
- Google 애널리틱스 4는 웹사이트 및 앱에서 트래픽과 참여도를 측정할 수 있는 분석 서비스입니다.
- 웹사이트와 웹, 앱의 데이터를 수집하여 비즈니스 통찰력을 제공하는 구글의 차세대 분석 플랫폼입니다.
Google 애널리틱스 4 소개 | Google Analytics | Google for Developers
Google 애널리틱스용 MCP 서버를 사용해 보세요. GitHub에서 설치하고 공지사항에서 자세한 내용을 확인하세요. 의견 보내기 Google 애널리틱스 4 소개 컬렉션을 사용해 정리하기 내 환경설정을 기준
developers.google.com
1. UA(Universal Analytics)와 GA(Google Analytics)
💡 UA(Universal Analytics)와 GA(Google Analytics)
1. UA(Universal Analytics)
- 세션(Session)'과 '페이지뷰(Pageview) 중심이었습니다. 사용자가 머문 시간이나 본 페이지 수를 중요한 데이터로 이용하였습니다.
2. GA(Google Analytics)
- 모든 사용자 상호작용을 '이벤트(Event)'로 처리합니다.
- 버튼 클릭, 스크롤, 동영상 재생, 페이지 조회 등 모든 행위가 각각의 이벤트가 되며, 여기에 '매개변수(Parameter)'를 붙여 상세 정보를 수집합니다.
| 구분 | UA (Universal Analytics) | GA4 (Google Analytics 4) |
| 측정 기준 | 세션(Session), 히트(Hit) 기반 | 이벤트(Event), 파라미터 기반 |
| 플랫폼 | 주로 웹(Web) 중심 | 웹(Web) + 앱(App) 통합 측정 |
| 쿠키/개인정보 | 쿠키 의존도가 높음 | 머신러닝을 활용한 데이터 보정, IP 익명화 |
| ID 체계 | 속성 ID (UA-000000-0) | 측정 ID (G-XXXXXXX) |
| 보고서 구조 | 표준 보고서(획득, 행동, 전환 등) 위주 | 탐색(Exploration) 중심의 맞춤형 보고서 |
| 데이터 보관 | 거의 무제한 (설정에 따라 다름) | 기본 2개월, 최대 14개월 |
2. GA 수집 데이터
2.1. 이벤트
💡 이벤트
- 웹 사이트 또는 앱과의 기본적인 상호작용을 통해서 트리거가 됩니다.
- 웹의 경우는 구글 태그(gtag.js)를 통해 자동으로, 또는 '향상된 측정' 설정을 통해 수집되는 데이터입니다.
- 앱의 경우는 Firebase용 구글 애널리틱스 SDK를 통해 데이터를 수집하고 이를 GA4로 전송을 합니다.

| 분류 | 이벤트 명 | 수집 시점 | 주요 수집 데이터 |
| 웹/앱 자동 수집 | first_visit | 웹/앱을 통틀어 사용자가 서비스를 처음 방문했을 때 | 소스, 매체, 캠페인 |
| session_start | 사용자가 방문하여 새로운 세션이 시작될 때 | 세션 ID, 세션 번호 | |
| user_engagement | 사용자가 콘텐츠를 활발히 이용 중일 때 (주기적 수집) | 참여 시간(밀리초) | |
| 웹 자동 수집 | page_view | 새로운 페이지가 로드되거나 브라우저 기록이 변경될 때 | 페이지 URL, 페이지 제목 |
| 앱 자동 수집 | screen_view | 앱 내에서 화면 전환이 일어날 때 | 화면 이름, 클래스 이름 |
| first_open | 앱 설치 후 사용자가 처음으로 실행했을 때 | 앱 버전, 기기 모델, OS 정보 | |
| app_exception | 앱이 **비정상 종료(Crash)**되거나 예외가 발생할 때 | 오류 메시지, 치명적 여부(fatal) | |
| in_app_purchase | 인앱 결제(App Store, Play Store)가 완료되었을 때 | 상품 ID, 가격, 통화, 수량 | |
| app_update | 사용자가 앱을 새 버전으로 업데이트하고 실행할 때 | 이전 앱 버전 정보 | |
| notification_receive | 백그라운드 상태에서 푸시 알림을 수신했을 때 | 알림 제목, 본문, 캠페인 정보 | |
| notification_open | 사용자가 푸시 알림을 클릭하여 앱을 열었을 때 | 클릭된 알림의 캠페인 정보 | |
| app_remove | (Android 전용) 사용자가 앱을 삭제할 때 | 삭제된 앱 패키지 정보 | |
| 향상된 측정(웹) | scroll | 사용자가 페이지의 90% 지점까지 스크롤했을 때 | 스크롤 깊이 |
| click | 현재 도메인이 아닌 외부 링크를 클릭할 때 | 외부 URL, 링크 ID, 링크 클래스 | |
| view_search_results | 사이트 내 검색 결과 페이지가 로드될 때 | 검색어 (q, s, search_term 등) | |
| video_start / progress | 내장된 YouTube 영상이 재생되거나 특정 구간(25, 50% 등) 통과 시 | 영상 제목, 영상 URL, 진행률 | |
| file_download | 문서, 실행 파일, 압축 파일 링크를 클릭했을 때 | 파일 이름, 확장자, 파일 URL |
자동 수집 이벤트 - 애널리틱스 고객센터
도움이 되었나요? 어떻게 하면 개선할 수 있을까요?
support.google.com
2.2. 속성
💡 속성
- 자동 수집되는 속성과 사용자가 직접 정의하여 부여하는 속성이 있습니다.

| 속성명 | 데이터 내용 | 분석 활용도 |
| Device 정보 | 기기 모델, 브랜드, OS 버전, 브라우저 | 기기별 최적화 및 UI/UX 개선 근거 |
| Geo 정보 | 국가, 지역, 도시 (IP 기반) | 지역별 타겟 마케팅 및 광고 집행 |
| App 정보 | 앱 버전, 스토어 ID, 패키지 이름 | 버전별 버그 추적 및 업데이트 유도 |
| Language | 시스템 설정 언어 | 다국어 지원 우선순위 결정 |
2) Google Analytics(GA4) 환경 설정
1. 공식사이트에 접속합니다.
Google Analytics | Google for Developers
Google 애널리틱스를 사용하면 디지털 전략을 세부적으로 조정하고, 캠페인을 최적화하며, 온라인 인지도를 한 단계 업그레이드할 수 있습니다.
developers.google.com
2. 아래와 같이 속성을 만듭니다
💡 아래와 같이 속성을 만듭니다
- 수집하려는 프로젝트에 대해서 생성합니다.

3. 업종 및 카테고리를 선택합니다

4. 비즈니스 목표를 선택합니다

5. 데이터 수집을 웹으로 선택합니다

6. 웹 사이트 URL을 입력하고, 스트림 이름을 입력합니다
💡 웹 사이트 URL을 입력하고, 스트림 이름을 입력합니다
- 로컬에서 테스트를 하는 경우 웹 사이트 URL의 경우 임의로 입력을 해도 됩니다!

7. 아래와 같이 생성이 되었습니다.

8. 태그를 확인합니다
💡 태그를 확인합니다
- 아래와 같이 GA에서 제공해 주는 태그를 확인할 수 있습니다.

3) 프로젝트 설정
1. GA 라이브러리를 설치합니다
npm i react-ga4
# or
yarn add react-ga4
https://www.npmjs.com/package/react-ga4
2. 로컬에서 측정을 위한 체커를 구성합니다.
💡 로컬에서 측정을 위한 체커를 구성합니다.
- GA_ID는 위에서 발급한 아이디를 입력합니다.
- 해당 함수에서는 추가로 ‘페이지에 머문 시간(체류시간)’을 측정하기 위해 page_stay라는 이벤트를 추가하는 과정입니다.
- 기본적으로 제공하는 이벤트 외에 새로운 함수를 이용합니다.보조적으로 새로고침 및 탭 종료 시에 머문 시간을 측정하도록 추가 구성하였습니다.
1. GA 초기화
- react-ga4 라이브러리를 이용하여서 GA 사용을 초기화 합니다
2. GA 기록 -1
- 기본적으로 사용자의 웹 체류시간에 대한 이벤트 기록을 추가로 수행합니다
3. GA 기록 -2
- 새로고침, 탭 닫기에 대한 체류시간에 대해서도 기록을 수행합니다.
// RouteChangeTracker.tsx
import { useEffect, useRef } from 'react';
import { useLocation } from 'react-router-dom';
import ReactGA from 'react-ga4';
const GA_ID = 'G-XXXXXXX';
const STORAGE_KEY = 'ROUTE_TRACK_LOG';
const MAX_LOG = 100;
let gaInitialized = false;
export default function RouteChangeTracker() {
const location = useLocation();
const enterTimeRef = useRef<number>(Date.now());
const prevPathRef = useRef<string>(location.pathname);
/**
* GA4 초기화
*/
useEffect(() => {
if (!gaInitialized) {
ReactGA.initialize(GA_ID, {
gaOptions: {
debug_mode: true,
},
});
gaInitialized = true;
}
}, []);
/**
* 체류시간 이벤트 전송
*/
const sendStayEvent = (path: string, enterAt: number) => {
const now = Date.now();
const durationSec = Math.round((now - enterAt) / 1000);
if (durationSec <= 0) return;
ReactGA.event('page_stay', {
page_path: path,
engagement_time_sec: durationSec,
});
const log = {
path,
enterAt,
leaveAt: now,
durationSec,
};
const prev = JSON.parse(localStorage.getItem(STORAGE_KEY) || '[]');
localStorage.setItem(
STORAGE_KEY,
JSON.stringify([...prev, log].slice(-MAX_LOG))
);
};
/**
* 라우트 변경 → 이전 페이지 체류시간 기록
*/
useEffect(() => {
sendStayEvent(prevPathRef.current, enterTimeRef.current);
enterTimeRef.current = Date.now();
prevPathRef.current = location.pathname;
}, [location.pathname]);
/**
* 최초 진입 페이지 보정
*/
useEffect(() => {
return () => {
sendStayEvent(prevPathRef.current, enterTimeRef.current);
};
}, []);
/**
* 새로고침 / 탭 종료 보조 처리
*/
useEffect(() => {
const handleUnload = () => {
sendStayEvent(prevPathRef.current, enterTimeRef.current);
};
window.addEventListener('beforeunload', handleUnload);
return () => window.removeEventListener('beforeunload', handleUnload);
}, []);
return null;
}
3. Layout
💡 Layout
- 한 번만 수행되어야 하는 컴포넌트이기에, 아래와 같이 추가가 되었습니다.
import { Outlet } from "react-router-dom";
import Header from "./Header";
import Footer from "./Footer";
import RouteChangeTracker from "../ga/RouteChangeTracker";
export default function Layout() {
return (
<div style={styles.container}>
<Header />
<main style={styles.main}>
<RouteChangeTracker />
<Outlet />
</main>
<Footer />
</div>
);
}
const styles: Record<string, React.CSSProperties> = {
container: {
minHeight: "100vh",
display: "flex",
flexDirection: "column",
},
main: {
flex: 1,
padding: 24,
background: "#f9fafb",
},
};
4) 결과
💡 결과
- 아래와 같이 기록한 이벤트들이 잘 들어오는 것을 확인하였습니다.

오늘도 감사합니다. 😀
'React & React Native > 환경 설정 및 구성' 카테고리의 다른 글
| [RN/오류노트] Solved - Families Policy Requirements: Ad Content (0) | 2025.11.04 |
|---|---|
| [RN] Google Firebase Analytics & Crashlytics 설치 및 세팅 가이드 : 0.80.2+ 버전 기준 (0) | 2025.11.04 |
| [RN] 공통 반응형 디자인 개선 작업 : Dementions + StyleSheet (0) | 2025.09.25 |
| [RN] Google PlayStore: 비공개 테스트 이후 앱 프로덕션 과정까지 설정 방법 (3) | 2025.07.14 |
| [RN] 앱 개인정보 처리방침 및 이용약관 Notion으로 구성하기 (1) | 2025.07.09 |

