tech

이벤트 로그 저장 구조와 적재 실패 데이터 확인하기: 이벤트 로그 전송 4편

Hive 애널리틱스로 전송한 이벤트 중 수집 기준을 충족한 이벤트는 회사별 BigQuery 데이터셋의 t_raw_event_log에, 기준에 맞지 않는 이벤트는 원본 JSON과 격리 사유를 담아 t_raw_event_log_rescue에 저장된다. 정상 테이블에서 이벤트를 찾을 수 없다면 rescue 테이블의 errorReason, errorStackTrace, rawData로 격리 원인을 확인한다. 예를 들어 eventTime이 RFC 3339 형식을 준수하지 않은 경우 201(DATETIME_INVALID) 오류로 격리된다. 이때 시간 형식을 수정해 이벤트를 다시 전송한 후, 정상 테이블에 저장되었는지 확인하면 된다.

전송한 이벤트의 저장 결과 확인하기

「게임 데이터를 이벤트 로그로 전송하기: 이벤트 로그 전송 3편」에서는 실제 게임 데이터를 이벤트 로그로 전송하는 방법을 살펴봤다. 이번 편에서는 전송한 이벤트의 저장 구조를 살펴보고, 정상적으로 저장되지 않은 이벤트의 격리 사유와 확인 방법을 알아본다.

로그 전송 기능을 적용한 후에는 이벤트가 정상적으로 저장되었는지 확인해야 한다. 필수 속성과 값의 형식 등 수집 기준을 충족한 이벤트는 정상 테이블에 저장되지만, 기준에 맞지 않는 이벤트는 별도의 격리 테이블에 저장된다.

정상 테이블에서 전송한 이벤트를 찾을 수 없다면 단순한 수집 지연으로 판단하기보다 격리 여부와 원인을 함께 확인할 필요가 있다.

Hive 애널리틱스의 이벤트 저장 구조

이벤트 데이터

Hive 애널리틱스에 정상적으로 수집된 이벤트는 회사별 BigQuery 데이터셋의 t_raw_event_log 테이블에 저장된다. 이 테이블은 dateTime을 기준으로 일 단위 파티션이 구성되며, 이벤트의 기본 정보와 속성을 함께 저장한다.

필드자료형설명생성 기준
userIdSTRING계정을 기준으로 이용자를 식별하는 값필수 속성으로 전송
identifierProviderSTRING이용자 식별자를 발급한 시스템필수 속성으로 전송
deviceIdSTRING기기를 기준으로 이용자를 식별하는 값필수 속성으로 전송
appIdSTRING이벤트가 발생한 앱을 식별하는 값필수 속성으로 전송
appIdGroupSTRING여러 앱을 하나의 게임(프로젝트)으로 구분하는 값appId 기준으로 자동 생성
dateTimeTIMESTAMPeventTime을 UTC 기준으로 변환한 이벤트 발생 시각eventTime을 파싱해 자동 생성
eventNameSTRING이벤트를 구분하는 이름필수 속성으로 전송
checksumSTRING이벤트 데이터로 생성한 해시값이벤트 데이터를 기준으로 자동 생성
bigqueryRegistTimestampTIMESTAMP이벤트가 BigQuery에 저장된 시각저장 시 자동 생성
attributesJSON사용자 정의 속성과 자동 수집 속성이 저장되는 영역전송한 속성을 구조에 맞게 자동 생성

contents_success 이벤트가 정상적으로 수집되면 다음과 같이 이벤트의 기본 정보와 속성값이 한 행에 저장된다. 동일한 이벤트가 재전송되면 중복 데이터가 저장될 수 있다. 원본 데이터를 직접 조회할 때는 checksum을 기준으로 중복을 제거하는 것을 권장한다.

BigQuery에서 t_raw_event_log를 조회해 contents_success 이벤트의 기본 정보와 attributes가 한 행에 저장된 결과 화면
t_raw_event_log에 이벤트의 기본 정보와 속성값이 한 행에 저장되어 있다.

이벤트 속성 저장 구조

