메뉴 닫기

파이썬 JSON 숫자와 날짜 처리 가이드, 부동소수 오차와 Decimal 정밀도 그리고 과학적 표기 제어

파이썬 JSON 숫자와 날짜 처리 가이드, 부동소수 오차와 Decimal 정밀도 그리고 과학적 표기 제어

📌 JSON 직렬화에서 흔히 놓치는 숫자 정밀도와 날짜 포맷, 과학적 표기 강제와 방지까지 한 번에 정리합니다

프로덕션 환경에서 JSON으로 숫자와 날짜를 주고받다 보면 엉뚱한 반올림이 생기거나 0.1 더하기 0.2가 0.30000000000000004처럼 보이는 장면을 한 번쯤 마주하게 됩니다.
단위가 가격이나 환율, 계량 값이라면 작은 오차도 바로 버그가 되죠.
또 로그를 열어보면 1000000이 1e+06으로 바뀌어 읽기 어려워지는 과학적 표기 때문에 점검이 힘들 때도 있습니다.
이 글은 파이썬의 JSON 처리에서 부동소수 오차가 왜 생기는지, 정밀도 요구 시 Decimal 사용으로 어떻게 안정적으로 값을 지킬 수 있는지, 그리고 숫자의 과학적 표기를 강제하거나 방지하는 실무 팁을 친근한 예시로 정리합니다.

파이썬 표준 라이브러리의 json 모듈은 타입별 직렬화 규칙이 분명하고, 날짜는 기본적으로 문자열 포맷으로 다뤄야 한다는 점을 이해하면 많은 문제가 풀립니다.
여기에 Decimal을 활용한 금액 처리, 커스텀 인코더로 과학적 표기 제어, 파싱 시 숫자 타입을 정확히 매핑하는 방법을 더하면 백엔드와 프런트엔드 간 데이터 일관성이 높아집니다.
실제 현장에서 바로 붙여 넣어 쓸 수 있는 코드와 검증 포인트를 준비했으니, 반복되는 숫자·날짜 이슈를 근본적으로 줄이는 데 도움이 될 것입니다.



🔗 파이썬 JSON 기본 타입 매핑

파이썬에서 JSON 데이터를 다룰 때 가장 먼저 이해해야 할 부분은 타입 매핑입니다.
JSON은 단순한 데이터 포맷이기 때문에 타입 종류가 한정되어 있으며, 파이썬의 다양한 데이터 타입을 어떻게 변환할지 정해져 있습니다.
예를 들어 JSON의 객체는 파이썬의 dict로, 배열은 list로 매핑됩니다.
또한 문자열은 str, 숫자는 int나 float, 불리언은 bool, null은 None으로 매핑되는 것이 기본 규칙입니다.

하지만 날짜와 시간은 JSON에서 직접적인 타입이 없기 때문에 기본적으로 문자열로 직렬화해야 합니다.
이때 ISO 8601 같은 국제 표준 포맷을 사용하는 것이 안전하며, 파이썬에서는 datetime 객체를 직렬화할 때 이를 문자열로 변환하는 커스텀 인코더가 자주 활용됩니다.
이처럼 기본 매핑 원리를 이해하면 직렬화와 역직렬화 과정에서 불필요한 타입 오류나 데이터 손실을 막을 수 있습니다.

  • 📌JSON 객체 → dict
  • 📌JSON 배열 → list
  • 📌JSON 숫자 → int 또는 float
  • 📌JSON 문자열 → str
  • 📌JSON 불리언 → bool
  • 📌JSON null → None

숫자와 날짜가 핵심 쟁점이 되는 이유는 이 매핑이 단순히 형식 변환이 아니라, 실제 데이터의 정밀도와 가독성에 직결되기 때문입니다.
따라서 JSON 기본 매핑 규칙을 잘 이해하고 있어야 이후 다루게 될 부동소수 오차 문제와 Decimal 활용, 과학적 표기 통제까지 자연스럽게 연결할 수 있습니다.

🛠️ 부동소수 오차 이해와 재현

프로그래밍을 하다 보면 0.1 + 0.2를 계산했을 때 기대한 0.3이 아닌 0.30000000000000004가 출력되는 현상을 자주 보게 됩니다.
이것은 버그가 아니라 부동소수점 표현 방식의 한계에서 비롯된 정상적인 결과입니다.
컴퓨터는 2진법을 기반으로 숫자를 저장하기 때문에, 10진수에서 깔끔하게 표현되는 값이 이진수에서는 무한 소수가 되어 근사치로 저장될 수밖에 없습니다.

예를 들어, 0.1은 2진 부동소수 표현에서 정확히 떨어지지 않는 값이기 때문에 내부적으로 약간의 오차를 포함합니다.
이 오차가 연산 과정에서 누적되며 예상치 못한 결과가 나타납니다.
따라서 금융, 과학, 통계 등 정밀도가 중요한 영역에서는 기본 float 타입만으로는 신뢰할 수 없는 결과가 나올 수 있습니다.

CODE BLOCK
import json

# 부동소수 오차 재현
data = {"value": 0.1 + 0.2}
print(data)
print(json.dumps(data))

