글

동기 부여의 수학: React Native로 구현한 눈덩이 vs. 눈사태 방식

TinyDebt를 만들며 수학적으로 최적인 코드도 사람에게는 맞지 않을 수 있다는 것을 알게 된 과정과, 두 가지 부채 상환 전략을 모두 구현한 이유를 소개합니다.

동기 부여의 수학: React Native로 구현한 눈덩이 vs. 눈사태 방식

대부분의 개발자는 금융 앱을 순수한 수학 문제로 접근합니다. 무슨 일이 있어도 이자를 최소화하라.

기술 용어로는 이것이 눈사태(Avalanche) 방식입니다. 부채를 이자율이 높은 순으로 정렬하고 여유 자금을 맨 위 항목에 배분합니다. 수학적으로는 가장 효율적인 경로입니다.

하지만 TinyDebt를 만들면서 “수학적으로 올바른” 코드가 종종 “사람의 테스트”에는 실패한다는 것을 깨달았습니다. 그래서 잔액 크기순으로 정렬하는 눈덩이(Snowball) 방식도 구현했고, 이 구현 과정에서 사용자 중심 로직에 대해 많은 것을 배웠습니다.

로직: 성공을 위한 정렬

로컬 우선 React Native 환경에서 백엔드 없이 이런 계산을 처리하려면 클라이언트 로직이 빠르고 안정적이어야 합니다. 다음은 사용자가 “수학적 효율”과 “심리적 추진력”을 전환할 수 있도록 제가 사용한 로직의 단순화 버전입니다.

type Debt = {
  id: string;
  name: string;
  balance: number;
  interestRate: number;
};

// The "Avalanche" Logic: Maximizing Interest Savings
const getAvalancheOrder = (debts: Debt[]) => {
  return [...debts].sort((a, b) => b.interestRate - a.interestRate);
};

// The "Snowball" Logic: Maximizing Psychological Wins
const getSnowballOrder = (debts: Debt[]) => {
  return [...debts].sort((a, b) => a.balance - b.balance);
};

기술적 과제: 실시간 비교

사용자에게 진짜 가치 있는 것은 목록을 보는 것이 아니라 선택의 영향을 보는 것입니다. TinyDebt에서는 사용자의 월 “추가” 납입액에 대해 두 알고리즘을 모두 실행해 서로 다른 두 개의 “부채 없는 날짜”를 보여 주는 예측 엔진을 만들어야 했습니다.

앱이 로컬 우선이고 개인정보를 중시하는 단순한 데이터 모델을 사용하기 때문에 이 계산은 즉시 이루어집니다. 서버가 상환 일정을 계산하는 동안 로딩 스피너가 돌지 않습니다. 그 결과 UI가 빠르게 반응하고 격려하는 느낌을 줍니다.

“눈덩이” 방식이 UX 대결에서 이기는 이유

눈사태 방식은 장기적으로 더 많은 돈을 절약하지만, 눈덩이 방식은 “완료율”이 더 높습니다.

프로그래밍에서는 이를 마찰 줄이기라고 부릅니다.

  • 눈사태 방식 은 크고 복잡한 레거시 모듈부터 리팩터링하는 것과 같습니다. 옳은 일이지만 지치는 일입니다.
  • 눈덩이 방식 은 월요일 아침에 “쉬운” 버그 세 개를 먼저 고치는 것과 같습니다. 화요일에 큰 일을 해치우는 데 필요한 도파민을 줍니다.

결론: 데이터베이스만이 아닌 사람을 위해 설계하라

특히 금융 분야에서 도구를 만들 때는 “인간이라는 변수”를 고려해야 합니다. 미니멀하고 프라이빗한 환경에서 두 가지 옵션을 모두 제공했더니 사용자가 훨씬 오래 참여한다는 것을 알게 되었습니다.

유틸리티 앱을 만들고 있다면 스스로 물어보세요. 내 로직은 프로세서를 위해 최적화되어 있는가, 아니면 사용하는 사람을 위해 최적화되어 있는가?