이벤트와 함께 전송하거나 자동으로 수집된 속성은 attributes 필드에 JSON 형태로 저장된다. attributes 내부는 속성의 수집 방식에 따라 hiveAttributes와 eventAttributes로 구분된다.

구분설명주요 값
hiveAttributesHive 애널리틱스의 데이터 처리 과정에서 자동으로 추가되는 속성_dataSource
eventAttributes이벤트와 함께 전송하거나 클라이언트에서 자동으로 수집한 속성원본 eventTime, 사용자 정의 속성, SDK 자동 수집 속성

hiveAttributes의 _dataSource를 확인하면 Hive SDK나 게임 서버 등 이벤트가 전송된 경로를 구분할 수 있으며, eventAttributes에서는 게임에서 직접 전송한 사용자 정의 속성과 실제 값을 확인할 수 있다. Hive SDK를 통해 자동으로 수집한 클라이언트 속성도 이 영역에 포함된다. 더 자세한 내용은 개발자 사이트의 데이터 저장 구조에서 확인할 수 있다.

격리 데이터

필수 속성과 값의 형식 등 수집 기준을 충족하지 못한 이벤트는 적재에 실패하여 회사별 BigQuery 데이터셋의 t_raw_event_log_rescue에 격리된다. 격리 테이블에는 전송한 원본 JSON과 격리 사유가 함께 저장된다. 정상 테이블에서 이벤트가 확인되지 않는다면 rescue 테이블에서 해당 이벤트가 격리되었는지 확인한다.

주요 격리 사유설명
필수 속성 누락로그 전송에 필요한 속성이 없거나 값이 비어 있음
예약어 사용사용자 정의 속성명으로 attributes, eventAttributes, hiveAttributes를 사용하거나, _로 시작하는 속성명을 사용함
지원하지 않는 자료형사용자 정의 속성값으로 JSON 객체 또는 배열을 전송함
잘못된 eventTime 형식eventTime을 타임존이 포함된 RFC 3339 형식으로 해석할 수 없음
eventTime 허용 범위 초과이벤트 발생 시각이 수집할 수 있는 범위를 벗어남(과거 10년부터 미래 5년까지)
JSON 형식 오류전송한 로그를 정상적인 JSON으로 해석할 수 없음

속성명에 사용하는 예약어는 영문 대소문자를 구분하지 않는다. 예를 들어 Attributes나 HIVEATTRIBUTES도 예약어로 처리되므로 사용자 정의 속성명으로 사용하지 않는다.

격리 테이블의 저장 구조

t_raw_event_log_rescue에는 원본 로그에서 확인할 수 있는 이벤트의 기본 정보와 원본 데이터, 격리 원인이 저장된다.

필드자료형설명
userIdSTRING원본 로그에서 확인할 수 있는 이용자 식별자
identifierProviderSTRING이용자 식별자를 발급한 시스템
deviceIdSTRING원본 로그에서 확인할 수 있는 기기 식별자
appIdGroupSTRING이벤트가 속한 게임(프로젝트)의 식별값
dateTimeSTRING전송된 원본 eventTime 값
eventNameSTRING이벤트를 구분하는 이름
bigqueryRegistTimestampTIMESTAMP이벤트가 BigQuery에 저장된 시각
checksumSTRING이벤트 데이터로 생성한 해시값
rawDataSTRING전송한 이벤트의 원본 JSON
errorReasonSTRING이벤트가 격리된 원인을 나타내는 코드
errorStackTraceSTRING누락된 필드 등 격리 원인에 대한 상세 정보

정상 테이블의 dateTime에는 eventTime을 변환한 TIMESTAMP 값이 저장된다. 격리 테이블의 dateTime에는 전송한 값의 문제를 확인할 수 있도록 원본 eventTime이 문자열로 저장된다.

contents_success 격리 사유 확인하기

contents_success 이벤트를 전송했을 때 격리된 데이터를 BigQuery에서 확인하는 과정이다.

💡 BigQuery 조회 권한 신청

