주제 70 / 91· 소프트웨어 공학과 디지털 전달

센트 단위 정확한 비용 배분

공동 보조금, 인프라 청구서, 예산 영향 수치 같은 총액을 단순한 백분율 계산으로 여러 수령자에게 나누면, 각 부분을 합쳐도 원래 총액이 되지 않는 일이 흔히 생깁니다. 센트 단위 정확한 배분이 그 해결책입니다. 최소 통화 단위(센트)로 작동하는 정수/십진 방식으로, 아무리 나누어떨어지지 않더라도 각 부분의 합이 정확히 전체가 됨을 보장합니다. 분할한 총액을 센트 단위까지 맞춰야 하는 모든 소프트웨어 엔지니어(급여, 보조금 지급, 공유 서비스 비용 청구)는 부동소수점 백분율이 아니라 이 패턴이 필요합니다.

왜 중요한가

이는 엔터프라이즈 소프트웨어 공학에서 이름이 붙은 근본 패턴입니다. Martin Fowler의 Patterns of Enterprise Application Architecture(2002)가 Money와 Allocate를 문서화한 것은 바로 "$100를 셋으로 나누기"가 단순한 코드가 끊임없이, 그것도 조용히 틀리는 문제이기 때문입니다. 오류는 누군가 장부를 대조해서 각 부분의 합이 총액보다 1센트 모자라거나 넘친다는 것을 발견할 때에야 드러납니다. 보건경제학과 NHS 재무 업무에서 이는 학술적인 문제가 아닙니다. 예산 영향 총액은 사업장, 연도, 부서로 나뉘고, 공유 인프라와 라이선스 비용은 인원이나 활동 비중에 따라 부서에 배분됩니다. 이 모든 분할은 정확히 맞아떨어져야 합니다. 총액과 합이 맞지 않는 부분들을 받아 든 재무 책임자는 모델 전체를 신뢰하지 않게 되기 때문입니다.

수식

단순한(잘못된) 방법:
  부분_i = 반올림(총액 × 비율_i / Σ 비율)     — 각 부분을 따로 반올림

정확한 방법(최대 잉여 방식 / "largest remainder allocation"):
  1. 기본_i = 내림(총액_최소단위 × 비율_i / Σ 비율)   — 정수 최소 단위(센트)만
  2. 잉여 = 총액_최소단위 − Σ 기본_i                    — 남은 센트, 항상 수령자 수 미만
  3. 1단계의 소수 부분이 가장 큰 `잉여`명의 수령자에게, 잉여가 소진될 때까지
     최소 단위를 1씩 추가로 배분

결과: Σ 부분_i == 총액, 항상, 구조적으로.

정확한 방법은 한 부분을 따로 반올림하지 않고 배분 전체를 하나의 연산으로 반올림하며, 바로 이것이 합계 불변식을 성립시킵니다.

계산 예시

$100.00을 세 몫으로 균등 분할합니다(비율 = [1, 1, 1]).

단순한 방법: $100.00 ÷ 3 = $33.333…을 따로 가장 가까운 센트로 반올림하면 수령자마다 $33.33입니다. 합산하면 $33.33 × 3 = $99.99이며, 1센트가 사라졌고, 눈으로 봐서 알아챌 만큼 "틀린" 개별 항목은 하나도 없습니다.

정확한 방법: 세 명 모두 기본 = $33.33(내림(10,000 / 3) = 3,333센트씩, 합계 9,999 최소 단위)이고, 잉여 1센트(10,000 − 9,999)가 남습니다. 그 남은 1센트는 나눗셈에서 소수 부분이 가장 큰 수령자에게 갑니다. 구체적으로 누구인지는 동점 처리의 내부 세부 사항이며 호출자가 의존할 일이 아닙니다. 두 수령자는 $33.33, 한 수령자는 $33.34가 되고, 세 부분의 합은 정확히 $100.00입니다.

이는 총 예산 영향 수치를 사업장, 코호트, 회계연도로 나눈 뒤 공표된 총액과 대조해야 할 때마다 예산 영향 분석이 필요로 하는 바로 그 연산입니다. 그런 많은 항목을 어긋남 없이 합산하는 짝이 되는 문제는 통화 안전 비용 집계를 참고하세요.

소프트웨어 공학과의 연관성

이는 문자 그대로 엔터프라이즈 소프트웨어 아키텍처의 "Money 패턴"으로, 바로 이 버그 부류에 대한 이름이 붙은 근본 패턴이며 일회성 요령이 아닙니다. 실제 재무 대사 실패가 정확히 이 버그 부류에서 출하된 적이 있습니다. f64로 계산한 백분율 분할을 수령자별로 반올림하고 원래 총액과 대조하지 않은 경우입니다. 이는 이 저장소의 총소유비용 모듈과 직접 연결되며, 현재 이 모듈은 연도와 선택지에 걸쳐 일반 부동소수점 비용을 합산합니다. TCO나 예산 영향 총액을 단순히 합산하는 데 그치지 않고 배분해야 할 때도 같은 정확성의 규율이 적용됩니다.

함정

  • 최대 잉여 방식 대신 "백분율 후 반올림": 부동소수점 백분율로 배분하고 각 수령자를 따로 반올림하면, 반올림 오차가 누적되고 특히 수령자가 많을수록 총액으로 되돌아가는 일이 드뭅니다.
  • 통화 최소 단위 지수 무시: 모든 통화가 소수 둘째 자리라고 가정하는 것. 일본 엔은 0자리이고 일부 통화는 3자리입니다. 직접 만든 백분율 분할은 보통 2를 하드코딩하여 다른 통화에서 조용히 깨집니다. 정확한 배분 루틴은 지수를 통화 자체에서 읽습니다(ISO 4217).
  • 이미 배분된 잉여를 다시 배분하기: 멱등성 검사 없이 이전 배분에서 남은 것에 배분 루틴을 다시 실행하면, 같은 센트를 같은 수령자에게 이중으로 입금할 수 있습니다.

출처

  • Fowler M. "Patterns of Enterprise Application Architecture." Addison-Wesley, 2002 — Money와 Allocate 패턴.
  • ISO 4217 — 통화 및 자금 코드 표준으로, 각 통화의 최소 단위 지수를 정의합니다.