들어가기 전 짧은 퀴즈 하나!
여기 최근 출시된 2개의 피처(Feature) A와 B가 있습니다. 오픈 후 데이터를 살펴보니, 피처 A는 일 6,700명의 신규유저가 들어오고 D1 리텐션은 7%인 반면, 피처 B는 일 600명의 신규유저가 들어오고 D1 리텐션은 35%를 기록하고 있습니다. 그럼 피처 A와 B는 각각 어느 정도의 DAU로 수렴할까요? 과연 피처 A와 B 중 어느 피처가 더 많은 사용자를 확보할 수 있을까요?

제품 개발 사이클에서는 새로운 먹거리 탐색을 위해 심심치 않게 크고 작은 새로운 피처를 선보이게 됩니다. 새로운 피처일수록 PO, DA 모두 숫자에 대한 감을 잡기 어렵기 때문에, 이 피처가 어느 정도 성장할 수 있을지, 무엇을 더 어떻게 하면 성장시킬 수 있을지는 굉장히 복잡한 질문입니다.
최근 알라미도 여러 새로운 기능들을 시도해 보고 있어, 이런 고민들이 예외가 아닌데요. 이렇게 초면인 피처들을 분석하는 관점에서 좀 더 쉽게 숫자에 대한 감을 잡고, 전략 방향을 뽑아낼 수 있을지 고민해 본 내용을 공유하고자 합니다.
새로운 기능에 대한 Capacity(수용 여력)를 분석하고, 지표 방향을 잡는 과정에서는 크게 아래 두 가지 질문에 답할 수 있어야 하는데요.
예를 들어, 신규 유저가 2배가 되어도 리텐션(사용자 유지율)이 너무 낮아 실제 사용자 수는 10%밖에 증가하지 않을 수 있는데요. 리텐션이 20%만 증가해도 실제 사용자 수가 50% 증가할 수 있다면 리텐션(사용자 유지율)을 올리는 방향이 더 현명한 방법이겠죠. 그리고 리텐션에 집중한다고 해도, 만약 월간 리텐션 수치가 필요하다면, 일간 리텐션에 비해 액션의 결과를 확인하는 기간이 1일에서 1달로 늘어나게 됩니다. 이는 다음 액션의 속도를 늦추게 됩니다.
몇 년 전 토스에서 ‘Carrying Capacity’라는 개념을 인용하며, 서비스의 Capacity를 가늠할 수 있는 프레임워크가 많은 관심을 받은 적이 있는데요.
CC = # of new daily(period) customers / % customers you lost each day(period) (자료 참고)
신규 유저 수와 유저의 daily churn을 활용해, 일반적인 등비급수의 합 공식을 통해 보면, 겉으로 보기에는 매우 단순하게 일별 잔존 유저들의 합으로 서비스의 전체 유저 수를 가늠해볼 수 있습니다.

하지만 실제 서비스에 도입해보려 하다 보면, 이게 맞나…? 싶은 순간이 생기는데요. 피처 A를 예로 들면, 하루에 6,700명이 유입되지만 정작 DAU는 7,000밖에 되지 않는 서비스라는 결론이 나옵니다. (스포: 실제로는 2만이 넘는데도 말이죠.)
6700 / (1–7%) = 6700 / 0.93 = 7200
Carrying Capacity 공식의 중요한 가정들은 아래와 같은데요.
실제로 80%의 리텐션을 가정하고 y = 0.8^x 그래프를 그려보면, 30일이 되는 시점에는 거의 0에 수렴하는 것을 볼 수 있는데요. 리텐션 수치가 낮아질수록 생각보다 잔존 유저가 과소평가되는 면이 있다는 점을 확인할 수 있습니다.

하지만 실제 서비스에서는 일반 방문자 또한 Active 유저에 포함하는 경우가 많고, churn rate 또한 일정하게 떨어지기보다는 일별로 달라지는 경우가 더 일반적이기 때문에 공식과 실제 유저 수 사이에 괴리가 생기게 됩니다.
일반적인 제품에서 신규 유저들은 초반 진입 이후, 일수가 증가함에 따라 초반에는 비교적 가파른 이탈률을 보이지만, 시간이 지날수록 이탈이 줄어들며, 점차 평평한 리텐션 커브가 형성되게 되는데요.
이를 보다 잘 설명해주는 리텐션 커브는 y = a * x^b 형식의 power law function입니다. 아래 이미지와 같이 단순히 0으로 수렴하는 것이 아니라, 리텐션 커브의 기울기가 점점 완만해지며 0 이상의 값으로 수렴하는 것을 확인할 수 있는데요.

