🖇 RFM 스코어
🖇 Recency
🖇 Frequency
🖇 Monetary
🖇 RFM으로 인사이트 도출하기
이제 전처리한 데이터를 가지고 고객별 구매 패턴을 파악하여 고객을 세그먼테이션해야 한다.
다양한 고객 세그먼테이션 방법 중 왜 RFM 지표일까?
예를 들어,
오랜만에 한 번 크게 지출한 고객 과
최근 자주 방문하지만 금액은 소액인 고객 은
동일하게 취급할 수 있을까?
그래서 해당 프로젝트에서는 고객별로 얼마나 최근에(Recency), 얼마나 자주(Frequency), 얼마나 많이(Monetary) 지출했는지를 기준으로 고객을 나누는 RFM 분석을 선택했다.
이제 전처리된 이커머스 데이터를 바탕으로 고객별 구매 패턴을 분석하고, RFM 기반의 세그먼테이션을 통해 인사이트를 도출해 보자.
RFM 분석(Recency, Frequency, Monetary)은 고객을 세 가지 기준으로 분류하는 대표적인 세그먼테이션 기법이다.
Recency(최신성): 마지막 구매가 얼마나 최근이었는가?
Frequency(구매 빈도): 얼마나 자주 구매했는가?
Monetary(구매 가치): 얼마나 많은 금액을 지출했는가?
이 세 가지 기준을 통해 기업은 충성 고객, 이탈 고객, 신규 고객, 재활성화 대상 고객 등으로 나누고, 각 그룹에 맞춘 마케팅 전략을 수립할 수 있다.
해당 프로젝트에서도 RFM 분석을 포함한 고객 세그먼테이션 기법을 통해 고객을 분류하고 각 그룹에 맞는 마케팅 전략을 세워볼 것이다.
RFM 지표에 대해 더 자세히 알고 싶다면 [SQL] RFM 분석 해당 글을 참고하기 바란다 :)
Recency 단계에서는 고객이 얼마나 최근에 구매를 했는지에 중점을 둔다. 따라서 '마지막 구매일로부터 현재까지 경과한 일수'를 계산해야 한다.
우선 InvoiceDate를 'YYYY-MM-DD' 형태로 날짜에 해당하는 부분만 남겨놓기 위해 자료형을 변경해 보자.
InvoiceDate 컬럼 자료형 변경하기 SELECT DATE(InvoiceDate) AS InvoiceDay,
*
FROM project_name.dataset.data;
실제 회사에서 다루는 데이터라면 오늘 날짜를 기준으로 최종 구매일이 몇 일 지났는지 계산하겠지만, 데이터는 2010년~2011년 사이의 데이터이므로 최종 구매일로부터 꽤 오랜 시간이 지난 데이터라는 특성이 있다.
따라서 이번 프로젝트에서는 모든 고객들을 통틀어 가장 최근 구매 일자를 기준으로 Recency를 구하려고 한다.
SELECT
(SELECT MAX(DATE(InvoiceDate))
FROM `project_name.dataset.data`) AS most_recent_date,
DATE(InvoiceDate) AS InvoiceDay,
*
FROM project_name.dataset.data;

이번에는 유저별로 가장 최근에 일어난 구매 정보를 정리해 보자.
InvoiceDay를 가장 최근 구매일로 저장하기 SELECT CustomerID,
MAX(DATE(InvoiceDate)) AS InvoiceDay
FROM project_name.dataset.data
GROUP BY CustomerID;

most_recent_date)와 유저별 마지막 구매일(InvoiceDay)간의 차이 계산하기 SELECT CustomerID,
-- EXTRACT 함수: 날짜 또는 시간 데이터 타입에서 특정 부분을 추출할 때 사용
-- 날짜의 연도, 월, 일 또는 시간의 시, 분, 초 등을 추출할 수 있다.
EXTRACT(DAY FROM MAX(InvoiceDay) OVER () - InvoiceDay) AS recency
FROM (
SELECT CustomerID,
MAX(DATE(InvoiceDate)) AS InvoiceDay
FROM project_name.dataset.data
GROUP BY CustomerID
);

