현장

값이 정해지는 자리는 하나 — 라벨과 장부가 마감에 어긋나는 이유

작성: makemind · 2026년 8월 4일

무게를 재서 파는 가게는 언젠가 마감이 안 맞는다.

라벨 뭉치를 더한 값과 포스 합계가 몇백 원 차이가 나고, 어디서 났는지 못 찾는다. 그리고 매일 조금씩 난다.

왜 나는가

값이 두 번 계산되기 때문이다.

  • 라벨을 찍을 때 — 손님이 낼 수 있는 단위로 반올림한다. 3,444.5원짜리를 3,440원이라고 찍는다.
  • 장부에 넣을 때 — 무게에서 다시 계산한다. 3,444.5원.

둘 다 틀리지 않았다. 그런데 다르다. 그리고 그 차이는 건마다 4~5원이라 하루가 지나야 보인다.

값을 만드는 자리를 하나로

이 샘플의 답은 함수 하나다.

/// The only place a price is made.
///
/// Rounds to what somebody can pay, once. Every other number in this server
/// — the label, the ledger, the day total — comes from this and never from
/// a second pass over the weight.
static int priceFor(Product p, int grams) {
  final exact = p.wonPer100g * grams / 100;
  return (exact / _payableStep).round() * _payableStep;
}

그리고 라벨을 찍을 때 그 한 번의 결과가 장부로 그대로 들어간다.

// One call, one number. The label and the ledger row are the same
// integer, so there is nothing for them to disagree about.
final won = priceFor(_product, _grams);
_sales.add(Sale(_product.code, _product.name, _grams, won));

손님이 낸 금액이 곧 장부에 남는 금액이다. 장부가 "원래는 3,444.5원인데"라고 말할 이유가 없다 — 손님은 그걸 안 냈다.

저울 위

Pork belly 2980 won/100g — 347 g. LABEL 10340 won, exact 10340.6 · rounded -0.6 won to the nearest 10
Pork belly 2980 won/100g — 347 g. LABEL 10340 won, exact 10340.6 · rounded -0.6 won to the nearest 10

라벨에 반올림이 얼마였는지가 적혀 있다.

pan: Pork belly 347 g — exact 10340.6 won, label 10340 won (rounded -0.6 won to the nearest 10)
// What the rounding actually did, in won, said out loud. A shop
// that rounds without showing it is a shop that argues later.

이건 손님을 위한 게 아니라 가게를 위한 것이다. 반올림을 안 보이게 하면 나중에 "왜 계산이 이렇게 나오냐"는 질문에 아무도 답을 못 한다. 보이면 그 자리에서 끝난다.

다섯 건, 그리고 마감

label 1:  347 g -> 10340 won   (exact 10340.6, rounded -0.6)
label 2:  512 g -> 21250 won   (exact 21248.0, rounded +2.0)
label 3:  210 g ->  2600 won   (exact  2604.0, rounded -4.0)
label 4: 1000 g -> 29800 won   (exact 29800.0, rounded  0.0)
label 5:   83 g ->  3440 won   (exact  3444.5, rounded -4.5)

올림도 있고 내림도 있고 딱 떨어지는 것도 있다. 일부러 그렇게 골랐다 — 전부 같은 방향으로 반올림되는 데이터로 시험하면 이 종류의 버그는 안 잡힌다.

TODAY · 5 LABELS — 67430 won
TODAY · 5 LABELS — 67430 won
ledger says 5 labels, total 67430 won
harness added the labels itself: 67430 won
ledger total minus watched labels: 0 won

이 콘텐츠는 개발자 이상이 필요합니다

로그인 후 플랜을 업그레이드하면 계속 읽을 수 있습니다.

플랜 보기
Twitter