목차
1. 개요
2. GA4 → BigQuery 적재 흐름 이해하기
3. BigQuery 내 GA4 테이블 구조 개요
4. STRUCT와 ARRAY, 그리고 중첩 필드 이해하기
5. 참고하면 좋을 정보
1. 개요
GA4를 사용하다보면 언급될 수 밖에 없는 빅쿼리.
빅쿼리에 적재되어있는 GA4의 RAW 테이블 형식이 낯설어서 처음에는 꽤 당황한 경험이 있어요.
이번 기회에 다시금 내용을 정리하고, 왜 빅쿼리에서 이런 구조를 활용하는지 알아보려고 합니다.
- 예상 독자 : GA4를 사용하다 한계를 느낀 마케터, 데이터 분석가, PM
- 담을 내용 : GA4 → BigQuery 데이터 흐름, BigQuery 내 GA4 테이블 구조, STRUCT와 ARRAY 개념 설명
2. GA4 → BigQuery 적재 흐름 이해하기
🔸 왜 BigQuery에 데이터를 적재하나요?
GA4는 UI 상에서도 다양한 분석 기능을 제공하지만, 샘플링 이슈, 파라미터별 상세 쿼리의 제약, 그리고 장기 보관의 한계로 인해 실무에서는 BigQuery 연동이 거의 필수예요. BigQuery를 연결하면 GA4 원천(raw) 데이터를 테이블 형태로 받아볼 수 있고, SQL을 통해 더 자유로운 분석이 가능해요.
🔸데이터 적재의 전체 흐름은 이렇게 돼요
step1. 사용자가 사이트/앱에서 행동을 하면 GA4 SDK가 이벤트를 수집
- 웹: gtag.js 혹은 Google Tag Manager에서 삽입한 GA4 측정 코드가 작동해요
- 앱: Android/iOS용 Firebase SDK를 기반으로 GA4 SDK가 작동해요
- 이 단계에서 각 이벤트는 다양한 파라미터들과 함께 수집돼요 (event_params, user_properties 포함)
step2. Firebase가 중간에서 이 이벤트 데이터를 처리
- GA4는 내부적으로 Firebase 기반의 백엔드 플랫폼을 활용해요
- 수집된 데이터는 Firebase를 통해 실시간 처리되고, 일정 기준으로 정제돼요
step3. 실시간 스트리밍 또는 일일 배치 형식으로 BigQuery에 적재
- 실시간: events_intraday_YYYYMMDD
- 일일 배치: events_YYYYMMDD (주로 이 테이블을 분석에 사용)
🔸 일일 내보내기 vs 스트리밍 내보내기
구분 | 일일 내보내기 | 스트리밍 내보내기 |
생성 시점 | 하루가 끝난 후에 events_YYYYMMDD 테이블로 생성 | 실시간으로 events_intraday_YYYYMMDD 테이블로 전송 |
이벤트 수 제한 | 최대 1백만 이벤트 제한이 있으며, 이를 초과하면 내보내기 기능이 비활성화 | 이벤트 수 제한이 없지만, 트래픽 소스 정보가 포함X |
그 외 | 트래픽 소스 정보가 포함 | 데이터는 실시간으로 반영되지만, 일부 데이터는 최대 3일 후에 반영 |
👉🏻참고자료 : https://www.optizent.com/blog/difference-between-ga4-daily-export-and-streaming-export-to-bigquery/
3. BigQuery 내 GA4 테이블 구조 개요
🔸 테이블 이름 규칙은?
GA4 → BigQuery 연동 시 생성되는 테이블은 events_YYYYMMDD 형식으로 매일 생성돼요.
예: events_20250325, events_20250326 처럼 날짜별 테이블로 쌓입니다.
🔸 row 단위로 어떤 정보가 담기나요?
각 row는 하나의 이벤트(event) 를 의미해요. 한 사용자가 하나의 세션에서 여러 이벤트를 보내면, 그만큼 여러 row가 생겨요.
🔸 GA4 테이블의 필드 구조
필드 종류 | 예시 필드명 | 설명 |
기본 필드 | event_name, event_timestamp, user_pseudo_id | 이벤트명, 타임스탬프, 유저 식별자 등 |
세션/디바이스 | geo, device, traffic_source | 지역, 기기, 유입 경로 등 STRUCT 형태 |
반복 필드 | event_params, user_properties, items | ARRAY of STRUCT 구조. 파라미터나 속성 등 |
4. STRUCT와 ARRAY, 그리고 중첩 필드 이해하기
🔸 BigQuery는 왜 이렇게 복잡한 구조를 쓸까요?
GA4 데이터는 정규화된 테이블에 JOIN하여 분석하기엔 너무 많고 복잡한 이벤트/속성들이 있어요.
그래서 BigQuery는 비정규화(denormalized) + 중첩 필드(nested fields) 구조를 채택해서 쿼리 성능을 높이고, 유연하게 데이터를 다룰 수 있게 만들었어요.
🔸 STRUCT란?
- 여러 개의 필드를 하나의 구조로 묶는 것
- JSON처럼 보이지만, BigQuery에서는 명시적 타입을 가지는 구조체예요
- geo는 STRUCT 타입, 내부 필드가 continent, country, city
{
"geo": {
"continent": "Asia",
"country": "South Korea",
"city": "Seoul"
}
}
🔸 ARRAY란?
- STRUCT 같은 구조가 반복될 수 있게 만든 리스트
- 주로 event_params, items, user_properties 등에 사용돼요
[
{ "key": "page_location", "value": { "string_value": "https://..." } },
{ "key": "ga_session_id", "value": { "int_value": 123456 } }
]
🔸 STRUCT + ARRAY 쿼리 시 주의점: UNNEST!
이렇게 중첩된 구조를 분석하려면 UNNEST() 함수를 써서 펼쳐줘야 해요.
SELECT
event_name,
param.key,
param.value.string_value
FROM
`project.dataset.events_*`,
UNNEST(event_params) AS param
WHERE
param.key = "page_location"
5. 참고하면 좋을 정보
왜 이벤트가 row로 저장되나요? | GA4는 이벤트 기반 데이터 모델을 따르기 때문에 각 행이 하나의 이벤트를 나타냄. 이는 GA4의 데이터 구조가 사용자 상호작용을 이벤트로 기록하기 때문 |
STRUCT는 JSON이랑 비슷한가요? | STRUCT와 JSON은 개념적으로 유사하지만, BigQuery에서는 STRUCT가 명확한 타입을 가짐. STRUCT는 데이터의 구조를 엄격히 정의하며, 이는 데이터 일관성과 성능을 높이는 데 도움이 됨. 반면, JSON은 더 유연한 데이터 구조를 제공하지만, 데이터 타입이 명확하지 않을 수 있음 |
UNNEST 안 하면 쿼리가 안 되나요? | 중첩 구조에서 특정 key-value를 추출하려면 UNNEST를 사용해야함. UNNEST는 ARRAY나 STRUCT 내의 데이터를 평면화하여 별도의 행으로 변환하여 쿼리할 수 있게 함 |
'Study > GA4' 카테고리의 다른 글
[TIL] user_id는 왜 없지? GA4 사용자 식별값을 BigQuery에서 직접 확인해봤다 (0) | 2025.03.28 |
---|---|
[TIL] GA4의 사용자 식별값, 뭐가 다를까? – User ID, Device ID, Client ID, Google Signals (0) | 2025.03.26 |
[GA4를 의심하고 BigQuery를 열다] GA4를 진짜 이해하고 싶은 당신에게 - 시리즈를 연재하며 (0) | 2025.03.24 |
GA4 깊게 이해하기(2/2) (0) | 2024.11.23 |
GA4 깊게 이해하기(1/2) (2) | 2024.11.02 |