본문 바로가기
C.W.K.
Stream
Lesson 04 of 08 · published

숫자 — IEEE 754 의 경고들

~10 min · json, numbers, ieee754, precision

Level 0평문
0 XP0/64 lessons0/12 achievements
0/100 XP to next level100 XP to go0% complete

JSON 숫자 타입 하나, 그리고 그건 float

JSON 숫자는 IEEE 754 배정밀도 float 으로 떨어져. spec 에 정수 타입이 따로 없어서 55.0 은 같은 값이야. 파서 대부분이 내부적으로는 정수와 float 을 구분해 두지만, 그건 spec 이 시킨 게 아니라 구현이 알아서 해주는 거고.

문법 규칙

  • 맨 앞 0 금지007 은 안 되고 7 로 써.
  • 양수에 + 금지+5 는 안 되고 5 로 써.
  • 소수점 양쪽에 숫자 필요.55. 는 안 되고 0.5, 5.0 으로 써.
  • 지수 표기는 돼1e6, 1.5e-3, 2E10 다 유효해.
  • NaN 과 Infinity 는 안 돼null 로 바꿔 보내거나, 관행대로 표시를 단 문자열로 보내.

253 정밀도 절벽

JS 숫자는, 그리고 JSON 파서 대부분은 Number.MAX_SAFE_INTEGER (= 253 - 1 = 9,007,199,254,740,991) 를 넘어가면 정수 정밀도를 잃어. 64 비트 Twitter ID, Stripe object ID, 데이터베이스 BIGINT 가 여길 지나가면 아무 경고 없이 반올림돼. 큰 정수는 문자열 로 보내.

Twitter ID 버그: Twitter API 는 64 비트 tweet ID 를 돌려줬어. 그런데 10 년 동안 순진하게 짠 JS 클라이언트들이 253 넘는 ID 를 조용히 망가뜨리고 있었지. 결국 Twitter 문서가 id 말고 id_str 을 읽으라고 안내하기에 이르렀어. 큰 정수를 JSON 숫자로 보내는 API 는 지뢰밭이야. 문서에 따로 못 박아두지 않았으면 문자열이라고 치고 들어가.

Code

유효한 숫자·json
{
  "int": 42,
  "negative": -17,
  "zero": 0,
  "float": 3.14159,
  "scientific": 6.022e23,
  "small": 1.5e-9,
  "big_id_as_string": "1234567890123456789"
}
무효 (각 줄이 파스 에러)·text
007        ← leading zero
+5         ← explicit positive sign
.5         ← no leading digit
5.         ← no trailing digit
NaN        ← unquoted, not a value
Infinity   ← unquoted, not a value
Python 의 큰 정수 (작동, JS 는 반올림)·python
import json

# Python int 는 임의 정밀도
big = 9007199254740993  # 2**53 + 1
text = json.dumps({"id": big})
print(text)            # {"id": 9007199254740993}
back = json.loads(text)
print(back["id"] == big)  # True — 깨끗하게 라운드트립

# 같은 텍스트를 JS 엔진에 먹이면:
# JSON.parse('{"id": 9007199254740993}').id
# → 9007199254740992  (조용히 반올림)

External links

Exercise

평범한 정수, 음수 float, 지수 표기 값, 그리고 64 비트 ID 를 문자열로 담은 JSON 문서를 하나 써. 같은 데이터를 ID 만 숫자로 바꿔서 하나 더 쓰고. 둘 다 node REPL 에서 JSON.parse 로 읽고 ID 값을 비교해봐. 정밀도가 눈앞에서 죽는 걸 보게 될 거야.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.