개발/데이터 분석

게임의 이탈 원인 분석하기 - RF 활용

용묻이 2022. 7. 9. 16:08

새로운 회사에 들어온지 벌써 2달이 넘었다.
그 동안 난잡하게 여러 일들을 했는데, 한 번 정도 기록으로 남겨보고 싶었던 케이스들이 있었다.

그 중에서 RF 모델을 통해 로그 없이 게임 데이터만으로 이탈 원인 분석했던 케이스를 포스팅해 보려고 한다.

이탈 분석

모든 온라인 서비스들은 이탈에 대한 모니터링을 한다. 코호트 분석을 통한 D+N일 리텐션이나, 이벤트 로그를 심어 퍼널 차트를 만들어 분석하기도 한다.

 


(위 두 사진은 구글링 이미지이다.)

게임을 운영하면서 기획/퍼블리싱 팀에서는 여러가지 차트를 모니터링한다. 차트로부터 이상 현상을 발견하면 개발팀과의 협업을 통해 로그를 심어 심도 있게 분석하는 과정을 거친다.

가령, 모니터링을 통해 급격한 이탈 구간을 발견했다고 가정하자. 그러면 해당 구간에서 실제로 이탈했던 유저들의 로그를 모아서 "어떤 메뉴에서 얼마큼의 시간을 보냈는가", "마지막으로 사용한 기능은 무엇인가" 등을 찾아내어 이탈 원인을 발견하고 이에 대응하는 접근을 취한다.

FireBase의 이탈 또는 결제 예측 같은 기능은 개발자가 미리 정의한 이벤트 로그를 심어야 하며, 해당 로그들로부터 ML/DL 모델의 BinaryClassification 결과를 제공하여 운영팀이 선제적으로 이탈에 대응하는 걸 돕는다.

그러나 아쉽게도, 나는 로그 데이터가 접근되지 않거나(권한), 거의 없거나(양), 있어도 노이즈가 너무 많은(퀄리티) 환경에서 이탈 원인을 분석할 필요가 있었다.

여러 게임을 분석하면서 많은 접근법을 활용했다. 그 중에서 RandomForest 모델을 활용하는 것이 있었는데, 일부 게임에서만 효용이 컸다. 그래서 주된 방법론으로 차용하고 있지는 않다만 기록으로 남겨 두고자 이렇게 포스팅을 하게 되었다.

이론적으로도 초보적인 수준이고 대단한 작업도 아니니 그냥 하나의 데이터 분석 케이스로 봐주시길 바란다.

가용 데이터 확인

이탈 분석을 위해서는 퍼널 형태의 로그나 시계열 형태로 남겨진 데이터들이 필요했다. 그러나 시계열 데이터는 커녕 로그 조차 제대로 남겨지지 않은 상태였고, 나는 최신의 것으로 덮어 씌워지는 형태의 인게임 데이터만을 활용해야했다.

결측치들은 모두 0/-1과 같은 값으로 fill하거나 drop하고, array나 json으로 저장된 DTO들은 펼쳐서 저장하고. 그런 노가다스러운 feature engineering/selection 과정을 거쳤다.

EDA

이탈 원인을 분석하기 위해서는 이탈 여부 Binary Label을 먼저 만들 필요가 있다. 이 작업을 Churn Labeling이라고 하는데, 주로 특정 시점 $T$를 잡아 $T-7$일에 로그인한 이력이 있는 유저 중 $T+7$일까지 로그인한 적이 있으면 Non-Churner, 없으면 Churner로 분류한다.

다만 나는 로그인 관련 로그가 아예 다른 DB에 저장되고 있었기에(

귀차니즘

) 다른 방식으로 Churn Labeling을 진행하였다.

login_log.login_date = pd.to_datetime(login_log.login_date)
X = (login_log.login_date.max() - login_log.login_date).dt.total_seconds()
X.hist(bins=100)
plt.plot([3600 * 24 * 5] * 2, [0, 10000], c='k')


