프로젝트/GA4 분석

[GA4 퍼널 분석] Day4-1 (begin_checkout → purchase | Mobile UX 분석)

조성호 2026. 5. 9. 18:15

장바구니 추가 구간 퍼널 분석 결과, 결제 시작 이후 구매 완료 전환율이 가장 큰 병목으로 나타났음
따라서 이번에는 구매 완료 직전 이탈 원인을 가설 기반으로 검증할 예정

 

가설

모바일 결제 UX 문제

- 모바일 결제 UX 문제 때문에 Purchase 전환율이 낮은가?

 

1. 필요한 원천 데이터 확인

- event_name에 begin_checkout, purchase가 있는가?
- device_category에 mobile, desktop, tablet 등이 있는가?
- ga_session_id가 NULL이 아닌 값으로 존재하는가?

-- STEP 1: 원천 데이터 구조 확인
-- 목적:
-- purchase 분석에 필요한 event_name, device.category, ga_session_id가 정상적으로 존재하는지 확인한다.

SELECT
  event_date,

  -- 이벤트명 확인
  event_name,

  -- 디바이스 유형 확인
  device.category AS device_category,

  -- 세션 ID 확인
  (
    SELECT value.int_value
    FROM UNNEST(event_params)
    WHERE key = 'ga_session_id'
  ) AS ga_session_id,

  -- 사용자 ID 확인
  user_pseudo_id
FROM
  `bigquery-public-data.ga4_obfuscated_sample_ecommerce.events_*`
WHERE
  _TABLE_SUFFIX BETWEEN '20210101' AND '20210131'
LIMIT 100;
event_date event_name device_category ga_session_id user_pseudo_id
1 20210109 user_engagement desktop 1602771170 1001844.096
2 20210109 first_visit desktop 1602771170 1001844.096
3 20210109 page_view desktop 1602771170 1001844.096
4 20210109 scroll desktop 1602771170 1001844.096
5 20210109 page_view desktop 1602771170 1001844.096
6 20210109 page_view desktop 1602771170 1001844.096
7 20210109 page_view desktop 1602771170 1001844.096
8 20210109 scroll desktop 1602771170 1001844.096
9 20210109 user_engagement desktop 1602771170 1001844.096
10 20210109 scroll desktop 1602771170 1001844.096

 

2. 분석 대상 이벤트만 필터링

- 분석 대상 이벤트가 begin_checkout, purchase로만 잘 제한되었는가?
- device_category가 함께 붙어 있는가?
- 세션 ID가 함께 추출되는가?

-- STEP 2: 결제 단계 이벤트만 필터링
-- 목적:
-- begin_checkout과 purchase 이벤트만 추출하여
-- 결제 시작 후 구매 완료 여부를 분석할 준비를 한다.

SELECT
  user_pseudo_id,

  (
    SELECT value.int_value
    FROM UNNEST(event_params)
    WHERE key = 'ga_session_id'
  ) AS ga_session_id,

  device.category AS device_category,

  event_name
FROM
  `bigquery-public-data.ga4_obfuscated_sample_ecommerce.events_*`
WHERE
  _TABLE_SUFFIX BETWEEN '20210101' AND '20210131'
  AND event_name IN ('begin_checkout', 'purchase')
LIMIT 100;
user_pseudo_id ga_session_id device_category event_name user_pseudo_id
1 1158637.038 2473786972 mobile begin_checkout 1001844.096
2 1158637.038 2473786972 mobile begin_checkout 1001844.096
3 1158637.038 2473786972 mobile begin_checkout 1001844.096
4 1158637.038 2473786972 mobile purchase 1001844.096
5 2831057.058 930301630 desktop begin_checkout 1001844.096
6 2831057.058 930301630 desktop begin_checkout 1001844.096
7 2831057.058 930301630 desktop begin_checkout 1001844.096
8 2976470.575 3580327648 desktop begin_checkout 1001844.096
9 2976470.575 3580327648 desktop begin_checkout 1001844.096
10 2976470.575 3580327648 desktop begin_checkout 1001844.096

 

3. 세션 ID 만들기

- session_id가 user_pseudo_id-ga_session_id 형태로 생성되었는가?
- NULL 세션이 제거되었는가?
- 동일 세션 안에서 begin_checkout과 purchase를 비교할 준비가 되었는가?

-- STEP 3: 고유 세션 ID 생성
-- 목적:
-- user_pseudo_id와 ga_session_id를 결합하여
-- 세션 단위 분석이 가능한 session_id를 생성한다.

