GA4 페이지 제목 누락 보완: BigQuery에서 원본을 지키는 방법
GA4 페이지 제목이 비었을 때 URL과 ID로 분석용 값을 보완한 사례입니다. 원본 우선순위, 잘못된 URL 결합, 중복 행과 수동 예외를 확인하고 가상 SQL로 결과를 비교합니다.

목차
세 줄로 먼저 읽기
이번 방문에서 한 편은 바로 볼 수 있습니다.
제목이 비었다고 모든 데이터가 없어진 것은 아닙니다
GA4는 웹사이트와 앱의 이용 현황을 분석하는 도구입니다. page_location은 방문한 페이지 주소, page_title은 페이지 제목을 담는 이벤트 매개변수입니다. 매개변수는 이벤트와 함께 보내는 부가 정보입니다.
주소는 있는데 제목이 NULL인 기록이 있을 수 있습니다. NULL은 값이 없다는 표시이며 길이가 0인 글자인 빈 문자열 ''과도 구분됩니다. 원시 자료는 가공하기 전의 수집 기록을 뜻합니다. 이때 주소를 근거로 분석용 제목을 채울 수 있지만, 당시 실제로 수집하지 못한 제목을 확실히 되찾았다고 말할 수는 없습니다.
먼저 해당 이벤트에서 제목을 수집하도록 구현했는지, 값이 늦게 설정되는지, 보고서와 원시 자료에서 무엇이 비어 있는지 확인해야 합니다. 모든 누락을 특정 광고 플랫폼이나 전송 시점의 문제로 단정하지 않습니다.
스프레드시트에서 BigQuery로 옮긴 배경
기존 작업에서는 누락된 제목을 스프레드시트의 URL과 이름 대응표로 관리하고, Looker Studio에서 결합해 보여주었습니다. Looker Studio는 여러 데이터를 표와 차트로 표시하는 도구입니다. 두 자료의 공통 항목으로 행을 연결하는 작업을 조인(join)이라고 합니다.
새 URL이 늘어날 때마다 대응표를 고치는 일이 생겨, 이 규칙을 BigQuery의 분석용 데이터 생성 단계로 옮겼습니다. BigQuery는 데이터를 저장하고 SQL로 조회하는 서비스입니다. SQL은 데이터를 선택하고 계산하는 언어입니다.
이 방식이 모든 상황에서 정답인 것은 아닙니다. 작은 대응표는 시트로 관리해도 충분할 수 있습니다. 반복 조회가 많고 같은 보완 규칙을 여러 보고서에서 써야 할 때, 분석용 표인 데이터마트에 미리 반영하는 방식을 검토할 수 있습니다.
작업의 목적은 다음 세 가지였습니다.
| 기존 작업 | 바꾸려는 방식 |
|---|---|
| 새 주소마다 사람이 이름을 찾아 입력 | 신뢰할 수 있는 기존 기록에서 후보를 생성 |
| 보고서마다 같은 조인을 반복 | 공통 분석용 표에서 보완 결과 사용 |
| 왜 제목이 바뀌었는지 알기 어려움 | 원본, 보완값, 선택 근거를 따로 보존 |
자동화해도 예외 확인은 남습니다. 처리 시간이 얼마나 줄었는지와 제목이 얼마나 정확히 채워졌는지는 별도로 측정해야 합니다.
첫 연습은 제목 네 개를 비교하는 것입니다
매핑(mapping)은 주소나 ID에 대응하는 제목을 연결하는 것입니다. 다음은 실제 데이터가 아닌 가상 예제입니다. ‘URL 후보’는 같은 페이지 주소에서 찾은 제목이고, ‘ID 후보’는 같은 콘텐츠 식별자로 찾은 제목입니다. 후보가 해당 날짜와 페이지에 적합하다는 검증을 이미 마쳤다고 가정합니다.
| 기록 | 원본 제목 | URL 후보 | ID 후보 | 선택할 제목 |
|---|---|---|---|---|
| e1 | 원래 제목 | 새 제목 | 다른 이름 | 원래 제목 |
| e2 | NULL | 교육 안내 | 교육 안내 | 교육 안내 |
| e3 | 빈 문자열 | NULL | 상담 신청 | 상담 신청 |
| e4 | NULL | NULL | NULL | NULL 유지 |
우선순위는 정상 원본 → 검증한 URL 후보 → 검증한 ID 후보입니다. 원본이 있는데 후보를 먼저 적용하면 ‘누락 보완’ 범위를 넘어 원본을 바꾸게 됩니다. 근거가 없으면 e4처럼 비어 있는 상태를 남깁니다.
가상 자료로 우선순위 확인하기
아래 SQL은 외부 테이블을 읽거나 수정하지 않습니다. 이미 사용할 수 있는 BigQuery 환경이 있다면 BigQuery의 GoogleSQL 편집기에 코드 전체를 붙여 넣고 구문 검사 후 실행(Run)을 누릅니다. 오류가 나면 처음 WITH부터 마지막 세미콜론까지 복사했는지 확인합니다. 계정이 없다면 위 표의 답을 설명하는 것으로 첫 연습을 끝낼 수 있습니다.
WITH examples AS (
SELECT 'e1' AS event_key, '원래 제목' AS original_title,
'새 제목' AS url_title, '다른 이름' AS id_title
UNION ALL SELECT 'e2', NULL, '교육 안내', '교육 안내'
UNION ALL SELECT 'e3', '', NULL, '상담 신청'
UNION ALL SELECT 'e4', NULL, NULL, NULL
), normalized AS (
SELECT *,
CASE WHEN NULLIF(TRIM(original_title), '') IS NOT NULL
THEN original_title END AS usable_original,
NULLIF(TRIM(url_title), '') AS usable_url,
NULLIF(TRIM(id_title), '') AS usable_id
FROM examples
)
SELECT event_key, original_title,
COALESCE(usable_original, usable_url, usable_id) AS resolved_title,
CASE
WHEN usable_original IS NOT NULL THEN 'original'
WHEN usable_url IS NOT NULL THEN 'url_map'
WHEN usable_id IS NOT NULL THEN 'id_map'
ELSE 'missing'
END AS title_origin
FROM normalized
ORDER BY event_key;TRIM은 앞뒤 공백을 정리하고 NULLIF는 빈 문자열을 NULL로 바꿉니다. 이 예제는 NULL뿐 아니라 공백만 있는 값도 ‘비어 있음’으로 보는 규칙입니다. 정상 원본은 원래 문자열을 유지합니다. COALESCE는 왼쪽부터 NULL이 아닌 첫 값을 고르므로 순서가 중요합니다. 조건식 설명
original_title은 원본, resolved_title은 선택한 분석용 제목, title_origin은 선택 근거입니다. 결과는 e1부터 e4까지 네 행이며, title_origin은 차례로 original, url_map, id_map, missing이어야 합니다. e4에 그럴듯한 이름을 억지로 채우지 않습니다.
주소를 같게 만드는 규칙부터 검증합니다
URL 정규화는 같은 페이지의 주소 표기를 비교 가능한 형태로 정리하는 작업입니다. 예를 들어 https://example.com/course_A?utm_source=email과 https://example.com/course_A가 같은 콘텐츠라면 추적용 값을 제외한 주소로 비교할 수 있습니다.
그러나 물음표 뒤를 항상 지우면 안 됩니다.
| 주소 차이 | 먼저 확인할 점 |
|---|---|
?utm_source=email | 추적용 값인지 확인 후 비교용 키에서 제외 검토 |
?id=100과 ?id=200 | 서로 다른 콘텐츠라면 ID를 보존 |
?lang=ko와 ?lang=en | 제목 언어가 다르면 언어 구분 보존 |
/course_A와 /course_A/ | 사이트에서 같은 페이지인지 확인 |
| 같은 경로, 다른 호스트 | 다른 사이트나 고객 자료일 수 있으므로 호스트 보존 |
정규화한 주소는 원본 주소와 별도 열로 보관합니다. 원본을 잘라내서 유입 정보를 잃지 않도록 합니다. 경로의 대소문자나 # 뒤 정보도 서비스에서 의미가 있는지 먼저 확인합니다.
정규표현식으로 ID를 찾는 작은 예
정규표현식은 문자열의 규칙을 지정해 필요한 부분을 찾는 방법입니다. 아래 예제는 example.com에서 숫자 세 자리 ID를 쓰는 두 경로만 대상으로 합니다.
WITH urls AS (
SELECT 'https://example.com/123?utm_source=email' AS page_location
UNION ALL SELECT 'https://example.com/view/456/certification'
UNION ALL SELECT 'https://example.com.evil.test/123'
UNION ALL SELECT 'https://example.com/123/other'
)
SELECT page_location,
COALESCE(
REGEXP_EXTRACT(page_location,
r'^https://example\.com/([0-9]{3})/?(?:[?#].*)?$'),
REGEXP_EXTRACT(page_location,
r'^https://example\.com/view/([0-9]{3})/certification/?(?:[?#].*)?$')
) AS content_id
FROM urls;결과는 주소별로 123, 456, NULL, NULL입니다. 순서는 지정하지 않았으므로 행의 주소와 결과를 함께 비교합니다. ^와 $는 문자열 전체의 범위를 제한하고, 괄호로 묶은 숫자 세 자리만 꺼냅니다. 맞지 않으면 REGEXP_EXTRACT는 NULL을 반환합니다. BigQuery 문자열 함수
이 예제는 모든 사이트 주소를 처리하는 코드가 아닙니다. 실제 ID가 한글, 하이픈, 다른 길이를 포함한다면 별도의 규칙과 테스트가 필요합니다. ID를 추출했다는 것만으로 서로 다른 페이지의 제목이 같다고 결정하지도 않습니다. 예를 들어 안내 페이지와 인증 완료 페이지는 같은 콘텐츠 ID를 쓰면서도 제목이 다를 수 있습니다.
결합할 때는 행 수가 늘지 않는지 봅니다
URL 후보와 ID 후보를 차례로 붙이는 방식은 도움이 될 수 있지만, 각 기준에 후보가 여러 행이면 원본 이벤트 한 건이 여러 건으로 늘어날 수 있습니다. 후보 표에서 결합 키 하나당 사용할 후보가 하나인지부터 확인합니다. 키는 두 자료를 연결하는 기준 항목입니다.
제목이 과거에 바뀐 페이지라면 최신 제목 하나를 모든 과거 기록에 넣지 않습니다. 사이트, 콘텐츠 ID, 페이지 종류와 제목 적용 기간 등을 함께 검토합니다. 후보가 충돌하면 임의로 하나를 고르지 말고 ‘확인 필요’ 대상으로 남깁니다.
이벤트 전체를 GROUP BY로 묶는 것도 자동 중복 제거의 정답은 아닙니다. 두 번 실제로 발생한 같은 행동까지 한 행으로 합칠 수 있습니다. 이벤트 중복 여부는 수집 식별자와 업무 기준으로 판단하고, 제목 보완 때문에 정상 이벤트 수가 변하지 않도록 해야 합니다.
원시 event_params를 바로 수정할 필요는 없습니다
GA4 내보내기의 event_params는 이름과 값이 반복해서 들어 있는 배열입니다. 각 원소는 여러 필드를 묶은 STRUCT 구조이며, page_title은 보통 문자열 값으로 들어갑니다. data_id와 data_name은 모든 GA4 속성에 기본으로 존재하는 제목 필드가 아닙니다. 사용하는 서비스가 따로 수집했는지 확인해야 합니다. GA4 내보내기 구조
처음 설계할 때는 원시 이벤트를 유지하고 분석용 표에 original_title, resolved_title, title_origin 같은 별도 열을 두는 편이 변경 근거를 확인하기 쉽습니다. 원시 중첩 배열까지 다시 만들어야 한다면 키의 중복과 다른 매개변수 보존을 별도로 검증해야 합니다. 제목이 비었다는 이유만으로 전체 배열을 덮어쓰지 않습니다.
MERGE를 쓴다고 수동값이 자동 보존되지는 않습니다
MERGE는 조건에 따라 기존 행을 수정하거나 새 행을 추가할 수 있는 SQL 문입니다. CREATE OR REPLACE 대신 썼다고 해서 수동값이 보호되지는 않습니다. 수정 조건에 수동 입력 여부를 반영해야 합니다. 여러 입력 행이 같은 기존 행을 갱신하려 하면 오류가 발생할 수도 있습니다. BigQuery MERGE 안내
예를 들어 후보의 출처를 manual과 automatic으로 구분하고, 확인된 수동값을 자동 후보가 덮어쓰지 않도록 정할 수 있습니다. 누가 어떤 근거로 입력했는지, 언제까지 적용할지도 기록합니다. 잘못 넣은 수동값을 영구히 유지하는 것이 목표는 아닙니다.
자동 후보를 한 번도 만들 수 없었던 새 페이지는 사이트의 콘텐츠 관리 자료 등 확인 가능한 원본을 찾습니다. 근거 자료가 없으면 누락 상태로 남깁니다. 과거 로그 한 건에서 제목을 찾았더라도 현재와 과거의 모든 제목이 같다고 보장되지는 않습니다.
자동 실행 전에 남길 확인 기록
가상 예제에서 규칙을 이해한 다음, 실제 적용은 담당자가 기간과 데이터 범위를 정해 사본으로 점검합니다. 일정에 따라 자동 실행하는 스케줄을 바로 켜기 전에 다음 결과를 비교합니다.
| 확인 항목 | 통과 기준의 예 |
|---|---|
| 입력과 출력 이벤트 행 수 | 제목 보완만 했다면 같음 |
| 정상 원본이 바뀐 건수 | 빈값만 채우는 규칙에서는 0건 |
| 보완한 건수 | URL 후보와 ID 후보를 구분해 집계 |
| 남은 NULL과 충돌 | 숨기지 않고 별도 집계 |
| 수동값 유지 | 다음 실행에서도 정한 우선순위를 유지 |
| 재실행 | 같은 입력과 같은 후보로 다시 실행해 결과가 변하지 않음 |
행 수가 늘거나 정상 원본이 바뀌었다면 운영 결과에 적용하지 않고 후보 표의 중복과 선택 순서를 먼저 확인합니다. 보완 자동화와 별개로 새 데이터의 제목 누락을 줄이려면 수집 구현도 점검해야 합니다.
실제 BigQuery 테이블을 읽을 때는 날짜 범위와 예상 처리량, 비용 상한을 확인합니다. 원본 덮어쓰기 없이 검증한 뒤 필요한 분석용 결과에만 반영하세요. 속도 개선은 같은 보고서와 조건으로 전후 조회 시간을 측정해야 비교할 수 있습니다.
혼자 한 번 더 판단하기
원본 제목이 ‘기초 과정’이고, 최신 매핑 제목이 ‘심화 과정’입니다. 누락 보완 작업에서 무엇을 선택할까요?
원본 ‘기초 과정’을 유지합니다. 그다음 콘텐츠가 바뀌었는지, ID가 재사용됐는지와 제목의 적용 기간을 따로 확인합니다. 반대로 원본이 NULL이고 URL 후보와 ID 후보가 모두 없으면 NULL을 남깁니다. 보완율을 높이는 것보다 근거 없는 제목을 넣지 않는 것이 먼저입니다.
3줄 요약
-
페이지 제목 보완은 근거 자료로 분석용 이름을 채우는 작업이며 당시 수집하지 못한 원래 제목을 확실히 복원하는 것은 아닙니다.
-
원본 제목을 먼저 보존하고 URL과 ID 후보가 같은 페이지와 기간을 가리키는지 확인한 뒤 빈값만 보완합니다.
-
자동화 전후의 행 수, 원본 변경 수, 보완 근거와 남은 누락을 확인하며 MERGE도 수동값을 보존할 조건을 따로 설계해야 합니다.

제대로 이해했는지 한 문제로 확인해 볼까요?
답을 고르면 바로 풀이가 나와요.
원본 제목은 A이고 URL 매핑 후보는 B입니다. 빈 제목만 채우는 작업에서 먼저 선택할 값은 무엇인가요?
이 글이 도움이 되었나요?
GA4 화면의 숫자를 모으고 읽고 보여 주는 세 단계를 정리했습니다
코스 전체 보기 →
새 글과 AI 소식을 메일로 받아 보세요
AI가 바꾸는 일과 도구, 측정 실무 이야기를 매주 한 번 보내 드려요.