로그인 로그가 찍힌 시점부터 가장 최근 시점까지의 시간을 히스토그램으로 분석하면 이런 식으로 나타난다. 이 차트는 좀 난잡한 편인데, 중요한 것은 특정 지점에서 값이 훅 떨어지며, 그 이후로 평탄하다는 것이다. 만약 그 특정 지점이 이탈 기준이 아니라면 그 뒤가 평탄할 리가 없기에 해당 지점을 이탈 기준으로 삼아도 큰 문제가 없다.(게임마다 2일일 수도, 7일일 수도 있으므로 따로 확인해줘야 한다.)

이렇게 이탈 기준을 정하면 여러가지 차트를 그리면서 이탈자와 비이탈자를 구분할 수 있다.

예를 들어, 레벨 데이터 히스토그램을 그리고 이탈자를 표시하면 다음과 같이 그 분포를 알 수 있다.

이런 EDA 작업으로 게임 운영에 유의미한 차트를 정말 많이 작성할 수 있다.
대표적으로 다음과 같은 퍼널 분석이 있을 수 있다.


위 퍼널에서는 명백하게 1, 20레벨이 주요 이탈지점이라고 생각할 수 있다. 또한 기울기가 완만하게 꺾이는 지점 이전에서도 꾸준히 이탈이 나오므로 해당 구간에서도 어떤 일이 일어나는지 파악해야 한다.

작성할 수 있는 차트는 정말 많다. 또한 다룰 수 있는 데이터도 많다. 가령 스테이지나, 일일미션 혹은 스토리 퀘스트 클리어 Flags 등으로도 분석이 가능하다.

matplotlib의 twinx 기능을 사용하여 bar chart를 두 개 그려 비교해볼 수도 있다.

EDA는 단순히 여러 변수의 여러 차트를 그려보는 것보다 좀 더 띵킹을 섞어 진행하는 게 좋다. 특히나 데이터 샘플링이 중요한데, 어떤 경우에는 게임이 업데이트되어 이전 데이터들이 노이즈로 작용하기도 한다. 따라서 '업데이트 이후 시점부터' 샘플링하여 이탈/비이탈자 분포를 확인하는 게 좋을 것이다.

아무튼 이제 X 레벨에서 이탈을 한다!는 인사이트를 얻었다고 가정하자.

해당 구간 이탈 원인 파악

여기서 하나의 가정이 필요하다.

$X$레벨에서 유난히 이탈을 많이 한다면 해당 레벨에서 어떤 문제가 있어 사람들이 원할하게 다음 다음 구간으로 넘어가지 못한다는 것이다. 따라서 $X + 1$ 레벨 유저가 $X$ 레벨 유저와 다른 점이 있을 것이고, (기획 의도를 침범하지 않는 선에서) 그 부분을 해결해주면 유저들은 원만하게 다음 레벨로 넘어갈 수 있을 것이다. 그들은 추후에 이탈할 수 있지만, 그 중에는 LTV나 잠재적 충성도가 높은 고객이 있을 수 있으므로 전반적인 이탈률 개선을 달성할 수 있을 것이다.

이 가정이 들어맞는다면 본 포스팅에서 시도한 방법론이 유의미할 수 있다.

PairPlot

가장 수고가 덜 들면서 운 좋으면 빠르게 원인을 파악할 수 있는 방법은 PairPlot을 그리는 것이다.
$X$레벨과 $X+1$레벨의 유저들 데이터를 가져와 over_X_level과 같은 Binary Label을 만든 뒤, Seaborn 패키지의 PairPlot을 그리면서 hue 파라미터에 레이블을 넘겨주면 된다. 그러면 $X$ 레벨 유저와 $X + 1$ 레벨 유저의 차이점을 알 수 있다.


위 그림에서는 뚜렷하게 Feature B가 $X$ 레벨 유저와 $X + 1$ 레벨 유저의 차이를 결정짓는 요소라고 볼 수 있다.

PairPlot의 단점은 Feature의 수가 너무 많으면 활용하기 어렵다는 것이다. $N\times N$개의 그림을 그려주는데 $N>6$이면 사람 눈에도 잘 안들어오며 이미지를 출력하는 데도 꽤 오랜 시간이 걸린다. PairPlot의 대각 성분인 KDE Plot만 따로 그린다고 해도 $N$개의 차트가 생성되므로 피곤한 것은 매한가지다.