SELECT
  -- 사용자 ID와 세션 ID를 결합하여 고유 세션 생성
  CONCAT(
    user_pseudo_id,
    '-',
    CAST((
      SELECT value.int_value
      FROM UNNEST(event_params)
      WHERE key = 'ga_session_id'
    ) AS STRING)
  ) AS session_id,

  device.category AS device_category,

  event_name
FROM
  `bigquery-public-data.ga4_obfuscated_sample_ecommerce.events_*`
WHERE
  _TABLE_SUFFIX BETWEEN '20210101' AND '20210131'
  AND event_name IN ('begin_checkout', 'purchase')
  AND (
    SELECT value.int_value
    FROM UNNEST(event_params)
    WHERE key = 'ga_session_id'
  ) IS NOT NULL
LIMIT 100;
session_id device_category event_name
1 1461470.1796917150-1525083024 desktop begin_checkout
2 1461470.1796917150-8662366916 desktop begin_checkout
3 1461470.1796917150-9592361978 desktop begin_checkout
4 1461470.1796917150-1525083024 desktop begin_checkout
5 1461470.1796917150-9592361978 desktop begin_checkout
6 1461470.1796917150-9592361978 desktop begin_checkout
7 1461470.1796917150-8662366916 desktop begin_checkout
8 1461470.1796917150-9592361978 desktop begin_checkout
9 1461470.1796917150-1525083024 desktop begin_checkout
10 1461470.1796917150-9592361978 desktop begin_checkout

 

4. 세션별 결제 시작/구매 여부 만들기

- began_checkout이 1인 세션이 있는가?
- purchased가 1인 세션이 있는가?
- 같은 session_id 기준으로 결제 시작과 구매 완료 여부가 정리되었는가?

-- STEP 4: 세션별 결제 시작/구매 여부 생성
-- 목적:
-- 각 세션이 begin_checkout을 했는지,
-- purchase까지 완료했는지를 0/1 값으로 변환한다.

WITH base AS (
  SELECT
    CONCAT(
      user_pseudo_id,
      '-',
      CAST((
        SELECT value.int_value
        FROM UNNEST(event_params)
        WHERE key = 'ga_session_id'
      ) AS STRING)
    ) AS session_id,

    device.category AS device_category,

    event_name
  FROM
    `bigquery-public-data.ga4_obfuscated_sample_ecommerce.events_*`
  WHERE
    _TABLE_SUFFIX BETWEEN '20210101' AND '20210131'
    AND event_name IN ('begin_checkout', 'purchase')
    AND (
      SELECT value.int_value
      FROM UNNEST(event_params)
      WHERE key = 'ga_session_id'
    ) IS NOT NULL
)

SELECT
  session_id,

  device_category,

  -- 해당 세션에서 결제 시작 이벤트가 있었는지 여부
  MAX(CASE WHEN event_name = 'begin_checkout' THEN 1 ELSE 0 END) AS began_checkout,

  -- 해당 세션에서 구매 완료 이벤트가 있었는지 여부
  MAX(CASE WHEN event_name = 'purchase' THEN 1 ELSE 0 END) AS purchased
FROM base
GROUP BY
  session_id,
  device_category
LIMIT 100;

 

session_id device_category began_checkout purchased
1 22570371.0320972505-920839109 desktop 1 0
2 82379049.4680589452-2185402217 mobile 1 0
3 87047667.1042912591-5358392223 desktop 1 1
4 1188134.8498680538-2255400706 mobile 1 0
5 68546038.8820428933-5425867143 mobile 1 1
6 6101467.4740745406-1934665090 mobile 1 1
7 17007406.8391181695-6225971848 mobile 1 0
8 1065673.0722289663-8521814404 desktop 1 0
9 23076688.2979878923-2278105558 desktop 1 0
10 46574324.9683380755-1913386074 desktop 1 0

 

5. Device별 집계하기

- mobile, desktop, tablet별 결제 시작 세션 수 차이가 있는가?
- 구매 완료 세션 수가 결제 시작 세션 대비 얼마나 적은가?
- 특정 디바이스에서 구매 완료 세션이 유독 낮은가?

-- STEP 5: Device별 결제 시작/구매 세션 집계
-- 목적:
-- 디바이스별로 결제 시작 세션 수와 구매 완료 세션 수를 확인한다.

WITH base AS (
  SELECT
    CONCAT(
      user_pseudo_id,
      '-',
      CAST((
        SELECT value.int_value
        FROM UNNEST(event_params)
        WHERE key = 'ga_session_id'
      ) AS STRING)
    ) AS session_id,

    device.category AS device_category,

    event_name
  FROM
    `bigquery-public-data.ga4_obfuscated_sample_ecommerce.events_*`
  WHERE
    _TABLE_SUFFIX BETWEEN '20210101' AND '20210131'
    AND event_name IN ('begin_checkout', 'purchase')
    AND (
      SELECT value.int_value
      FROM UNNEST(event_params)
      WHERE key = 'ga_session_id'
    ) IS NOT NULL
),

