컴퓨터가 돈을 세지 못하는 이유와 프론트엔드 해결법

발행: (2026년 6월 18일 PM 07:40 GMT+9)
10 분 소요
원문: Dev.to

Source: Dev.to

Il problema non è l’aritmetica: è la rappresentazione dei numeri. E nelle app con pagamenti basta un centesimo “fantasma” per creare caos.

문제는 계산 자체가 아니라 숫자 표현이다. 결제 앱에서는 단순히 ‘가상의’ 한 센트가 문제를 일으킬 수 있다.

Gestire denaro in un’applicazione sembra banale: sommi, sottrai, mostri un totale. In realtà è uno dei domini più insidiosi che esistono, perché il denaro non ammette approssimazioni: non puoi “perdere” un centesimo per strada, non puoi crearne uno dal nulla e—soprattutto—non puoi essere “quasi corretto”.

앱에서 돈을 다루는 것은 단순해 보이지만, 더하고 빼고 총을 보여주는 것만큼 간단하지 않다. 실제로는 가장 위험한 도메인 중 하나다. 왜냐하면 돈이 근사할 수 없기 때문이다: 거리로 한 센트를 ‘잃’ 수는 없고, nulla에서 만든다는 것도 불가능하며—특히—완전히 정확하지 않을 수 없다.

Eppure, per anni (e ancora oggi se non si sta attenti) sistemi di pagamento e piattaforme bancarie hanno dovuto combattere una classe di bug legata a una verità scomoda: i computer non rappresentano i numeri decimali come li pensiamo noi.

하지만 수년간(그리고 여전히 주의 깊게 보지 않는 경우) 결제 시스템과 은행 플랫폼은 컴퓨터가 우리가 생각하는 소수점 decimal을 그대로 표현하지 못한다는 불편한 진실을 마주하며 버그와 싸워야 했다.

Un errore di 0,0000001 su una singola transazione non fa notizia. Ma prova a moltiplicarlo per milioni di operazioni al giorno: improvvisamente quel “rumore” numerico diventa una deriva misurabile.

단일 거래에 0.0000001 오차가 발생해도 큰 문제가 되지 않는다. 하지만 이걸 하루 수백만 건의 운영에 적용하면, 그 ‘노이즈’가 측정 가능한 편차로 변한다.

Il problema peggiora quando:

  • una parte del sistema arrotonda per eccesso, un’altra per difetto;
  • alcuni passaggi non arrotondano affatto;
  • si combinano conversioni, split di pagamenti, riaggregazioni, rimborsi.

문제가 악화되는 경우:

  • 시스템의 일부는 과도하게 반올림하고, 다른 일부는 부족하게 반올림한다;
  • 일부 단계는 전혀 반올림하지 않는다;
  • 변환, 결제 분할, 재집계, 환불이 결합된다.

In questi casi il valore può “driftare” (derivare) tra sistemi e report: microscopiche differenze si accumulano e i saldi non tornano più perfettamente.

이런 경우 값은 시스템과 보고서 간에 ‘drift’(편차)를 일으킬 수 있다. 미세한 차이가 누적돼 saldo가 더 이상 정확히 맞지 않는다.

E c’è un risvolto ancora più delicato: se un flusso consente di ripetere certe operazioni (split/merge, conversione, reverse) introducendo ogni volta un arrotondamento leggermente diverso, quelle discrepanze possono essere amplificate. Non serve “bucare” un sistema: basta sfruttare in modo ripetitivo comportamenti numerici incoerenti.

더 민감한 점은 흐름이 split/merge, 변환, reverse 같은 특정 연산을 반복하면서 매번 약간 다른 반올림을 도입한다는 것이다. 시스템을 ‘해킹’할 필요가 없다; 단순히 불일치하는 수치 행동을 반복적으로 활용하면 된다.

Nel frontend, soprattutto in JavaScript, il problema si vede subito:

0.1  + 0.2
// 0.30000000000000004

const balance  = 0.1  + 0.2;
if (balance === 0.3) {
  console.log('ok');
} else {
  console.log('nope');
}
// nope

프론트엔드, 특히 자바스크립트에서는 문제가 바로 보인다:

Se poi fai confronti diretti, ti fai male:

const balance = 0.1 + 0.2; if (balance === 0.3) { console.log(‘ok’); } else { console.log(‘nope’); } // nope

그 후 직접 비교를 하면 문제를 맞이한다:

Non è un “bug di JavaScript”. È un effetto della rappresentazione numerica più comune: i floating point (IEEE 754).

이건 ‘JavaScript 버그’가 아니라 가장 일반적인 부동소수점( IEEE 754) 표현 때문이다.

Noi ragioniamo in base 10 (decimale). I computer, invece, memorizzano i numeri in base 2 (binario). Alcuni decimali “semplici” per noi—come 0.1 o 0.2—in binario non hanno una rappresentazione finita.