이제 최종 데이터 셋에 필요한 데이터들을 각각 정제해서 이어붙이자.
user_r 테이블로 저장하기 CREATE OR REPLACE TABLE `project_name.dataset.user_r` AS
SELECT CustomerID,
EXTRACT(DAY FROM MAX(InvoiceDay) OVER () - InvoiceDay) AS recency
FROM (
SELECT CustomerID,
MAX(DATE(InvoiceDate)) AS InvoiceDay
FROM project_name.dataset.data
GROUP BY CustomerID
);

Recency 값이 낮을수록 고객이 최근에 구매를 했음을 의미하며, 제품이나 서비스에 더 관심을 보인다고 예측할 수 있다.
Recency를 통해 오랜 시간 동안 구매를 하지 않았던 고객을 발견하고, 다시 제품과 서비스로 불러들이기 위한 마케팅 전략을 맞춤화해볼 수도 있을 것이다.
Frequency를 계산하는 단계에서는 고객의 구매 빈도 또는 참여 빈도에 초점을 맞춘다.
전체 거래 건수로 계산을 할 수도 있고, 구매한 아이템의 총 수량으로 합하여 계산할 수도 있다.
예를 들어 한 명의 고객이 구매를 2번 했는데 각각 아이템을 4개씩 구매한 경우, 해당 고객의 거래 건수는 2회겠지만 실제로 구매한 수량은 8개가 됩니다.
이 두가지 측면을 모두 포착하기 위해 두 경우를 모두 계산해 보자.
1. 전체 거래 건수 계산
우선 각 고객의 거래 건수를 계산해 보자. 참고로 거래 건은 InvoiceNo를 기준으로 파악된다.
InvoiceNo 수 확인하기 SELECT CustomerID,
COUNT(DISTINCT InvoiceNo) AS purchase_cnt
FROM project_name.dataset.data
GROUP BY CustomerID;

2. 구매한 아이템의 총 수량 계산
SELECT CustomerID,
SUM(Quantity) AS item_cnt
FROM project_name.dataset.data
GROUP BY CustomerID;

위에서 구한 1. 전체 거래 건수 계산과 2. 구매한 아이템의 총 수량 계산의 결과를 합쳐서 user_rf라는 이름의 테이블에 저장할 것이다.
user_rf 테이블에 저장하기 CREATE OR REPLACE TABLE `project_name.dataset.user_rf` AS
-- (1) 전체 거래 건수 계산
WITH purchase_cnt AS (
SELECT CustomerID,
COUNT(DISTINCT InvoiceNo) AS purchase_cnt
FROM project_name.dataset.data
GROUP BY CustomerID
),
-- (2) 구매한 아이템 총 수량 계산
item_cnt AS (
SELECT CustomerID,
SUM(Quantity) AS item_cnt
FROM project_name.dataset.data
GROUP BY CustomerID
)
-- 기존 user_r 테이블과 병합
SELECT pc.CustomerID,
pc.purchase_cnt,
ic.item_cnt,
ur.recency
FROM purchase_cnt AS pc
JOIN item_cnt AS ic
USING(CustomerID)
JOIN project_name.dataset.user_r AS ur
USING(CustomerID);

어떤 고객은 거래 횟수는 적지만 한번에 많이 구매한다.
반대로 거래는 자주 하지만 소량씩 구매하는 고객도 있다.
따라서, 두 지표를 함께 보아야 진정한 "빈도"를 파악할 수 있게 된다.
Monetary를 계산하는 단계에서는 고객이 지불한 총 금액에 초점을 맞춘다.
이 때 고객별 총 지출액을 계산할수도 있고, 고객별 평균 거래 금액을 계산할 수도 있다.
예를 들어 한 명의 고객이 총 2번의 구매를 했고 그 합산 금액이 10만원인 경우, 총 지출액은 10만원, 거래당 평균 거래 금액은 5만원이 되는 것이다.
이 두 가지 측면을 모두 포착하기 위해 고객별 총 지출액과 평균 거래 금액을 모두 계산해 보자.
1. 고객별 총 지출액 계산
SELECT CustomerID,
ROUND(SUM(Quantity * UnitPrice), 1) AS user_total
FROM project_name.dataset.data
GROUP BY CustomerID;