# 출력 결과
# {'value': 0.30000000000000004}
# {"value": 0.30000000000000004}

위 예시처럼 JSON 직렬화 과정에서도 오차가 그대로 노출됩니다.
프런트엔드와 API로 데이터를 주고받을 때 이 값이 사용자에게 직접 보이거나, 합산/비교 연산에 영향을 주면 치명적인 문제가 됩니다.
따라서 단순히 현상을 이해하는 것을 넘어, 어떻게 해결할 수 있는지까지 고민해야 합니다.

⚠️ 주의: float 오차는 특정 언어에 국한된 문제가 아니라, IEEE 754 부동소수점 표준을 따르는 모든 환경에서 공통적으로 발생합니다.



⚙️ 정밀도 요구 시 Decimal 사용법

부동소수 오차 문제를 해결하기 위해 파이썬은 decimal.Decimal 클래스를 제공합니다.
Decimal은 10진법 기반의 정밀한 연산을 보장하기 때문에 금융, 과세, 통화 단위 계산처럼 작은 차이도 허용되지 않는 경우에 필수적입니다.
특히 JSON 직렬화 과정에서도 Decimal을 적절히 활용하면 부정확한 float 출력 대신 정확한 값 그대로를 다룰 수 있습니다.

파이썬의 json.dumps()는 기본적으로 Decimal을 지원하지 않으므로, default 파라미터를 활용하거나 커스텀 인코더를 작성해 Decimal을 문자열 혹은 숫자로 변환해야 합니다.
또한 parse_float=Decimal 옵션을 사용하면 JSON 문자열을 파싱할 때 float 대신 Decimal로 변환할 수 있어 입력 단계부터 정밀도를 확보할 수 있습니다.

CODE BLOCK
from decimal import Decimal
import json

data = {"price": Decimal("0.1") + Decimal("0.2")}

# 직렬화 시 문자열 변환
json_str = json.dumps(data, default=str)
print(json_str)  
# {"price": "0.3"}

# 파싱 시 Decimal 사용
parsed = json.loads('{"price": 0.3}', parse_float=Decimal)
print(parsed)  
# {'price': Decimal('0.3')}

위 예시처럼 Decimal을 사용하면 0.1 + 0.2가 정확히 0.3으로 표현됩니다.
또 JSON 파싱에서도 float 대신 Decimal을 쓰도록 설정하면, 처음부터 끝까지 정밀도를 유지할 수 있습니다.

💡 TIP: Decimal을 문자열로 직렬화할지, 숫자로 직렬화할지는 시스템 요구 사항에 맞춰 선택하세요. 문자열 직렬화는 안전하지만, 소비 측에서 다시 변환해야 하는 불편이 있을 수 있습니다.

🔢 과학적 표기 강제와 방지 규칙

숫자가 크거나 소수점 자리가 길어질 때, JSON 직렬화 과정에서 과학적 표기법(Scientific Notation)이 자동으로 사용되는 경우가 있습니다.
예를 들어 1000000은 1e+06으로, 0.00001은 1e-05로 출력됩니다.
이 방식은 데이터의 크기를 줄이는 데는 유리하지만, 로그 확인이나 외부 시스템 연동 시 혼란을 줄 수 있습니다.

파이썬에서는 기본 json.dumps()가 float을 문자열로 변환할 때 과학적 표기를 허용하기 때문에, 이를 제어하려면 별도의 처리가 필요합니다.
가장 흔한 방법은 format()이나 Decimal.quantize()를 사용하여 원하는 자리수로 고정하거나, 커스텀 인코더를 통해 숫자를 항상 일반 표기로 강제하는 것입니다.

CODE BLOCK
import json
from decimal import Decimal

# 과학적 표기 방지: format 활용
value = 1000000
print(format(value, "f"))  # 1000000.000000

# JSON 직렬화 시 일반 표기 강제
class PlainFloatEncoder(json.JSONEncoder):
    def encode(self, obj):
        if isinstance(obj, float):
            return format(obj, "f")
        return super().encode(obj)

print(json.dumps({"num": 0.00001}, cls=PlainFloatEncoder))

# 출력: {"num": 0.000010}

반대로 과학적 표기를 강제해야 하는 경우도 있습니다.
아주 큰 수를 처리하거나 과학 데이터 포맷이 요구되는 경우, “{:e}”.format() 같은 포맷팅을 적용하면 일관된 과학적 표기로 직렬화할 수 있습니다.

💎 핵심 포인트:
숫자의 과학적 표기는 데이터의 목적에 따라 강제하거나 방지할 수 있으며, 파이썬에서는 커스텀 인코더나 Decimal을 적절히 조합해 문제를 해결할 수 있습니다.



💡 날짜와 숫자 직렬화 베스트 프랙티스

실무에서 JSON을 다룰 때 가장 많이 문제 되는 부분은 숫자 정밀도날짜 표현입니다.
이를 안정적으로 처리하기 위해서는 몇 가지 원칙을 지키는 것이 좋습니다.
숫자의 경우 float 대신 Decimal을 사용하는 것이 기본이며, 로그나 API 응답에서는 과학적 표기를 피하고 일반 숫자 표기를 유지하는 편이 가독성과 일관성을 높여 줍니다.