우리는 10진수(십진법)로 생각한다. 반면 컴퓨터는 2진수(이진법)로 숫자를 저장한다. 0.1이나 0.2처럼 ‘간단한’ 십진수는 이진수로 표현할 수 없다.

Quindi vengono salvati come approssimazioni. Sommi due approssimazioni e ottieni un’altra approssimazione: nella maggior parte delle UI non cambia nulla, но in ambito finanziario (grandi volumi, riconciliazioni, audit) quei residui diventano costi, contestazioni o vulnerabilità.

따라서 они 저장되는 근사값이다. 두 근사값을 더하면 또 다른 근사값이 된다. 대부분의 UI에서는 차이가 나타나지 않지만 금융 분야(대량 거래, 정산, 감사)에서는 이러한 잔여값이 비용, 이의 제기, 취약점으로 변한다.

Per questo i sistemi moderni seri non memorizzano denaro como decimali floating.

따라서 현대적인 진지한 시스템은 돈을 부동소수점(decimal)으로 저장하지 않는다.

L’approccio tipico è: salvare importi come interi nella unità minima (es. centesimi); fare tutte le operazioni (somma/sottrazione) su interi; convertire in decimale solo in fase di visualizzazione.

전형적인 접근법은:

  • 최소 단위(예: 센트)로 정수 금액을 저장한다;
  • 모든 연산(가산/감산)을 정수로 수행한다;
  • 시각화 단계에서만 소수점 형태로 변환한다.

Esempio: invece di 10.23, memorizzi 1023.

예시: 10.23 대신 1023을 저장한다.

Anche se la contabilità “vera” vive sul backend, il frontend può introdurre divergenze che poi diventano bug difficili da diagnosticare.

백엔드에 실제 회계가 있더라도 프론트엔드가 차이를 도입해 난해한 버그를 일으킬 수 있다.

Alcune pratiche pragmatiche:

Non sommare prezzi in Number se devi ottenere totali affidabili (carrello, tasse, sconti, rate).

Number 타입으로 가격을 더할 경우 신뢰할 수 있는 총계(카트, 세금, 할인, 할부)를 얻을 수 없으니 피한다.

Trasporta importi come interi (es. amountCents) nelle API e nei modelli di stato.

API와 상태 모델에서 금액을 정수(예: amountCents)로 전송한다.

Definisci una strategia di arrotondamento unica (half-up, half-even, ecc.) e applicala in un solo punto del flusso, non “a ogni passaggio”.

half-up, half-even 등 단일 반올림 전략을 정의하고 흐름의 한 지점에서만 적용한다. ‘각 단계마다’가 아니라.

Formatta per l’utente, not per il calcolo: usa Intl.NumberFormat per mostrare, non per computare.

계산이 아닌 사용자용 포맷팅: Intl.NumberFormat을 이용해 표시하고, 계산에 사용하지 않는다.

Se servono grandi numeri o regole complesse (tassi, conversioni, interessi), valuta librerie/approcci dedicati o tipi numerici appropriati (in JS moderno anche BigInt, donde applicabile), ma senza mescolare casualmente rappresentazioni diverse.

대규모 숫자나 복잡한 규칙(환율, 변환, 이자)이 필요하면 전용 라이브러리나 적절한 numeric 타입(BigInt 등)을 검토하지만, 무작정 다양한 표현을 혼합하지 않는다.

Quando lavori con prezzi e pagamenti, l’obiettivo non è “avere un numero vicino”: è avere sempre lo stesso numero tra UI, backend, sistemi esterni e riconciliazioni.

가격과 결제를 다룰 때는 ‘가까운 숫자’를 얻는 것이 목표가 아니라, UI, 백엔드, 외부 시스템 및 정산 간에 항상 동일한 숫자를 유지하는 것이 목표다.

La lezione è semplice e pratica: i floating point sono ottimi per molte cose, но il denaro non è una di quelle. Nel momento in cui rappresenti importi come interi (centesimi) e tratti l’arrotondamento como una regola di business, smetti di inseguire fantasmi come 0.30000000000000004 e costruisci un sistema molto più robusto, verificabile e difficile da sfruttare.

교훈은 간단하고 실용적이다: 부동소수점은 많은 경우에 유용하지만, 돈이 그 중 하나가 아니다. 금액을 정수(센트)로 표현하고 반올림을 비즈니스 규칙으로 다루는 순간, 0.30000000000000004 같은 fantasma를 추적할 필요가 없어지고 훨씬 견고하고 검증 가능하며ploitation이 어려운 시스템을 구축한다.

Articolo originale: https://frontendfacile.it/blog/perche-i-computer-non-sanno-contare-i-soldi-e-cosa-fare-nel-frontend

0 조회
Back to Blog

관련 글

더 보기 »

코드 리뷰가 잘못됐다

!Cover image for Code Review Gone Wronghttps://media2.dev.to/dynamic/image/width=1000,height=420,fit=cover,gravity=auto,format=auto/https%3A%2F%2Flavkesh.com%2F...