즉, y = ‘x일 이후의 잔존율’로 보고, y = a * x^b에서 a(시작점)와 적절한 b(커브의 모양을 결정)를 찾아준다면 y의 누적합을 통해 전체 유저 수를 예측해 볼 수 있습니다.
오늘 전체 유저 수
= 오늘 신규 유저 + 어제 신규 유저 중 남은 유저 수 + 엊그제 신규 유저 중 남은 유저 수 + … + N일 전 신규 유저 중 남은 유저 수
= 신규 유저 수 * y(0) + 신규 유저 수 * y(1) + … + 신규 유저 수 * y(N)
= 신규 유저 수 * (y(0) + y(1) + … + y(N))
조금 복잡해 보이지만, 약간의 일반화를 거치면 각 서비스에 맞게 커스텀할 수 있으면서도, 누구나 쉽게 사용할 수 있는 공식을 만들어볼 수 있습니다.
오늘 전체 유저 수
= 신규 유저 수 * (y(0) + y(1) + … + y(N))
= 신규 유저 수 * a * (1^b + 2^b + 3^b + … + N^b)
여기서 a는 시작점이기 때문에 D1 리텐션 값을 사용할 수 있고, b의 경우 전체적인 리텐션 커브를 결정하는 계수인데요. 실제 기능의 리텐션 커브를 구하기 위해 1~2달을 기다린다면, 이런 계산을 하는 이유가 많이 사라집니다. 그래서 좀 더 보편적으로 b를 사용할 수 있도록 생각한 방법은 서비스 전체 신규 유저의 리텐션 커브를 활용하는 방법입니다.
신규 피처 또한 결국에는 신규로 들어온 유저들이 사용하게 되고, 리텐션 커브의 모양이 유저의 특성을 대변한다고 본다면, 같은 서비스 안에서는 유저들의 특성이 크게 변하지 않을 것이라는 가정입니다.
예시 코드와 같이 파이썬 scipy의 curve_fit을 사용해, 월별 Day 1 ~ Day 28 리텐션을 활용하여 b 값을 예측해본 후 평균값을 사용할 수 있습니다.
import pandas as pd
import numpy as np
from scipy.optimize import curve_fit
def func(x, a, b):
return a * (x**b)
df = client.query(query).to_dataframe()
date_list = ["'2025-07-01'", "'2025-08-01'", "'2025-09-01'", "'2025-10-01'", "'2025-11-01'", "'2025-12-01'"]
df_constant = pd.DataFrame([], columns=['basis_month', 'platform', 'a', 'b'])
avg_retention= df[df.platform == platform].avg_retention.values
popt, pcov = curve_fit(func, days, avg_retention)
마지막으로 (1^b + 2^b + 3^b + … + N^b)를 계산하기 위해 1년을 가정하고, x^b의 누적합을 구해주면
baseline = np.array([x**b_mean for x in range(1, 365)])
print(b_mean, ': ', np.sum(baseline))
간단한 하나의 식에 도달하게 됩니다. 알라미의 경우 평균 b를 대입한 값은 63 정도로 수렴했습니다.
신규 피처 DAU = 신규 유저 수 *신규 D1 리텐션 * 63

위 공식을 통해 구해본 피처 A와 B의 예측 DAU와 실제 DAU가 기존 CC 방식보다 더 가까워진 것을 확인할 수 있었는데요. 물론 이 공식 또한 여러 가정이 있기 때문에 정확한 수치를 예측할 수는 없지만, 약간의 수고를 더한다면 우리 서비스에서 출시된 기능의 DAU가 1만이 될지, 5만이 될지, 10만이 될지 쉽게 가늠해보고, 현재 수치에서 어떤 레버를 얼마만큼 올려야 원하는 DAU를 달성할 수 있을지 판단하기 쉬워질 수 있다고 생각합니다.
또한 보다 즉각적인 지표인 신규 유저 수와 D1 리텐션 수치를 활용해, 비교적 짧은 시간 안에 여러 번의 iteration을 가져갈 수도 있습니다.
실제 서비스에 이 방식을 도입해보며 덧붙인 팁 몇 가지는 다음과 같습니다.
1) 지표가 어느 정도 안정화됐을 때의 수치를 쓰는 것이 정확도를 높였음
신규 피처의 경우 초반 오픈 효과, 배포율 등으로 초반 지표가 흔들리는 경우가 많아, 안정권에 들어온 지표를 쓰는 것이 정확도를 높였습니다.
2) 런칭 후 시간이 지난 피처의 경우 기존 유저가 쌓여 신규 유저 & 리텐션만으로는 반영이 어려움
기존에 쌓인 유저를 반영할 수 있도록 기존 유저 계수를 추가해 사용했습니다.
DAU = 신규 유저 수 *신규 D1 리텐션 * 기존 계수 + 기존 유저 계수
이 방식 또한 기존 가정들이 어긋나는 상황에서는 예측치가 다시 오류를 범할 수 있겠지만, 약간의 수고를 곁들인 추상화를 통해 쉽게 제품을 진단해볼 수 있는 방식에 도달하는 과정은 매우 즐거웠습니다. 여기까지 읽어주신 분들의 또 다른 고견도 기다리겠습니다.
<원문>
새로 출시한 이 기능은 DAU 얼마짜리 기능일까? (Carrying Capacity 적용이 어려울때)
©️요즘IT의 모든 콘텐츠는 저작권법의 보호를 받는 바, 무단 전재와 복사, 배포 등을 금합니다.