2. 고객별 평균 거래 금액 계산
고객별 평균 거래 금액을 구하기 위해 1) data 테이블을 user_rf 테이블과 조인(LEFT JOIN) 한 후, 2) purchase_cnt로 나누어서 3) user_rfm 테이블로 저장해 봅시다.
data 테이블을 user_rf 테이블과 조인(LEFT JOIN) 한 후, 2) purchase_cnt로 나누어서 3) user_rfm 테이블로 저장하기 CREATE OR REPLACE TABLE `project_name.dataset.user_rfm` AS
SELECT rf.CustomerID AS CustomerID,
rf.purchase_cnt,
rf.item_cnt,
rf.recency,
ut.user_total,
ROUND(ut.user_total / rf.purchase_cnt, 1) AS user_average
FROM project_name.dataset.user_rf AS rf
LEFT JOIN (
-- 고객 별 총 지출액
SELECT CustomerID,
ROUND(SUM(Quantity * UnitPrice), 1) AS user_total
FROM project_name.dataset.data
GROUP BY CustomerID
) AS ut
USING(CustomerID);
user_rfm 테이블 출력하기 SELECT *
FROM project_name.dataset.user_rfm;

이들과의 관계는 유지하는 것이 중요하며 프리미엄 상품 추천이 효과적일 수 있다.
즉, 결제한 총 금액이 높은 고객을 찾는 것도 좋지만 한번에 많이 구매하는 고객들을 찾는 것도 굉장히 중요하다.
결제 금액은 낮지만 구매를 자주 하는 고객과, 한번 결제할 때 큰 금액을 결제하는 고객은 분명 특성이나 행동 패턴이 다를 것이기 때문이다.
이렇게 RFM 분석을 통해 고객들의 구매 행동을 정량적으로 파악하고, 아래와 같은 시야를 얻을 수 있었다.
💡 Recency "최근 방문한 고객은 빠르게 반응할 가능성이 높다"
Recency가 낮은 고객들은 최근에 방문한 고객으로, 서비스에 대한 관심이 지속되고 있는 상태이다. 이들은 즉각적인 마케팅에 반응할 확률이 높으므로, 신제품 추천, 단기 할인 쿠폰 제공 등의 전략이 효과적일 것이다.
반면, Recency가 높은 고객은 이탈 가능성이 있으므로, 재방문 유도 캠페인이 필요할 수 있다.
💡 Frequency "자주 방문하는 고객은 충성도가 높다"
구매 빈도가 높은 고객은 서비스에 대한 신뢰도가 높고, 정기적으로 방문하는 루틴이 형성되어 있을 가능성이 있다. 이들은 리워드 프로그램, 멤버십 유도를 통해 장기 고객으로 유도할 수 있을 것이다.
반면, 빈도가 낮은 고객은 특정 이벤트로 유입된 일회성 고객일 수 있으므로, 구매 후 경험을 개선하여 재방문을 유도하는 전략이 필요하다.
💡 Monetary "고액 결제 고객은 VIP 관리 대상이다"
지출 금액이 높은 고객은 전체 매출에 기여하는 비중이 크기 때문에 우선순위 타겟으로 관리해야 한다. 이들에게는 프리미엄 상품, 개인화된 추천, 전용 혜택 제공이 효과적일 수 있다.
반면, 지출 금액이 낮지만 구매 빈도가 높은 고객은 잠재적인 고액 고객으로 육성 가능성이 있다.
이렇게 RFM 분석은 고객을 세그먼테이션할 때 매우 강력한 지표로 사용되지만, 사실 쇼핑 패턴의 복잡성을 완전히 설명하긴 어렵다.
예를 들어
🤔 "10개의 서로 다른 제품을 1개씩 산 고객"
vs
🤔 "1개의 제품을 10개 산 고객"
이 두 고객은 쇼핑 성향이 완전히 다르지만, 단순 RFM 분석에서는 동일한 수치로 분류될 수 있다.
바로 고객의 구매 행동을 더 입체적으로 이해할 수 있는 다양한 추가 Feature들을 함께 추출하는 것이다.
다음 글에서는 이처럼 RFM을 보완할 수 있는 추가 feature들을 추출하고, 이를 기반으로 고객의 성향을 보다 정확하게 파악하는 과정을 다뤄 볼 예정이다.
[해당 컨텐츠는 아이펠 캠퍼스 LMS에서 학습한 내용을 재해석한 것으로 무단 복제 및 사용을 금지합니다.]