마코프 체인과 멀티터치 기여도 분석 운영

마코프 체인 기반 멀티터치 기여도 분석의 경로 모델링, 제거 효과, 검증 체계와 예산 재배분 활용 방식을 정리한다.

2026-08-14 · 최초 발행 2024-04-29

전환 경로를 채널별 기여도로 바꾸는 방식

퍼스트파티 데이터를 중심으로 광고와 CRM 접점의 효과를 측정하려면, 마지막 클릭만으로는 부족하다. Multi-Touch Attribution(MTA)은 고객 여정에 포함된 여러 접점이 전환에 기여한 비율을 나누는 방법론이며, 라스트 클릭 편향을 줄이는 데 목적이 있다.

기여도 배분 방식은 규칙 기반과 알고리즘 기반으로 나뉜다. 규칙 기반에는 First, Last, Position, Time-decay가 있고, 알고리즘 기반에는 Markov와 Shapley가 있다.

마코프 체인 기반 접근은 고객의 전환 경로를 상태 전이 확률로 다루는 흡수 마코프 체인 방식이다. 특정 채널을 제거했을 때 전환 확률이 얼마나 감소하는지를 계산해 기여도를 산정하므로, 채널의 순서와 상호작용을 반영할 수 있다.

Shapley는 게임이론에 기반해 평균 한계 기여도를 구한다. 공정성 측면이 강점이고 해석 안정성도 양호하지만 계산량이 높다. Markov는 경로 순서와 전이 구조를 반영하면서 계산 효율이 좋지만, 경로 희소성과 데이터 품질에 민감하다.

경로 데이터가 모델의 품질을 좌우한다

MTA 이전에 데이터 레이어와 식별 체계를 정리해야 한다. 퍼스트파티 ID를 중심으로 쿠키, 디바이스, 로그인 식별자를 통합하고, 접점 택사노미를 표준화한다. 이벤트 스키마는 채널, 캠페인, 타임스탬프, 세션, 비용, 전환 플래그를 정규화해 설계한다.

경로를 만들 때는 세션화 규칙과 길이 제한이 필요하다. 예를 들어 세션은 30분 기준으로 나누고, 경로 길이는 10스텝으로 제한할 수 있다. 각 경로에는 START, CONVERT, DROP 상태를 추가한다. 광고 클릭과 노출의 중복을 제거하고, 브랜드·논브랜드 또는 유료·자연 채널처럼 일관된 기준으로 채널을 버킷팅해야 한다.

알고리즘 계층에서는 Time-decay, U-shape, W-shape 같은 규칙 기반 모델과 Markov, Shapley를 함께 운영할 수 있다. Markov 모델은 전이행렬 추정, 흡수확률 계산, 채널 제거 효과 산정, 정규화 분배 순으로 진행된다.

검증은 홀드아웃 경로 재현율, 월간 기여도 변동폭을 보는 안정성 지수, Σ기여=총전환·총비용의 비용 일치성으로 수행한다. 룰셋, 윈도우, 스무딩은 버전 관리하고, 유실·지연·스파스 상태를 감지하는 데이터 품질 경보도 둔다.

입력부터 예산 재배분까지의 흐름

입력 데이터는 채널·캠페인·타임스탬프·사용자 ID를 포함한 터치포인트 로그, 전환 이벤트, 비용 데이터다. 세션화와 경로 구성을 거쳐 희소 채널을 병합하고, 라플라스 스무딩과 시간가중치 여부를 선택해 전이행렬을 추정한다.

그다음 CONVERT와 DROP의 흡수확률을 구하고, 채널을 하나씩 제외했을 때의 Removal Effect를 계산한다. 결과는 전환·매출·비용 기준으로 정규화하며 리프트와 증분 지표를 함께 본다. 채널 또는 캠페인별 기여 전환·매출을 바탕으로 CAC와 ROAS를 다시 계산하고 예산 재배분안을 만들 수 있다.