session_event AS (
  SELECT
    session_id,

    device_category,

    MAX(CASE WHEN event_name = 'begin_checkout' THEN 1 ELSE 0 END) AS began_checkout,

    MAX(CASE WHEN event_name = 'purchase' THEN 1 ELSE 0 END) AS purchased
  FROM base
  GROUP BY
    session_id,
    device_category
)

SELECT
  device_category,

  -- 결제 시작 세션 수
  SUM(began_checkout) AS checkout_sessions,

  -- 구매 완료 세션 수
  SUM(purchased) AS purchase_sessions
FROM session_event
WHERE
  began_checkout = 1
GROUP BY
  device_category
ORDER BY
  checkout_sessions DESC;
device_category checkout_sessions purchase_sessions
1 desktop 1241 617
2 mobile 866 469
3 tablet 52 29

 

6. Device별 Checkout → Purchase 전환율 계산

- mobile의 checkout_to_purchase_rate가 desktop보다 낮은가?
- tablet은 표본 수가 너무 적지 않은가?
- 전환율 차이가 실제로 해석 가능한 수준인가?

-- STEP 6: Device별 Checkout → Purchase 전환율 계산
-- 목적:
-- 디바이스별로 결제 시작 후 구매 완료까지 이어진 비율을 계산한다.
-- mobile의 전환율이 현저히 낮다면 모바일 결제 UX 문제가 있을 가능성이 있다.

WITH base AS (
  SELECT
    CONCAT(
      user_pseudo_id,
      '-',
      CAST((
        SELECT value.int_value
        FROM UNNEST(event_params)
        WHERE key = 'ga_session_id'
      ) AS STRING)
    ) AS session_id,

    device.category AS device_category,

    event_name
  FROM
    `bigquery-public-data.ga4_obfuscated_sample_ecommerce.events_*`
  WHERE
    _TABLE_SUFFIX BETWEEN '20210101' AND '20210131'
    AND event_name IN ('begin_checkout', 'purchase')
    AND (
      SELECT value.int_value
      FROM UNNEST(event_params)
      WHERE key = 'ga_session_id'
    ) IS NOT NULL
),

session_event AS (
  SELECT
    session_id,

    device_category,

    MAX(CASE WHEN event_name = 'begin_checkout' THEN 1 ELSE 0 END) AS began_checkout,

    MAX(CASE WHEN event_name = 'purchase' THEN 1 ELSE 0 END) AS purchased
  FROM base
  GROUP BY
    session_id,
    device_category
)

SELECT
  device_category,

  -- 결제 시작 세션 수
  SUM(began_checkout) AS checkout_sessions,

  -- 구매 완료 세션 수
  SUM(purchased) AS purchase_sessions,

  -- 결제 시작 후 구매 완료 전환율
  ROUND(
    SAFE_DIVIDE(SUM(purchased), SUM(began_checkout)) * 100,
    2
  ) AS checkout_to_purchase_rate
FROM session_event
WHERE
  began_checkout = 1
GROUP BY
  device_category
ORDER BY
  checkout_to_purchase_rate ASC;
device_category checkout_sessions purchase_sessions checkout_to_purchase_rate
1 desktop 1241 617 49.72
2 mobile 866 469 54.16
3 tablet 52 29 55.77

 

전체 코드

-- 4일차 가설 1 최종 코드
-- 가설:
-- 모바일 결제 UX 문제로 인해 purchase 전환율이 낮을 수 있다.
--
-- 검증 방법:
-- Device별로 begin_checkout 이후 purchase까지 이어진 비율을 비교한다.
--
-- 해석 기준:
-- 1. mobile의 checkout_to_purchase_rate가 desktop보다 현저히 낮다면
--    모바일 결제 UX 문제가 있을 가능성이 있다.
-- 2. 디바이스별 전환율 차이가 크지 않다면
--    디바이스 자체는 주요 병목 원인이 아닐 가능성이 높다.

