N일차 및 롤링 리텐션
고전적인 리텐션, 롤링 리텐션, 제한형 리텐션 정의의 차이를 알아봅니다.
N일차 및 롤링 리텐션은(는) CoddyKit의 무료 SQL Interview Prep 강의입니다. 이것은 4개 중 3번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 SQL Interview Prep 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. SQL Interview Prep 강의에는 총 4개의 강의가 포함되어 있습니다.
잔존율에 여러 정의가 있는 이유
면접관이 단순히 "잔존율을 계산하세요"라고 말하는 경우는 거의 없습니다. 핵심적인 후속 질문은 어떤 잔존율인가요?입니다. 같은 데이터라도 정의에 따라 전혀 다른 수치가 나옵니다.
반드시 알아야 할 세 가지는 고전적 N일차 잔존율, 롤링(무제한) 잔존율, 제한 구간 잔존율입니다. 차이를 알고 비즈니스에서 어떤 정의를 원하는지 묻는 것 자체가 평가되는 능력입니다.
N일차(고전적) 잔존율
N일차 잔존율은 사용자가 첫 행동 후 정확히 N일째에 활동했는지를 묻습니다. 1일차, 7일차, 30일차가 모바일 앱의 대표적인 지표입니다.
핵심 단어는 정확히입니다. 어떤 사용자가 6일째와 8일째에는 활동했지만 7일째에는 활동하지 않았다면, 고전적 정의에서는 7일차 잔존 사용자가 아닙니다. 이런 정확성 때문에 집계가 엄격해지고 곡선이 들쭉날쭉해집니다.
날짜 차이 계산하기
N일차 잔존율의 핵심은 코호트 시작일과 각 활동일 사이의 일수입니다. Postgres에서는 두 날짜를 빼면 정수 형태의 일수가 바로 나옵니다.
다른 SQL 방언에서는 SQL Server의 경우 DATEDIFF(day, start, d), MySQL의 경우 DATEDIFF(d, start)를 사용합니다. 사용하는 방언을 밝히시기 바랍니다. 개념인 일수 오프셋은 동일합니다.
WITH cohort AS (
SELECT user_id, MIN(event_at::date) AS day0
FROM events GROUP BY user_id
),
act AS (
SELECT DISTINCT user_id, event_at::date AS day
FROM events
)
SELECT c.user_id, (a.day - c.day0) AS day_n
FROM cohort c
JOIN act a ON a.user_id = c.user_id;7일차 잔존율 쿼리
7일차 잔존율을 구하려면 일수 오프셋이 7인 고유 사용자 수를 코호트 규모로 나눕니다. 조건부 집계를 사용하면 분자와 분모를 한 번의 조회에서 모두 구할 수 있습니다.
= 7이라는 동일성 조건이 고전적 잔존율의 특징입니다. >= 7이 아니어야 합니다. 부등식으로 바꾸면 정의가 조용히 달라집니다.
WITH dn AS (
SELECT c.user_id, (a.day - c.day0) AS day_n
FROM cohort c JOIN act a ON a.user_id = c.user_id
)
SELECT
COUNT(DISTINCT CASE WHEN day_n = 7 THEN user_id END) AS d7_retained,
COUNT(DISTINCT user_id) AS cohort_size,
ROUND(100.0 * COUNT(DISTINCT CASE WHEN day_n = 7 THEN user_id END)
/ NULLIF(COUNT(DISTINCT user_id), 0), 1) AS d7_pct
FROM dn;롤링(무제한) 잔존율
롤링 잔존율은 N일차에 대해 조금 더 완화된 질문을 합니다. 사용자가 N일째 또는 그 이후 어느 날에라도 활동했는지를 묻습니다. 7일째, 20일째 또는 그 이후 언제든 돌아온 사용자를 7일차 잔존 사용자로 인정합니다.
이 방식은 더 매끄럽고 높은 곡선을 만들며 장기적인 사용자 유지력을 측정할 때 자주 선호됩니다. 핵심적인 변경은 최대 활동일에 = N 대신 >= N을 사용하는 것입니다.
MAX 일수로 롤링 잔존율 계산하기
롤링 잔존율을 계산하는 깔끔한 방법은 각 사용자의 마지막 활동 일수 오프셋을 MAX로 구하는 것입니다. 그런 다음 그 최댓값이 >= N이면 해당 사용자는 N일차에 롤링 잔존 사용자입니다.
MAX 이후에는 사용자 한 명당 한 행만 남으므로 집계가 간단합니다. 또한 롤링 잔존율이 단조롭다는 점도 분명해집니다. 30일차에 잔존한 사용자는 그보다 작은 모든 N에서도 잔존한 것으로 계산됩니다.
WITH last_day AS (
SELECT c.user_id, MAX(a.day - c.day0) AS max_day_n
FROM cohort c JOIN act a ON a.user_id = c.user_id
GROUP BY c.user_id
)
SELECT
COUNT(*) AS cohort_size,
COUNT(*) FILTER (WHERE max_day_n >= 7) AS rolling_d7,
ROUND(100.0 * COUNT(*) FILTER (WHERE max_day_n >= 7)
/ NULLIF(COUNT(*), 0), 1) AS rolling_d7_pct
FROM last_day;제한 구간 잔존율
중간 지점에 해당하는 것이 제한 구간 잔존율입니다. N일차 전후의 구간 안에서 한 번이라도 활동했는지를 봅니다. 예를 들어 "1주차" 지표라면 5일차부터 9일차까지를 사용할 수 있습니다. 정확한 날짜에 활동하지 않은 사용자를 허용하지만, 완전한 롤링 방식보다는 덜 부드럽습니다.
실제 사용은 간헐적으로 몰려 발생하므로 이 정의가 비즈니스 현실에 가장 가깝습니다. 쿼리에서는 일수 오프셋에 BETWEEN을 사용합니다.
SELECT
COUNT(DISTINCT CASE WHEN day_n BETWEEN 5 AND 9
THEN user_id END) AS week1_retained,
COUNT(DISTINCT user_id) AS cohort_size
FROM dn;같은 사용자에 대한 세 가지 정의
차이를 구체적인 예로 살펴보겠습니다. 한 사용자가 0일차에 시작한 뒤 9일차에만 활동했다고 하겠습니다.
- 고전적 7일차: 잔존하지 않음(정확히 7일차에 활동하지 않았음).
- 롤링 7일차: 잔존함(최대 일수 9가 >= 7임).
- 제한 구간 5–9일차 1주차: 잔존함(9일차가 구간에 포함됨).
같은 데이터에서 세 가지 답이 나옵니다. 면접에서는 이와 같은 예를 하나 설명하여 구문뿐 아니라 의미를 이해하고 있음을 보여 주시기 바랍니다.
기간 단위: 일, 주, 월
"N일차"는 N기간차로 일반화할 수 있습니다. 월별 사용이 일반적인 B2B 제품에서는 일 단위 잔존율이 잡음이 되므로 월별로 묶고 N개월차를 물어보는 편이 낫습니다. 작동 방식은 동일하고 절단 단위만 달라집니다.
제품의 자연스러운 사용 주기에 맞게 단위를 선택하고 그 이유를 말씀하시기 바랍니다. 소비자용 모바일 제품은 일 단위, 사용 주기가 느린 B2B 도구는 주 단위나 월 단위가 적합합니다.
-- weekly grain: offset in whole weeks
SELECT
c.user_id,
FLOOR((a.day - c.day0) / 7) AS week_n
FROM cohort c
JOIN act a ON a.user_id = c.user_id;생존자 편향과 성숙도 함정
세심한 고급 질문이 하나 있습니다. 생성된 지 10일밖에 되지 않은 코호트에 대해 30일차 잔존율을 보고해서는 안 됩니다. 이 사용자들은 아직 30일차에 활동할 기회를 얻지 못했으므로, 그 값은 실제로 잔존율이 낮아서가 아니라 인위적으로 0이 된 것입니다.
N일차를 보고할 때는 코호트의 경과 기간이 N 이상인 경우만 포함하여 방지합니다. CURRENT_DATE - day0 >= N으로 필터링하시기 바랍니다. 이를 잊으면 최근 코호트가 재앙적으로 나빠 보입니다.
WITH cohort AS (
SELECT user_id, MIN(event_at::date) AS day0
FROM events GROUP BY user_id
)
SELECT *
FROM cohort
WHERE (CURRENT_DATE - day0) >= 30; -- mature enough for Day-30정의 선택을 명확히 말하기
면접에서 가장 좋은 답은 쿼리가 아니라 되묻는 질문입니다. "고전적 N일차, 롤링, 제한 구간 중 어떤 잔존율을 원하시나요? 그리고 자연스러운 기간 단위는 무엇인가요?"라고 질문하시기 바랍니다.
그런 다음 절충점을 설명합니다. 고전적 방식은 엄격하며 정확한 날짜 기반 제품 기능에 적합하고, 롤링 방식은 단기 잔존율을 과대평가하지만 장기적인 사용자 유지력을 포착하며, 제한 구간 방식은 현실적인 절충안입니다. 목적에 맞게 지표를 선택한다는 점을 보여 주는 것이 이 수업의 핵심입니다.
간단한 확인
사용자의 첫 행동은 0일차이고 유일한 추가 활동은 12일차입니다. 각 정의에 따르면 이 사용자는 7일차에 잔존한 것입니까?
복습: 잔존율 정의
N일차 및 롤링 잔존율의 핵심 내용은 다음과 같습니다.
- 고전적 N일차: 정확히 N일차에 활동함(오프셋
= N) — 엄격하고 들쭉날쭉한 곡선입니다. - 롤링: N일차 또는 그 이후에 활동함(
MAX offset >= N) — 더 매끄럽고 단조로우며 사용자 유지력을 측정합니다. - 제한 구간: 특정 구간 안에서 활동함(
BETWEEN) — 현실적인 절충안입니다. - 제품의 사용 주기에 맞는 모든 기간 단위로 일차를 일반화합니다.
- 생존자 편향 함정을 피하기 위해 충분히 경과한 코호트(경과 기간 >= N)에 대해서만 N일차를 보고하고, 항상 비즈니스에서 어떤 정의를 의미하는지 질문합니다.
자주 묻는 질문
“N일차 및 롤링 리텐션” 강의는 무료인가요?
네 — “N일차 및 롤링 리텐션” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 SQL Interview Prep 강의 전체를 잠금 해제할 수 있습니다. SQL Interview Prep 강의에는 총 4개의 강의가 포함되어 있습니다.
“N일차 및 롤링 리텐션”에서 뭘 배우나요?
고전적인 리텐션, 롤링 리텐션, 제한형 리텐션 정의의 차이를 알아봅니다. 브라우저에서 직접 실행하는 실습 코드로 SQL Interview Prep을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.
SQL Interview Prep을(를) 시작하는 데 경험이 필요한가요?
사전 경험은 필요하지 않습니다. CoddyKit의 SQL Interview Prep은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 3번째 강의입니다.
“N일차 및 롤링 리텐션” 강의는 얼마나 걸리나요?
대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.
이 SQL Interview Prep 강의에서 코드를 작성하고 실행할 수 있나요?
네. 모든 SQL Interview Prep 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.
이 강의의 모든 강의
- 첫 행동으로 코호트 정의하기
- 리텐션 매트릭스 만들기
- N일차 및 롤링 리텐션
- 이탈 및 복귀 쿼리