그래서 PairPlot은 해당 구간을 기획한 담당자와 논의하여 의심되는 유력한 후보 Feature들이 있을 때 시도하는 게 좋다.

RandomForest

의심되는 게 없을 때에는 어떻게 할까? 그 수많은 Feature들을 하나하나 그려볼 수는 없는 노릇이다. 가능하고 확실한 방법이긴 한데 스마트하지는 않은 것같다.

이 때 RF 모델이 유용하다. 사실, PDP(Partial Dependent Plot)나 피셔의 피쳐 중요도 계산법, 퍼뮤테이션을 활용한 피쳐 중요도 계산 등 아무 예측 모델이든 건전하고 정확하게 예측할 수 있다면 Feature Importance를 뽑을 수 있는 방법은 많다.


그냥 Scikit-Learn 패키지를 이용하면 빠르고 간단하게 피쳐 중요도를 뽑을 수 있기 때문에 RF를 활용하는 것이다.(sklearn 외에도 AutoViML 등을 활용했다.)

아무튼 처음엔 Feature를 다 때려넣어 예측해보자. 어떻게 될까? __퀘스트 도달 Flags, 경험치, 골드, 강화 레벨, 몬스터 잡은 횟수 등의 변수들이 상위권을 차지할 것이다. __그런 변수들은 레벨과 깊은 상관/인과 관계를 가지므로 예측 정확도를 높이는 데 큰 기여를 한다. 당연히 RF 모델은 그런 피쳐들에 집중할 것이다.

그러나 이탈 원인 분석에는 도움이 되지 않는다. 30레벨을 통과했는지 여부를 결정짓는 가장 중요한 지표가 골드나 경험치라는 분석은 아무 쓸모가 없다. 그러므로 Feature Selection 과정이 필요하다. 해당 게임을 플레이해보거나 기획한 사람이 도메인 지식으로 변수들을 제거해야 한다.

이 과정은 메뉴얼도 없고 기계적이지도 못하다. 예를 들어 무기 강화가 최상위 Feature로 선정되었다 가정하자. 무기 수준이 좋을수록 레벨이 높은 유저인 건 당연한 것 아닌가? 그러나 해당 레벨에서 하필이면 무기 강화 재료가 수급되지 않았을 수도 있다. Feature Selection 과정에서 무기 강화 레벨을 지우면 재료 수급 실패라는 현상을 찾지 못할 수도 있으며, 그런 상황이 일어나고 있지 않음에도 포함시킨다면 분석에 노이즈가 생기는 것이다.

따라서 Feature Selection에서는 기획 의도를 잘 이해하고 있는 사람이 함께 참여할 필요가 있다.
(그냥 모든 데이터 분석 프로젝트는 Domain Knowledge/Experts가 필요하다. 나도 게임 분석할 때는 그 게임을 한참 해보고 필요하면 현질까지 하면서 분석한다.)

모델 해석

적절한 Feature Selection 과정을 거쳐 모델이 학습되었을 땐 두 가지 경우가 있다. 성능이 좋거나 안좋거나. 성능이 안좋아 정확도가 50% 정도 되는 경우에는 입력 Feature만으로는 두 집단을 구분할 수 없다는 이야기이며, Feature Selection이 잘 이루어졌다면 실제로 두 집단에 차이가 없다 말할 수 있다. 이 경우에는 유저의 피로도나 흥미 부족이 원인이며, 콘텐츠 개선 및 추가 개발로 해결해야 하는 경우들이 많다.

정확도가 높게 나왔다면 Feature Importance를 유심히 보면 된다. 피쳐 중요도에서 상위에 위치한 피쳐들을 몇 개 뽑아 PairPlot을 그리면 이탈 원인에 대해서 이해하기 쉽다.

몇 가지 케이스를 공유해보겠다.

특정 장비 소유 여부

방치형 로스트아크라는 모바일 게임이 있다고 가정해보자. 무기, 방어구, 장신구 상관 없이 오로지 돌 장착 여부로 갈리는 경우가 있었다. PairPlot으로 확인해보니 보유한 돌의 각인 수치 분포는 뚜렷한 차이가 있었으며, 무기/방어구/장신구의 여러 수치들은 거의 동일한 분포를 보였다. 왜 하필 돌일까?

