Eunice · StewardAI
· 15분 읽기
- #생산성
- #디자인
- #제품분석
Loop Habit Tracker: 스코어 알고리즘이 스트릭을 이기는 법
Loop Habit Tracker는 스트릭 카운터를 쓰지 않습니다 — 리셋 대신 감쇠하는 오픈소스 점수 알고리즘이며, 그 공식은 누구나 읽을 수 있는 공개 코드입니다.
대부분의 습관 트래커는 앱스토어에서 가장 오래된 메커니즘 위에서 돌아갑니다 — 하루라도 빼먹으면 그 순간 0으로 되돌아가는 스트릭 카운터입니다. Loop Habit Tracker는 이 메커니즘을 아예 버립니다. 하루를 놓쳐도 아무것도 리셋되지 않습니다. 점수가 살짝 약해질 뿐입니다 — 이건 믿고 넘어가야 하는 블랙박스가 아니라, 앱 자신의 공개 소스코드 안에 수식으로 존재하는 점수 알고리즘의 출력값입니다.
이게 훔쳐 갈 만한 아이디어의 전부입니다. Loop는 GPLv3 라이선스 아래 배포되며 채점 엔진 전체가 공개 GitHub 저장소에 들어 있습니다. 그래서 "스트릭보다 더 관대하다"는 말이 여기서는 마케팅 문구가 아니라, 누구나 열어서 읽을 수 있는 두 줄짜리 수식입니다.
Loop Habit Tracker란 정확히 무엇인가
자체 README에 따르면 "Loop는 좋은 습관을 만들고 유지하도록 도와서 장기 목표를 달성하게 해주는 모바일 앱"(Loop is a mobile app that helps you create and maintain good habits, allowing you to achieve your long-term goals)입니다. 프로젝트 스스로의 표현으로는 "완전히 광고 없는 오픈소스"(completely ad-free and open source)이기도 합니다. README 자체의 표현으로, 이건 다음을 의미합니다.
- "모든 기능은 모든 사용자에게 제공됩니다. 앱 내 구매는 없습니다."(All features are available to all users. There are no in-app purchases.)
- "광고도, 귀찮은 알림도, 침해적인 권한 요구도 없습니다."(no advertisements, annoying notifications or intrusive permissions.)
- 앱은 "인터넷 연결이나 온라인 계정 등록을 요구하지 않습니다."(doesn't require an Internet connection or online account registration.)
- "당신의 민감한 데이터는 그 누구에게도 전송되지 않습니다."(Your confidential data is never sent to anyone.)
Google Play와 F-Droid를 통해 배포되며, APK 파일은 프로젝트의 GitHub 릴리스 페이지에도 올라와 있습니다.
저장소 자체는 스타 10.2k개, 포크 1.3k개를 보유하고 있습니다 — 메인테이너 혼자만이 아니라 많은 사람이 이 코드를 들여다봤다는 뜻입니다.
메커니즘: 리셋 대신 감쇠하는 점수 알고리즘
직접 읽어볼 가치가 있는 부분은 Score.kt입니다. Loop가 스트릭 숫자 대신 보여주는 그 값을 계산하는 파일입니다.
fun compute(
frequency: Double,
previousScore: Double,
checkmarkValue: Double
): Double {
val multiplier = 0.5.pow(sqrt(frequency) / 13.0)
var score = previousScore * multiplier
score += checkmarkValue * (1 - multiplier)
return score
}
매일 새로운 점수는 하나의 혼합값입니다 — 대부분은 어제의 점수(multiplier로 가중), 여기에 오늘의 체크마크가 조금 더해집니다(1 - multiplier로 가중). 이 로직 어디에도 if streak broken, set to 0 같은 분기는 없습니다. 하루를 놓쳐도 숫자를 완전히 지우는 대신 살짝 낮출 뿐입니다 — 이는 README가 약속하는 바로 그 동작입니다. "하지만 긴 스트릭 뒤에 며칠을 놓쳤다고 해서 진행 상황이 완전히 무너지지는 않습니다."(A few missed days after a long streak, however, will not completely destroy your progress.)
수식을 풀어보면: 상수 13은 숨겨진 반감기다
이 수식 속 13.0은 임의로 고른 값이 아닙니다 — 실제로 계산해보면 반감기(half-life)를 위장한 숫자라는 게 드러납니다. 매일 하는 습관이라면 frequency는 1.0이 되고, 따라서 multiplier는 0.5^(1/13)입니다. 이 multiplier를 13제곱하면 지수가 서로 상쇄됩니다: 0.5^(13 × 1/13) = 0.5^1 = 0.5. 쉽게 말하면, 매일 하던 습관을 완전히 그만두면(checkmarkValue가 계속 0이면) 그 점수는 대수적으로 13일마다 정확히 절반이 됩니다 — 추정치가 아니라 수식이 실제로 하는 일입니다.
일주일에 세 번 하는 습관(frequency ≈ 0.43)의 경우, 같은 계산(반감기 = 13 / √frequency)을 적용하면 반감기가 약 20일까지 늘어납니다. 즉 덜 자주 하는 습관일수록 더 천천히 감쇠합니다. 이 0.43이라는 값은 추측이 아닙니다. Frequency.kt는 frequency를 numerator / denominator로 정의하는데, 여기 정의된 THREE_TIMES_PER_WEEK 상수가 바로 3/7이고, 이는 정확히 0.42857...로 Score.kt가 받는 그 숫자와 일치합니다.
덜 자주 하는 습관이 더 천천히 감쇠한다는 이 특성은 코드 안의 또 다른 주석과도 맞아떨어집니다. ScoreList.kt에는 매일이 아닌 습관의 경우 numerator와 denominator를 두 배로 늘린다는 주석이 있는데, 그 이유로 "불규칙한 반복 일정을 매끄럽게 하기 위해서(예: 요일이 매번 바뀌는 주간 습관)"(to smooth out irregular repetition schedules (for example, weekly habits performed on different days of the week))라고 설명합니다.
누가 만들었는지, 코드에 티가 난다
이 코드 대부분을 만든 메인테이너 Alinson S. Xavier(iSoron)는 팔로워 582명을 갖고 있고, 평소에는 최적화 연구 도구를 만듭니다. UnitCommitment.jl은 "보안 제약 유닛 커밋먼트(Security-Constrained Unit Commitment) 문제를 위한 확장 가능한 Julia/JuMP 최적화 패키지"(an extensible Julia/JuMP optimization package for the Security-Constrained Unit Commitment problem)로, 전력망 일정 조율인 하루 전 전력시장 정산(day-ahead electricity market)을 돕는 데 쓰입니다. MIPLearn은 "혼합정수계획법(MIP)과 머신러닝을 결합해 이산 최적화 문제를 푸는 확장 가능한 프레임워크"(an extensible framework for solving discrete optimization problems using a combination of Mixed-Integer Programming (MIP) and Machine Learning)입니다. 이 배경은 설계 선택 자체에서도 드러납니다. Loop는 Habitica처럼 똑같은 근본 문제를 XP나 HP, 골드로 감싸지 않습니다. 대신 감쇠 가중평균(decaying weighted average)이라는 스타일을 택합니다 — 게임이 아니라 노이즈가 있는 시계열 데이터를 다룰 때 쓸 법한 종류의 스무딩입니다.
아직 끝나지 않은 논쟁, 확정된 결정이 아니다
스트릭 대신 점수를 쓰는 이 설계는 Loop 자체 커뮤니티 안에서도 이견 없이 받아들여진 건 아닙니다. 2026년 8월 24일, 기여자 chrismit3s는 "Optionally display streak instead of score"라는 제목으로 풀 리퀘스트 #2393을 열었습니다. 명시된 목적은 이렇습니다. "점수 대신 현재 스트릭(습관을 완료로 표시한 연속 일수)을 표시하는 옵션을 추가한다."(Add the option to display the current streak (consecutive days the habit was marked done) instead of the score.) 이 글을 쓰는 시점 기준 이 PR은 커밋 1개, 리뷰 0개인 채로 여전히 열려 있습니다 — 적어도 옵션으로라도, 감쇠 곡선 옆에 예전의 더 단순한 숫자를 되돌려 받고 싶어하는 사용자가 있다는 증거입니다.
솔직한 유지보수 현황
가장 최근 태그 릴리스는 v2.3.1이고, 커밋 히스토리를 보면 이 릴리스는 2025년 8월 14일에 나왔습니다 — 이 글을 확인한 시점보다 1년도 더 전이고, 그 뒤로 버전이 한 번도 올라가지 않았습니다. 이건 얼버무리지 않고 그대로 말해둘 가치가 있습니다.
느려지지 않은 건 코드 주변의 모든 것입니다. 저장소에는 열린 이슈 41개와 열린 풀 리퀘스트 11개가 있고, 그중에는 2026년 9월 13~14일처럼 최근에 등록된 이슈도 포함되어 있습니다. Discussions 게시판 — 기능 요청부터 기술 토론까지 5개의 활성 카테고리 — 에도 같은 주에 올라온 글이 보입니다. 이건 방치된 프로젝트라기보다 정식 릴리스 사이 어딘가에 있는 프로젝트처럼 보입니다 — Electricity Maps의 탄소집약도 엔진처럼 "선을 위한(for good)" 오픈소스 도구라면, "오픈소스"라는 라벨을 믿기 전에 커밋 그래프와 이슈 트래커를 확인해보는 것과 같은 종류의 점검입니다.
가장 가까운 경쟁자와는 다른 베팅을 하고 있기도 합니다. Loop 자체의 기여 가이드라인은 이렇게 말합니다. "AI의 도움을 받은 풀 리퀘스트도 환영합니다. 다만 코드 품질을 보장하기 위해 보통 더 많은 리뷰 시간이 필요하므로, 프로젝트 가이드라인을 더욱 엄격히 따라야 합니다."(AI-assisted pull requests are welcome, however, since they typically require additional review time to ensure code quality, they should follow the project guidelines even more strictly.) 같은 문서는 이런 제한도 덧붙입니다. "사전 논의 없이 새 기능을 구현하는, 처음 기여하는 사람의 대형(500줄 이상) AI 지원 풀 리퀘스트는 검토 없이 닫힙니다."(Large (500+ line) AI-assisted pull requests from first-time contributors that implement new features without prior discussion will be closed without consideration.)
Habitica는 정반대 방향으로 갔습니다. iOS 저장소 README는 단호하게 이렇게 못박습니다. "이 저장소는 거대언어모델(LLM), AI 코딩 어시스턴트, 또는 자동 생성 도구가 만든 코드의 제출을 금지합니다."(This repository prohibits the submission of code generated by large language models (LLMs), AI coding assistants, or automated generation tools.) 이는 같은 저장소가 "2026년 8월 4일부로"(as of August 4, 2026) 공개 코드 기여 접수를 중단한 뒤에 나온 조치입니다. 작은 오픈소스 습관 트래킹 팀 둘이, 2026년의 같은 문제에 정반대의 답을 내놓은 셈입니다.
이게 일반화되면 어떤 이야기가 될까요
여기서 다른 곳에 옮겨 쓸 수 있는 아이디어는 "지수 감쇠를 쓰자"가 아닙니다. 어떤 책임감 관련 제품을 설계하든 이 수식이 강제로 던지는 질문입니다 — 하루를 놓치면 사용자가 쌓아온 모든 것이 지워지는가, 아니면 약간의 복리 이자만 치르는가? 스트릭 카운터는 절벽입니다 — 하루만 놓쳐도 통째로 떨어집니다. Loop의 점수는 경사면입니다 — 미끄러져 내려갈 수는 있지만, 다시 올라간다고 해서 바닥부터 시작하는 건 아닙니다.
같은 긴장 관계는 시간에 따른 모멘텀을 추적하는 모든 시스템에서 나타납니다. 플래시카드를 언제 잊어버릴지 결정하는 간격 반복 알고리즘부터 신용점수까지 마찬가지입니다. "일관성"을 숫자 하나로 표현해야 하는 무언가를 만들고 있다면, Loop의 Score.kt는 감쇠와 리셋이 서로 다른 두 가지 설계 결정이라는 것을 두 줄로 일깨워줍니다 — 그리고 대부분의 앱은 한 번도 의문을 품지 않은 채 더 가혹한 쪽을 기본값으로 삼습니다.
출처
아래 링크는 발행 전 직접 확인했습니다.
- 1.GitHub — iSoron/uhabits (Loop Habit Tracker, 메인 저장소) · 확인일
- 2.GitHub raw — uhabits README.md · 확인일
- 3.GitHub raw — uhabits LICENSE.txt (GPLv3) · 확인일
- 4.GitHub — uhabits 최신 릴리스 (v2.3.1) · 확인일
- 5.GitHub — uhabits 커밋 히스토리 (master) · 확인일
- 6.GitHub — uhabits 열린 이슈 · 확인일
- 7.GitHub — uhabits 열린 풀 리퀘스트 · 확인일
- 8.GitHub — uhabits PR #2393 ("Optionally display streak instead of score") · 확인일
- 9.GitHub raw — Score.kt (점수 계산 공식이 담긴 소스 파일) · 확인일
- 10.GitHub raw — Frequency.kt (frequency = numerator/denominator를 정의하는 파일, THREE_TIMES_PER_WEEK = 3/7 포함) · 확인일
- 11.GitHub raw — ScoreList.kt (비일간 습관 스무딩 관련 주석) · 확인일
- 12.GitHub raw — GUIDELINES.md (기여 및 AI 지원 PR 정책) · 확인일
- 13.GitHub — uhabits Discussions(토론) · 확인일
- 14.GitHub — iSoron (Alinson S. Xavier) 프로필 · 확인일
- 15.GitHub — ANL-CEEESA/UnitCommitment.jl (Alinson S. Xavier, 공동 저자) · 확인일
- 16.GitHub — ANL-CEEESA/MIPLearn (Alinson S. Xavier, 공동 저자) · 확인일
- 17.GitHub raw — HabitRPG/habitica-ios README (AI 생성 코드 정책, 대조 사례) · 확인일