결측/지연 존재정상아니오입력: 터치포인트로그/전환/비용세션화·경로 구성START/CONVERT/DROP 추가데이터 품질 점검재수집·지연 처리임시 제외 채널 마킹채널 버킷팅·희소 채널 병합Markov 전이행렬 추정(스무딩/시간가중)경로 희소성?규칙 기반 백오프Time‑decay/U‑shape흡수확률 계산(CONVERT/DROP)채널 제거 효과 계산P_conv_all vs P_conv_wo(c)기여도 정규화·보고서 생성캠페인 예산 재배분·액티베이션모니터링·드리프트 감지

제거 효과를 계산하는 마코프 체인

사용자별 접점을 시간순으로 정렬한 뒤 START와 CONVERT, DROP을 경로에 넣는다. DROP은 타임아웃이나 세션 종료를 나타내는 흡수 상태다. 경로 길이 캡을 적용하고 같은 접점이 연속되는 경우에는 축약 규칙을 둔다.

전이행렬은 상태 i에서 j로 이동한 빈도를 바탕으로 확률을 추정한다. 라플라스 스무딩은 α=15 범위로 적용해 제로 분모를 피할 수 있다. 최근 경로에 더 높은 비중을 주려면 w∈[0.5,1.5]의 시간가중치를 사용하며, 운영 윈도우는 예를 들어 3090일로 둔다.

채널 c의 제거 효과는 다음과 같이 정의한다.

RE(c) = (Pconv(all) − Pconv(wo c)) / Pconv(all)

전 채널에 대해 이 값을 계산한다. 특정 채널을 제거했을 때 전환 흡수확률 감소율이 클수록 해당 채널은 전환 유도 또는 경로 연결에 더 크게 기여한 것으로 해석한다. 제거 효과 비중은 전환 수, 매출, 비용 스케일에 맞춰 분배한다.

희소 채널은 롱테일을 “Other”로 통합하고 최소 샘플 스레숄드를 적용해 안정화한다. 주별 변동은 지수이동평균(EMA)으로 완화할 수 있으며, 상한과 하한 클리핑도 함께 사용한다.

모델 선택에서 보는 운영상 차이

방법 성능(예측/재현) 확장성 일관성 안정성 운영 편의
규칙 기반(Time/U/W) 매우 높음 높음 매우 높음
Markov Chains 중~높음 높음 중~높음 높음
Shapley 높음 중(가속 필요) 높음 높음

성능은 경로 구조와 데이터 품질에 따라 달라진다. Shapley는 근사 또는 샘플링 최적화가 필요하다.

기여도 결과를 의사결정에 연결하는 방법

예산 재배분에서는 Markov RE가 높은 채널을 증액하되, 한계수익 체감을 고려해 단계적으로 늘린다. 브랜드 검색의 과대배분을 교정하고 어퍼퍼널 채널을 보정하는 데도 사용할 수 있다.

리타겟팅에서는 경로 중복이나 과빈도 채널의 RE가 낮을 때 빈도 캡과 쿼터를 축소한다. 이는 인벤토리 낭비와 중복 비용을 줄이는 판단 근거가 된다.

랜딩 페이지와 크리에이티브 실험은 Assist→Convert 전이 확률이 높은 조합부터 우선순위를 둘 수 있다. 이탈 전이가 높은 구간은 전환 마찰을 줄일 개선 항목으로 연결한다.

쿠키 제약 환경에서는 MTA의 단편적인 경로 정보를 MMM 피처로 주입해 보완할 수 있다. 서버사이드 태깅과 컨센트 기반 로깅을 결합하는 운영 방식도 여기에 포함된다.

기대할 수 있는 변화와 전제

경험치 기반 범위이며 산업과 데이터 품질에 따라 달라질 수 있지만, CAC 1025% 절감, 중복지출 1530% 축소, 비효율 캠페인 20% 이상 식별이 정량 효과로 제시된다. 동일 예산에서는 전환이 5~15% 증가할 수 있고, 어시스트 채널의 가치를 다시 평가하면서 ROAS 개선을 기대할 수 있다.