WITH base AS (
  SELECT
    -- 사용자 ID와 세션 ID를 결합하여 고유 세션 생성
    CONCAT(
      user_pseudo_id,
      '-',
      CAST((
        SELECT value.int_value
        FROM UNNEST(event_params)
        WHERE key = 'ga_session_id'
      ) AS STRING)
    ) AS session_id,

    -- 디바이스 유형
    device.category AS device_category,

    -- 이벤트명
    event_name
  FROM
    `bigquery-public-data.ga4_obfuscated_sample_ecommerce.events_*`
  WHERE
    -- 분석 기간 설정
    _TABLE_SUFFIX BETWEEN '20210101' AND '20210131'

    -- 결제 시작과 구매 완료 이벤트만 사용
    AND event_name IN ('begin_checkout', 'purchase')

    -- 세션 ID가 없는 이벤트는 세션 분석에서 제외
    AND (
      SELECT value.int_value
      FROM UNNEST(event_params)
      WHERE key = 'ga_session_id'
    ) IS NOT NULL
),

session_event AS (
  SELECT
    session_id,

    device_category,

    -- 해당 세션에서 결제 시작 여부
    MAX(CASE WHEN event_name = 'begin_checkout' THEN 1 ELSE 0 END) AS began_checkout,

    -- 해당 세션에서 구매 완료 여부
    MAX(CASE WHEN event_name = 'purchase' THEN 1 ELSE 0 END) AS purchased
  FROM base
  GROUP BY
    session_id,
    device_category
)

SELECT
  device_category,

  -- 결제 시작 세션 수
  SUM(began_checkout) AS checkout_sessions,

  -- 구매 완료 세션 수
  SUM(purchased) AS purchase_sessions,

  -- 결제 시작 후 구매 완료 전환율
  ROUND(
    SAFE_DIVIDE(SUM(purchased), SUM(began_checkout)) * 100,
    2
  ) AS checkout_to_purchase_rate,

  -- 결제 시작 후 이탈률
  ROUND(
    (1 - SAFE_DIVIDE(SUM(purchased), SUM(began_checkout))) * 100,
    2
  ) AS checkout_dropoff_rate
FROM session_event
WHERE
  -- 결제 시작 세션만 분석 대상으로 설정
  began_checkout = 1
GROUP BY
  device_category
ORDER BY
  checkout_to_purchase_rate ASC;

 

핵심 발견

모바일의 Checkout → Purchase 전환율이 desktop보다 오히려 높음

  • mobile: 54.16%
  • desktop: 49.72%
  • 차이: 약 +4.44%

초기 가설이었던 "모바일 UX 문제로 인해 구매 완료율이 낮다"는 가설은 기각됨

 

확인된 사실

1) 모바일 자체는 주요 병목 아님

  • 모바일 사용자는 결제 단계 진입 후 구매 완료까지 비교적 잘 이어짐
  • 모바일 UX/결제 플로우가 치명적 문제라고 보기 어려움

2) 오히려 desktop에서 이탈이 더 큼

  • 가격 비교 탭 이동
  • 장바구니 보관 후 미결제
  • 업무/탐색 목적 방문
  • 배송비/조건 비교
  • 결제 직전 이탈

 

비즈니스 관점 해석

이번 프로젝트의 핵심 병목은 디바이스 문제가 아니라 공통 결제 단계 문제 또는 의사결정 문제일 가능성이 큼

 

다음 우선순위

더 중요한 가설 후보

  1. 신규 유저 신뢰 부족
  2. 유입 채널 품질 문제
  3. 배송비/가격 부담
  4. 회원가입/결제 절차 복잡성

 

액션 아이디어

하지 말아야 할 것

  • 모바일 UX만을 문제로 단정
  • 모바일 UI 개편을 핵심 해결책으로 설정

우선 검토할 것

A. 결제 공통 UX

  • 배송비 노출 시점
  • 쿠폰 적용 UX
  • 로그인 강제 여부
  • 결제수단 다양성

B. Desktop 행동 분석

  • 결제 페이지 체류 시간
  • 결제 단계 이탈 이벤트
  • 가격 비교 가능성

 

전략적 제안

단기

Desktop checkout 최적화

  • 장바구니 리마인드
  • Exit Intent 쿠폰
  • 결제 완료 직전 배송비/혜택 명확화

중기

공통 구매 장벽 제거

  • 게스트 결제
  • 간편결제 확대
  • 총 결제 금액 조기 노출

Device별 Checkout → Purchase 전환율 분석 결과 모바일 구매 전환율은 desktop보다 높게 나타나 모바일 UX가 주요 병목이라는 가설은 기각되었음
따라서 구매 완료율 저하의 핵심 원인은 특정 디바이스 이슈보다 결제 단계 전반의 가격,신뢰,절차 요인일 가능성이 높으며 신규/재방문 유저 특성 및 유입 채널 품질에 대한 추가 검증이 필요하다고 생각함

 

구매 이탈의 핵심은 모바일 UX가 아니라 디바이스 공통의 결제 의사결정 장벽일 가능성이 높음