7. 돈은 정수로 센다
사고 시나리오
섹션 제목: “사고 시나리오”9,900원에 10% 할인. 코드는 9900 × 0.9. 컴퓨터는 0.9 같은 소수를 정확히 저장하지 못해서 결과가 8909.999…가 되기도 한다. 건당 1원 미만의 오차가 수만 건 쌓이면 정산 금액이 어긋나고, 어디서 어긋났는지 찾으려면 전체 거래를 다시 계산해야 한다. 그때는 이미 데이터 마이그레이션 대공사다.
돈은 통화의 최소 단위 정수로 저장하고(원화는 원, 달러는 센트), 계산도 정수로 한다. 비율 계산은 곱을 먼저, 나눗셈을 마지막에 — 그리고 남는 소수의 처리(버림/반올림/올림)를 서비스 전체에서 하나로 통일한다.
실무 처방
섹션 제목: “실무 처방”- 스키마부터: 금액 컬럼은 INTEGER(최소 단위). float/double 컬럼 금지. 규약을 스키마 주석에 명시한다.
- 10% 할인은 × 0.9가 아니라 × 90 ÷ 100. 세율 8.8%는 × 880 ÷ 10000. 항상 정수 곱 먼저.
- 반올림 규약(버림/반올림/올림)을 한 곳에 정의하고, 금액 계산을 헬퍼 함수 하나로 모은다. 화면마다 따로 계산하면 화면끼리 1원이 다르다.
- 합계는 개별 항목을 각각 반올림한 뒤 더할지, 더한 뒤 한 번 반올림할지도 규약이다 — 세금계산서 관행과 맞춘다.
- 1원 차이를 재현하는 테스트를 하나 둔다. 규약이 깨지면 테스트가 먼저 알게.
체크리스트
섹션 제목: “체크리스트”- 금액이 최소 단위 정수(INTEGER)로 저장된다
- 비율 계산이 정수 곱 → 나눗셈 순서다 (float 곱 없음)
- 반올림 규약이 문서화돼 있고 계산이 헬퍼 한 곳에 모여 있다
- 1원 오차 재현 테스트가 있다