정성적으로는 채널 간 상호작용을 가시화하고 라스트 클릭 편향을 줄일 수 있다. 실험과 예산 의사결정의 설명가능성, 그리고 거버넌스도 강화된다.

프라이버시와 모델 거버넌스의 균형

식별은 퍼스트파티 ID를 우선하고, PII는 해시 또는 가명처리한다. 최소 수집 원칙과 동의·보관정책을 따라야 한다. 서버사이드 수집은 신뢰성을 높일 수 있지만 실시간성과 비용 사이에는 트레이드오프가 있다.

룰셋, 윈도우, 스무딩 하이퍼파라미터는 버전으로 관리한다. 월간 리프레시와 분기별 리콜리브레이션을 수행하며, EMA와 클리핑으로 얻는 안정성 및 변화에 민첩하게 반응하는 민감도 사이의 균형을 관리한다.

홀드아웃 백테스트에서는 경로 재현율을 보고, 캘리브레이션에서는 Σ기여=총전환·총비용을 확인한다. 지역 또는 오디언스 단위 증분 테스트와 함께 사용하고, MMM 및 Geo-lift로 보완한다.

Markov 제거 효과 계산 예시

전제조건: Python 3.10+, pandas 2.x, numpy 1.26+. 샘플 수준 구현이며, 대규모 데이터에는 스파스 행렬과 분산처리를 권장한다.

import pandas as pd
import numpy as np

# 입력: user_id, channel, ts, converted(bool)
df = pd.read_csv("touchpoints.csv", parse_dates=["ts"])
df = df.sort_values(["user_id", "ts"])

# 경로 구성
paths = (df.groupby("user_id")
           .apply(lambda g: ["START"] + g["channel"].tolist() + (["CONVERT"] if g["converted"].max() else ["DROP"]))
           .tolist())

# 전이 카운트
from collections import Counter, defaultdict
trans = defaultdict(Counter)
for p in paths:
    for i in range(len(p)-1):
        trans[p[i]][p[i+1]] += 1

# 전이확률(라플라스 스무딩)
states = list(set([s for p in paths for s in p]))
alpha = 1.0
P = {s: {} for s in states}
for i in states:
    total = sum(trans[i].values()) + alpha*len(states)
    for j in states:
        P[i][j] = (trans[i][j] + alpha) / total

# 흡수확률 계산 유틸
def absorb_prob(P, start="START", convert="CONVERT", drop="DROP", iters=1000):
    # 벡터 반복법
    states = list(P.keys())
    idx = {s:i for i,s in enumerate(states)}
    M = np.array([[P[i][j] for j in states] for i in states])
    v = np.zeros(len(states)); v[idx[start]] = 1.0
    acc = 0.0
    for _ in range(iters):
        v = v @ M
        acc += v[idx[convert]]
        # 흡수 상태로 질량 전이 후 제거
        v[idx[convert]] = 0.0
        v[idx[drop]] = 0.0
        if v.sum() < 1e-10:
            break
    return acc

base = absorb_prob(P)

def removal_effect(channel):
    P_wo = {i: P[i].copy() for i in P}
    # channel 제거: 해당 전이 0, 확률 재분배(정규화)
    for i in P_wo:
        P_wo[i][channel] = 0.0
        s = sum(P_wo[i].values())
        for j in P_wo[i]:
            P_wo[i][j] = P_wo[i][j]/s if s>0 else 0.0
    conv = absorb_prob(P_wo)
    return max((base - conv)/base, 0.0)

channels = [c for c in states if c not in ("START","CONVERT","DROP")]
re = {c: removal_effect(c) for c in channels}
contrib = pd.Series(re) / (pd.Series(re).sum() + 1e-9)  # 정규화
print(contrib.sort_values(ascending=False))

대규모 데이터에는 희소행렬과 흡수 마코프 해석해인 기본행렬 N=(I−Q)^−1 사용을 권장한다.

마케팅 분석마코프 체인멀티터치 기여도전환 경로예산 최적화