이는 기획적으로 의도되지 않은 현상이었으나, 어쩌다보니 돌이 없으면 사실상 통과가 불가능한 구간이 형성되었다. 예를 들어, 무기는 공격력, 장신구는 공격속도, 돌은 치명타 확률 및 치명타 데미지에 관여한다고 가정하자(로스트아크는 실제로는 그렇지 않다). 해당 구간은 몹의 체력이 과하게 높게 설정되었고, 10배의 데미지를 주는 치명타 없이는 클리어가 불가능하다. 따라서 좋은 돌을 장착했는지에 대한 여부가 중요해지며, 여기서 돌이라는 장비와 그 수급처 등에 대해 충분히 안내받지 못한 유저는 지루함을 느끼고 이탈했을 가능성이 높다.

기획적으로 해당 구간에서 돌을 수급하기 어렵도록 설계되었을 수도 있으며, 이 경우에는 기획 조정이 필요하다.

튜토리얼 종료

피쳐 중요도 최상위 피쳐 몇 개가 튜토리얼에 관련한 변수였다. 튜토리얼 몇 단계에 있냐는 step 변수와 클리어 여부에 대한 flag 변수 등이었다. 그래서 튜토리얼이 있는 초반 1~N레벨 유저들을 집중적으로 분석하였고, 초반 게임 과정을 모니터링한 결과 $X$레벨이 튜토리얼이 끝나는 지점이었던 것이다.

튜토리얼 끝나면 게임을 어느 정도 이해한 것이고, 거기서 재미가 없어 이탈하는 것은 자연스러운 현상이라고 생각할 수도 있다. 그러나 이 게임에서의 튜토리얼은 유저들에게 UX적으로 튜토리얼이 아니라 '단기적 목표'로 이해되었다. 튜토리얼은 게임 초반에 지속적으로 "몬스터 1000마리 사냥", "아무 장비 5회 강화" 등과 같은 목표와 그에 따른 보상을 제시했다. 튜토리얼보다는 미션의 성격이었던 것이다.

동일한 장르의 타 게임들은 이런 단기 목표들이 무한하게 제시되는 경우가 종종 있었다. 그러나 해당 게임은 몇 개의 튜토리얼 이후 제시되는 목표와 보상이 없었기에, 유저들은 튜토리얼이 끝나는 시점에서 무엇을 해야 할지 방황하다가 이탈을 했던 것이다.

한계점

이런 식으로 인게임 데이터 위주로 이탈 구간 및 원인을 분석할 수 있다. 그러나 한계점이 많은 방법론이라 생각한다.

몇 가지 제한적인 가정들이 필요했으며, 이를 만족하지 않는 게임은 상당히 많다. 본문에서 다루었던 레벨에 관한 분석을 예로 들면, 레벨을 넘긴다고 정말 좋아지는 것일까에 대한 의문이 있을 것이다. 만약 30레벨에서 하루 평균 100명이 이탈해야 정상인데 150명이 이탈하고 있었다. 분석 이후 업데이트를 진행하여 50명이 30레벨을 통과했다고 치더라도, 그 50명이 전부 나중에 이탈을 한다면 이탈의 근본적인 원인은 다른 데 있을 수 있다.

도메인 지식에 크게 의존하는 것도 아쉽다면 아쉬운 점이다. 상관 관계만을 분석해낼 수 있기 때문에 인과 관계를 추론하기 위해서는 Domain Experts가 반드시 필요하다. 데이터 분석가는 그들에게 현재 발생하고 있는 현상을 잘 설명해야 하며, Domain Experts는 그 원인을 빠르게 추론해야 한다. 만약 그 원인이 바로 떠오르지 않는다면 로그를 심어 데이터를 새로 쌓고 퍼널 분석을 진행해야 한다. 지속적으로 데이터가 잘 쌓이도록 파이프라인을 잘 설계했다면 상관 없겠으나 그렇지 않은 경우에는 결론이 나기까지 시간이 다소 요구될 것이다.