격리 사유를 확인하려면 BigQuery 원본 데이터 조회 권한이 필요하다. BigQuery를 이용하려면 애널리틱스 관리자 권한을 획득한 후 애널리틱스 계정 메뉴에서 BigQuery 조회 권한을 신청한다. 권한이 적용되면 Google Cloud의 BigQuery 콘솔에 접속하고, 탐색기에서 조회 권한이 부여된 애널리틱스 프로젝트와 회사별 데이터셋을 확인한다. 이후 해당 데이터셋의 t_raw_event_log_rescue를 조회한다. BigQuery 사용에 대한 자세한 내용은 개발자 사이트의 BigQuery 설정에서 확인할 수 있다.

BigQuery에서 t_raw_event_log_rescue의 errorReason, errorStackTrace와 rawData를 조회한 화면
격리 데이터를 조회하고 오류 코드와 원본 데이터를 확인한다.

BigQuery에서 t_raw_event_log_rescue를 조회한 결과 errorReason이 201로 표시되었다. errorStackTrace와 rawData를 확인하면 eventTime이 2026-10-26T17:51:57+09:00+09:00으로 전송되어 타임존이 중복된 것을 확인할 수 있다. 이 값은 RFC 3339 형식에 맞지 않아 저장용 dateTime으로 파싱할 수 없다.

격리 코드 및 조치 사항

errorReason조치 사항
100전송한 메시지가 유효한 JSON이 아니다. JSON 형식을 검증한 후 전송한다.
200eventTime 필드를 타임존이 포함된 RFC 3339 형식으로 전송한다. 또한 eventTime의 시간 값이 허용 범위(과거 10년~미래 5년)에 포함되도록 전송한다.
201eventTime 필드를 타임존이 포함된 RFC 3339 형식으로 전송한다.
300attributes, eventAttributes, hiveAttributes는 파이프라인이 자동 생성하는 예약 필드이므로 이벤트에 직접 포함하지 않는다. _로 시작하는 필드명은 파이프라인 내부용으로 예약되어 있으므로 사용하지 않는다.
400필수 필드(userId, identifierProvider, deviceId, appId, eventName, eventTime)가 모두 포함되었는지 확인한 뒤 전송한다.
401이벤트 속성값에 JSON 객체({}) 또는 배열([])이 포함되어 있다. 모든 속성은 1뎁스 flat 구조(문자열/숫자)로 전송한다. JSON 문자열("{...}", "[...]")도 거부된다.

정상적인 eventTime의 형식과 허용 범위를 확인한 뒤 2026-10-26T17:51:57+09:00처럼 타임존을 한 번만 포함하도록 수정해 다시 전송한다. 이후 동일한 조건으로 데이터를 조회해 수정한 이벤트가 t_raw_event_log에 정상적으로 저장되었는지 확인한다.

Hive 애널리틱스 시작해보기

정상적으로 수집된 이벤트는 t_raw_event_log에 저장되고, 수집 기준을 충족하지 못한 이벤트는 원본 데이터와 오류 정보를 포함해 t_raw_event_log_rescue에 격리된다. 두 테이블을 함께 확인하면 이벤트의 저장 결과를 구분하고, 정상적으로 수집되지 않은 로그의 원인을 찾아 전송 코드를 수정할 수 있다.

Hive 애널리틱스는 수집된 게임 이벤트를 분석하고, 정상적으로 처리되지 않은 이벤트 로그의 격리 사유와 원본 데이터를 확인해 문제의 원인을 파악할 수 있는 게임 전문 애널리틱스 솔루션이다. 지금 Hive 애널리틱스의 BigQuery 데이터셋에서 이벤트의 전송 상태를 확인해보자.

김동완 기자

애널리틱스가 게임 운영과 의사결정에 도움이 되기를 바랍니다. 앞으로도 게임 운영에 유용하게 활용할 수 있는 다양한 기능과 활용 방법을 꾸준히 소개할 예정이니, 애널리틱스에 많은 관심 부탁드립니다.


TOP