날짜는 JSON에 별도의 타입이 없기 때문에 항상 문자열로 저장해야 하며, 국제적으로 통용되는 ISO 8601 포맷(예: 2025-09-20T15:30:00Z)을 사용하는 것이 가장 안전합니다.
이 방식은 파이썬뿐 아니라 자바스크립트, 자바, Go 등 다양한 언어와 시스템에서 손쉽게 호환됩니다.
또한 UTC 기준 시간을 기본으로 저장하고, 클라이언트에서 타임존 변환을 처리하는 방법이 권장됩니다.

상황 추천 직렬화 방식
금액, 환율 등 정밀 계산 Decimal + 일반 숫자 표기
과학·공학 데이터 과학적 표기 강제 (format {:e})
일반 로그/통계 일반 숫자 표기 유지
날짜와 시간 ISO 8601 문자열 (UTC 기준)

이처럼 숫자와 날짜 처리 방식을 명확히 규정해 두면 팀 내 코드 품질과 서비스 데이터 신뢰도가 크게 향상됩니다.
API 문서나 데이터 스키마에 숫자·날짜 직렬화 규칙을 명시해 두는 것도 좋은 방법입니다.

💬 JSON은 단순한 포맷이지만, 숫자와 날짜 표현 규칙을 올바르게 적용해야만 데이터 정합성과 가독성을 동시에 확보할 수 있습니다.

자주 묻는 질문 FAQ

파이썬 JSON에서 날짜 타입은 어떻게 저장되나요?
JSON에는 날짜 타입이 없으므로 문자열로 직렬화해야 합니다. 가장 권장되는 방식은 ISO 8601 포맷(예: 2025-09-20T15:30:00Z)을 사용하는 것입니다.
0.1 + 0.2가 0.3이 아닌 이유는 무엇인가요?
부동소수점 표현의 한계 때문에 발생하는 정상적인 현상입니다. 컴퓨터는 10진수를 이진수로 변환할 때 일부 값을 근사치로 저장하기 때문에 오차가 누적될 수 있습니다.
Decimal을 사용하면 성능에 문제가 생기지 않나요?
Decimal은 float보다 연산 속도가 느리지만, 정밀도가 중요한 경우에는 안정성을 위해 필수적입니다. 일반적인 웹 서비스 규모에서는 성능 저하가 크게 문제되지 않습니다.
JSON 직렬화에서 과학적 표기를 막으려면 어떻게 하나요?
format() 함수나 커스텀 JSONEncoder를 사용해 숫자를 문자열로 변환하면 일반 표기 형식을 강제할 수 있습니다.
과학적 표기를 강제로 사용해야 하는 경우도 있나요?
네. 대규모 데이터나 과학·공학 계산에서는 과학적 표기가 오히려 일관성을 주기 때문에 포맷팅을 통해 강제로 적용하기도 합니다.
JSON 파싱 시 float 대신 Decimal로 읽을 수 있나요?
네. json.loads()에서 parse_float=Decimal 옵션을 주면 모든 float 값을 Decimal로 변환하여 읽을 수 있습니다.
날짜를 타임스탬프 숫자로 저장하면 안 되나요?
타임스탬프는 언어와 플랫폼에 따라 해석이 다를 수 있습니다. 가독성과 호환성을 위해 ISO 8601 문자열을 사용하는 것이 더 안전합니다.
JSON 숫자를 문자열로 저장하는 방식은 안전한가요?
문자열 저장은 정밀도를 보장하지만, 소비 측에서 다시 숫자로 변환해야 하므로 불편이 따릅니다. 데이터의 성격에 따라 적절히 선택하는 것이 좋습니다.

📌 파이썬 JSON 숫자와 날짜 직렬화 핵심 정리

파이썬에서 JSON을 다룰 때 가장 많이 겪는 문제는 숫자의 부동소수 오차와 날짜 포맷의 부재입니다.
기본적으로 float은 근사값을 저장하기 때문에 예상치 못한 결과가 나타날 수 있고, JSON은 날짜 타입이 없어서 문자열 포맷을 선택해야 합니다.
이를 해결하기 위해 Decimal을 사용하면 정밀도를 지킬 수 있으며, parse_float=Decimal 옵션으로 파싱 단계부터 안정성을 확보할 수 있습니다.
또한 숫자가 과학적 표기로 변환되는 문제는 커스텀 인코더나 포맷팅으로 제어 가능하며, 필요한 경우에는 과학적 표기를 강제하는 방식도 활용할 수 있습니다.
날짜는 ISO 8601 문자열 포맷을 기본으로 하고 UTC 기준으로 직렬화하는 것이 가장 안전합니다.
이처럼 숫자와 날짜 직렬화 규칙을 명확히 세우면 서비스 데이터의 일관성과 신뢰성을 높일 수 있습니다.


🏷️ 관련 태그 : 파이썬JSON, 부동소수점오차, Decimal사용법, 숫자정밀도, 날짜직렬화, ISO8601, 과학적표기방지, 데이터일관성, 프로그래밍팁, 파이썬데이터처리