배포 기록으로 부채의 이자를 재고 갚을 때를 정한다
목표
배포·작업 기록에서 DORA 지표와 모듈별 이자(계획 밖 작업 시간)를 계산하고, 리팩터링 후보의 회수 기간·순절감·지연 비용으로 "지금 갚을까" 를 규칙대로 결정한다.
왜 중요한가
기술 부채를 갚을지 기능을 낼지는 대개 목소리로 정해진다. 이자와 원금, 미뤄지는 기능의 가치를 같은 단위로 놓으면 그 논쟁이 계산이 된다. 재지 않은 이자는 없는 것처럼 보이다가 어느 날 팀 전체의 시간을 먹는다.
재료
/opt/fixtures/founder/debt/deploys.csv—deploy_id,service,committed_at,deployed_at,failed,recovered_at,unplanned(시각은 UTC, 12주)/opt/fixtures/founder/debt/worklog.csv—week,module,planned_hours,unplanned_hours(1~12주)/opt/fixtures/founder/debt/options.json—team_hours_per_week, hourly_cost_krw, horizon_weeks, refactor{모듈: {cost_hours, interest_reduction}}, feature{name, value_per_week_krw}
정의(이름은 dora.dev 를 따른다)
- 배포 빈도 = 서비스 배포 수 ÷ 12. 변경 리드 타임 = deployed_at − committed_at(시간). 변경 실패율 = failed=1 ÷ 전체. 실패 배포 복구 시간 = failed=1 배포의 recovered_at − deployed_at(시간) 중앙값. 배포 재작업률 = unplanned=1 ÷ 전체.
- 이자 = 모듈의 unplanned_hours.
mean(12주 평균),first4(1–4주 평균),last4(9–12주 평균). - 절감 = last4 × interest_reduction. 회수 기간 = cost_hours ÷ 절감. 기간 순절감 = (절감 × horizon_weeks − cost_hours) × hourly_cost_krw. 지연 비용 = cost_hours ÷ team_hours_per_week × value_per_week_krw.
- 결정: 회수 기간이 가장 짧은 후보의 순절감 > 지연 비용이면 그 모듈 이름, 아니면
"feature_first". - 반올림: 시간·주는 소수 둘째, 비율은 넷째, 원은 정수.
단계
/root/founder/debt/dora.py에frequency(fix, service)(주당 배포 수, 실수)를 만든다.dora.py에lead_time(fix, service)→{"median_h": x, "mean_h": y}를 더한다.dora.py에change_fail_rate(fix, service)를 더한다.dora.py에recovery_median(fix, service)(시간) 를 더한다./root/founder/debt/dora.json에 서비스마다frequency_per_week, lead_time_median_h, lead_time_mean_h, change_fail_rate, recovery_median_h, rework_rate를 쓴다./root/founder/debt/interest.json에 모듈마다mean, first4, last4, rising(last4 > first4) 를 쓴다./root/founder/debt/plan.json에 리팩터링 후보마다saved_per_week, payback_weeks, net_saved_krw, delay_cost_krw를 쓴다./root/founder/debt/decision.json에decision(정의의 규칙),worst_service(변경 실패율이 가장 높은 서비스),fastest_payback(회수 기간이 가장 짧은 후보)을 쓴다.
참고
statistics.median,statistics.mean,datetime.strptime(s, "%Y-%m-%dT%H:%M:%SZ")- 흔한 실수: 리드 타임을 평균만 보기, 변경 실패율 분모를 사고 수나 일수로 잡기, 복구 시간을 평균으로 내기, 늘고 있는 이자를 12주 평균으로 판단하기, 지연 비용을 빼먹기.
배포 빈도
/root/founder/debt/dora.py 에 frequency(fix, service) 를 만든다 — 그 서비스 배포 수 ÷ 12.
deploys.csv 를 서비스로 거른 줄 수를 12주로 나눕니다.
변경 리드 타임 — 중앙값과 평균
dora.py 에 lead_time(fix, service) → {median_h, mean_h} 를 더한다.
각 배포의 (deployed_at − committed_at) 를 시간으로 바꿔 목록을 만들고 statistics 의 median·mean 을 씁니다.
변경 실패율 — 분모는 배포
dora.py 에 change_fail_rate(fix, service) 를 더한다.
배포 직후 즉시 개입이 필요했던 배포(failed=1)의 수를 그 서비스의 전체 배포 수로 나눕니다.
실패 배포 복구 시간
dora.py 에 recovery_median(fix, service) 를 더한다(실패 배포만, 시간, 중앙값).
failed=1 인 배포의 (recovered_at − deployed_at) 중앙값입니다. 실패가 없으면 None.
서비스별 DORA 한 장
/root/founder/debt/dora.json 에 서비스마다 frequency_per_week·lead_time_median_h·lead_time_mean_h·change_fail_rate·recovery_median_h·rework_rate 를 쓴다.
배포 재작업률 = unplanned=1 ÷ 전체 배포. 시간은 소수 둘째, 비율은 넷째 자리입니다.
모듈별 이자와 추세
/root/founder/debt/interest.json 에 모듈마다 mean·first4·last4·rising 을 쓴다.
week 순서로 정렬한 뒤 앞 4주와 뒤 4주의 평균을 따로 냅니다.
회수 기간·순절감·지연 비용
/root/founder/debt/plan.json 에 리팩터링 후보마다 saved_per_week·payback_weeks·net_saved_krw·delay_cost_krw 를 쓴다.
절감은 최근 이자(last4) × interest_reduction 입니다. 지연 비용은 리팩터링이 팀 시간을 쓰는 주 수 × 기능의 주간 가치.
규칙대로 결정한다
/root/founder/debt/decision.json 에 decision·worst_service·fastest_payback 을 쓴다.
회수 기간이 가장 짧은 후보만 보고, 그 순절감이 지연 비용보다 크면 그 모듈 이름, 아니면 feature_first 입니다.