logo
|
Blog
  • 회사 소개
  • Alarmy
  • DARO
  • Delighthub
딜라이트룸 채용
비즈니스

새로 출시한 이 기능은 DAU 얼마짜리 기능일까? (Carrying Capacity 적용이 어려울때)

신규 기능 A와 B의 최종 사용자수는?
DelightRoom's avatar
DelightRoom
Jan 05, 2026
새로 출시한 이 기능은 DAU 얼마짜리 기능일까? (Carrying Capacity 적용이 어려울때)
Contents
신규 기능 A와 B의 최종 사용자수는?새로운 기능은 나한테도 새로운데,,,무엇이 중요할까몇 년전 스타트업을 흔들었던 그 공식보편적인 신규 유저들의 리텐션 커브좀 더 ‘딸깍’스러운 공식최종 공식퀴즈 정답!팁 요약100% 정확할 수는 없지만,,,

신규 기능 A와 B의 최종 사용자수는?

들어가기전 짧은 퀴즈 하나!

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

새로운 기능은 나한테도 새로운데,,,

제품 개발 사이클에서는 새로운 먹거리 탐색을 위해 심심치 않게 크고 작은 새로운 피쳐가 선을 보이게 되는데요. 새로운 피쳐일수록 PO, DA 모두 숫자에 대한 감을 잡기는 어렵게 때문에 이 피쳐가 어느 정도 성장할수 있는지, 무엇을 어떻게 하면 더 성장시킬수 있는지는 굉장히 복잡한 질문입니다.

알라미도 최근 여러 새로운 기능들을 시도해보고 있어 이런 고민들이 예외가 아닌데요. 이렇게 초면인 피쳐들을 분석하는 관점에서 좀 더 쉽게 숫자에 대한 감을 잡고, 전략 방향을 뽑아낼수 있는 방법에 대해 고민해본 내용을 정리해보려합니다.

무엇이 중요할까

새로운 기능에 대한 capacity을 분석하고 지표 방향을 잡는 과정은 크게 아래 두가지 질문을 답할 수 있어야 하는데요.

  • 어떤 lever가 얼마나 전체 사용자 수를 움직일수 있는가?
  • 그 lever들이 선행지표로써 역할을 할 수 있는가? 측정이 너무 오랜 시간이 걸려 액션이 지체되지 않는가?

예를 들어, 신규유저가 2배가 되어도 리텐션이 너무 낮아 실제 사용자수는 10% 밖에 증가될 수 없는데, 리텐션이 20%만 증가해도 실제 사용자수가 50% 증가 할 수 있다면 리텐션을 올리는 방향이 더 현명한 방법이겠죠.

그리고, 리텐션에 집중한다고 해도 만약 Monthly 리텐션 수치가 필요하다면 Daily 리텐션에 비해 액션에 대한 결과를 확인하는 기간이 1일 에서 1달로 증가하며 다음 액션에 대한 속도를 늦추게 됩니다.

몇 년전 스타트업을 흔들었던 그 공식

몇 년전 토스에서 Carrying Capacity 라는 개념을 인용하며 서비스의 Capacity를 가늠할 수 있는 프레임워크가 많은 관심을 받은 적이 있는데요.

CC = # of new daily(period) customers / % customers you lost each day(period) (자료 참고)

신규 유저 수와 유저의 daily churn을 사용하여 일반적인 등비급수의 합 공식을 통해, 보기에는 굉장히 단순하게 일별 잔존 유저들의 합으로 서비스의 유저수를 가늠해볼수 있습니다.

등비급수의 합 공식 (일정한 a, 일정한 r)

하지만, 실제 서비스에 도입해보려 하다보면 이게 맞나..? 싶을때가 생기는데요.

피쳐 A를 예로 들면, 하루에 6700명이 들어오지만 정작 DAU는 7000 밖에 되지 않는 서비스라는 결론이 나옵니다. (스포: 실제로는 2만이 넘는데도 말이죠.)

6700 / (1–7%) = 6700 / 0.93 = 7200

Carrying Capacity 공식의 중요한 가정들은 아래와 같은데요

  • Active User에 대한 정의를 실제로 WoW factor 를 경험한 유저로 정의
  • 이에 따라 낮은 churn rate을 기대하며, Day N에서 Day N+1일의 리텐션이 일정할거라 가정 (매일 똑같은 r을 가정)

실제로 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'])

platforms = ['ios', 'android']

for platform in platforms:
  avg_retention= df[df.platform == platform].avg_retention.values
  basis_month = df[df.platform == platform].basis_month.values[0]

  days = np.arange(1, 29)

  popt, pcov = curve_fit(func, days, avg_retention)

  retention_days = np.arange(1, 364)
  retention_rate = np.concatenate((np.array([1.0]), func(retention_days, *popt)))
  print(*popt)
  new_row_const = pd.DataFrame([[basis_month, platform, popt[0], popt[1]]], columns=['basis_month', 'platform', 'a', 'b'])
  df_constant = pd.concat([df_constant, new_row_const], ignore_index=True)

print("Total b Mean: ", np.mean(df_constant['b']))
print("Total Android b Mean: ", np.mean(df_constant[df_constant.platform == 'ios']['b']))
print("Total iOS b Mean: ", np.mean(df_constant[df_constant.platform == 'android']['b']))

마지막으로 (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을 가져갈수도 있습니다.

팁 요약

실제 서비스에 이 방식을 도입해보며 얹은 팁 몇가지는

> 지표가 어느 정도 안정화 되었을때 수치를 쓰는것이 정확도를 올렸음

  • 신규 피쳐의 경우 초반 오픈 효과, 배포율 등 초반 지표가 흔들리는 경우가 많아 안정권에 들어온 지표를 쓰는것이 정확도를 올렸습니다

> 런칭 후 오래된 피쳐의 경우 기존 유저가 쌓여 신규 유저 & 리텐션만으로는 반영이 어려움

  • 기존에 쌓인 유저를 반영할수 있도록 기존 유저 계수를 추가하여 사용

DAU = 신규 유저 수 *신규 D1 리텐션 * 기존 계수 + 기존 유저 계수

100% 정확할 수는 없지만,,,

이 방식 또한 기존 가정들이 어긋나는 상황이라면 예측치들이 또 다시 오류를 범하겠지만, 약간의 수고를 곁들인 추상화를 통해 쉽게 제품을 진단해볼수 있는 방식에 도달하는 과정이 매우 즐거웠습니다. 여기까지 읽어주신 분들의 또 다른 고견들을 기다리겠습니다 :)

⏰ 딜라이트룸에서 알라미와 함께 아침을 바꿀 분들을 모십니다 🙌

→ 딜라이트룸 채용 공고 살펴보기 ⏰

Share article
Contents
신규 기능 A와 B의 최종 사용자수는?새로운 기능은 나한테도 새로운데,,,무엇이 중요할까몇 년전 스타트업을 흔들었던 그 공식보편적인 신규 유저들의 리텐션 커브좀 더 ‘딸깍’스러운 공식최종 공식퀴즈 정답!팁 요약100% 정확할 수는 없지만,,,

Delightroom

RSS·Powered by Inblog