LogoSEO Jing
  • All Posts
  • SEO Jing
  • okayJing
  • KD Team
  • CLAB Coreteam
  • Study

Contact Me

© 2026 SEOJing. All rights reserved.

JavaScript프론트엔드자바스크립트 퀴즈북NumberIEEE 754BigInt

자바스크립트 퀴즈북 리마인드 Day 1: 숫자는 왜 가끔 믿을 수 없을까

2026년 6월 23일·13분 읽기

예상 읽기 시간: 15~20분

오늘의 문제

먼저 이런 코드를 봅니다.

js
console.log(0.1 + 0.2 === 0.3);
console.log(Number.MAX_SAFE_INTEGER + 1 === Number.MAX_SAFE_INTEGER + 2);
console.log(NaN === NaN);
console.log(Object.is(-0, 0));

처음 보면 이상합니다. 전부 숫자를 비교하는 코드인데 결과가 직관과 자주 어긋납니다.

text
false

Post Q&A

오케이징에게 물어보기

자바스크립트 퀴즈북 리마인드 Day 1: 숫자는 왜 가끔 믿을 수 없을까 전체를 기준으로 질문과 피드백을 받아요.답을 본 뒤에는 이 내용을 댓글로 달아서 서징에게도 물어볼 수 있어요. 작성자가 직접 볼 수 있어요!

0/500

포스트 목록

/study/javascript-quizbook
파일 1개, 폴더 0개
자바스크립트 퀴즈북 리마인드 Day 1: 숫자는 왜 가끔 믿을 수 없을까

같은 섹션의 대표 이미지

1 posts · latest first
JavaScript Number, safe integer, NaN, -0, BigInt를 한 장으로 정리한 다이어그램
Study26. 06. 23.

자바스크립트 퀴즈북 리마인드 Day 1: 숫자는 왜 가끔 믿을.

자바스크립트의 Number가 왜 정수처럼 보여도 부동소수점 모델 위에서 움직이는지, NaN과 -0, safe integer, BigInt를 프론트엔드 코드 리뷰 관점에서 다시 정리합니다.

26. 06. 23.SEOJing
true
false
false

오늘 목표는 “자바스크립트 숫자는 이상하다”에서 끝내는 게 아닙니다. 프론트엔드 코드를 읽을 때 다음 질문을 할 수 있게 되는 것입니다.

text
이 값은 계산용 숫자인가?
정확한 정수 식별자인가?
소수점 오차가 화면/검증/서버 요청에 영향을 주는가?
NaN, Infinity, -0 같은 예외값이 UI 상태로 흘러올 수 있는가?

이 질문을 할 수 있으면 숫자 버그를 단순 암기가 아니라 코드 리뷰의 체크포인트로 다룰 수 있습니다.


흔한 착각: 숫자는 그냥 숫자다

자바스크립트에는 number 타입 하나로 정수와 실수를 대부분 표현합니다.

js
typeof 1; // "number"
typeof 1.5; // "number"
typeof NaN; // "number"
typeof Infinity; // "number"

그래서 처음에는 이렇게 생각하기 쉽습니다.

text
1은 정수고,
1.5는 실수고,
NaN은 숫자가 아니고,
Infinity는 특별한 값이겠지.

하지만 자바스크립트의 number는 대체로 IEEE 754 double precision floating-point입니다. 즉 많은 값이 “정확한 십진수”가 아니라 이진 부동소수점으로 표현됩니다.

이 말은 두 가지를 뜻합니다.

  1. 소수 계산은 사람이 기대하는 십진수 계산과 다를 수 있다.
  2. 안전한 정수 범위를 벗어나면 정수도 정확히 구분하지 못할 수 있다.

Number 모델을 한 장으로 보기

JavaScript Number, safe integer, NaN, -0, BigInt를 한 장으로 정리한 다이어그램

이 그림에서 중요한 건 Number가 하나의 단순한 정수 상자가 아니라는 점입니다. 같은 number 안에 일반 소수, 큰 정수 근사값, NaN, Infinity, -0 같은 값이 같이 들어옵니다.

프론트엔드에서 이 차이는 생각보다 자주 튀어나옵니다.

  • 가격/비율/퍼센트 계산
  • 입력값 파싱
  • 서버에서 내려온 큰 ID
  • 차트 축 계산
  • 페이지네이션 카운트
  • 애니메이션 진행률
  • 날짜/시간 timestamp

숫자는 화면에서는 그냥 텍스트로 보이지만, 내부에서는 표현 방식의 한계를 계속 갖고 있습니다.


1. 0.1 + 0.2는 왜 0.3이 아닐까

js
0.1 + 0.2; // 0.30000000000000004
0.1 + 0.2 === 0.3; // false

자바스크립트가 덧셈을 못해서가 아닙니다. 0.1과 0.2가 이진 부동소수점으로는 정확히 떨어지지 않기 때문입니다.

십진수에서 1 / 3을 정확히 적기 어려운 것과 비슷합니다.

text
1 / 3 = 0.3333333333...

이진수에서도 어떤 십진 소수는 끝없이 반복됩니다. 0.1, 0.2가 그런 값입니다. 그래서 아주 작은 오차가 생기고, 그 오차가 === 비교에서 드러납니다.

프론트엔드에서는 보통 이런 방식으로 다룹니다.

js
const nearlyEqual = (a, b, epsilon = Number.EPSILON) =>
  Math.abs(a - b) < epsilon;

nearlyEqual(0.1 + 0.2, 0.3); // true

다만 Number.EPSILON을 무조건 쓰면 된다는 뜻은 아닙니다. 값의 규모가 커지면 허용 오차도 도메인에 맞게 잡아야 합니다.

js
const almostSamePrice = (a, b) => Math.abs(a - b) < 0.01;

금액이면 보통 소수 계산을 직접 누적하기보다 정수 단위로 바꾸는 편이 안전합니다.

js
// 나쁜 쪽에 가까움: 달러 금액을 소수로 계속 계산
const total = 19.99 + 9.99;

// 더 안전한 쪽: 센트 단위 정수로 계산 후 표시
const totalCents = 1999 + 999;
const label = `$${(totalCents / 100).toFixed(2)}`;

2. 안전한 정수 범위는 왜 필요할까

자바스크립트에는 안전하게 표현할 수 있는 정수 범위가 있습니다.

js
Number.MAX_SAFE_INTEGER; // 9007199254740991
Number.MIN_SAFE_INTEGER; // -9007199254740991

이 범위를 넘으면 정수 간격을 모두 표현하지 못합니다.

js
const max = Number.MAX_SAFE_INTEGER;

console.log(max + 1); // 9007199254740992
console.log(max + 2); // 9007199254740992
console.log(max + 1 === max + 2); // true

서버가 큰 ID를 숫자로 내려주면 위험할 수 있습니다.

json
{
  "id": 9007199254740993,
  "name": "post"
}

정확히는 API 응답이 JSON.parse를 지나 자바스크립트 값이 되는 순간 number 모델에 들어갑니다. 이때 이미 정확도가 깨질 수 있습니다. 이런 ID는 계산할 숫자가 아니라 식별자입니다. 문자열로 받는 편이 안전합니다.

json
{
  "id": "9007199254740993",
  "name": "post"
}

코드 리뷰에서는 이렇게 물어봐야 합니다.

text
이 숫자는 더하고 빼는 값인가?
아니면 정확히 보존해야 하는 식별자인가?

식별자라면 number보다 string이 더 안전한 모델일 때가 많습니다.


3. NaN은 숫자가 아니지만 number다

NaN은 “Not a Number”입니다. 이름만 보면 숫자가 아닌 것 같습니다. 그런데 타입은 number입니다.

js
typeof NaN; // "number"

NaN은 주로 숫자로 해석할 수 없는 연산에서 나옵니다.

js
Number("hello"); // NaN
parseInt("px", 10); // NaN
Math.sqrt(-1); // NaN

특이한 점은 NaN이 자기 자신과도 같지 않다는 것입니다.

js
NaN === NaN; // false

그래서 NaN 확인에는 Number.isNaN을 쓰는 편이 안전합니다.

js
Number.isNaN(NaN); // true
Number.isNaN("hello"); // false
isNaN("hello"); // true

전역 isNaN은 먼저 숫자 변환을 시도합니다. 그래서 문자열도 true가 나올 수 있습니다. 입력값 검증에서는 이 차이가 중요합니다.

js
const value = Number(input.value);

if (Number.isNaN(value)) {
  showError("숫자로 입력해주세요.");
}

4. -0은 왜 신경 써야 할까

자바스크립트에는 0과 -0이 둘 다 있습니다.

js
-0 === 0; // true
Object.is(-0, 0); // false

대부분의 UI에서는 큰 문제가 아닙니다. 하지만 계산 방향이나 비율을 다루면 가끔 드러납니다.

js
1 / 0; // Infinity
1 / -0; // -Infinity

차트, 좌표, 스크롤 방향, 제스처 속도처럼 “방향”이 의미 있는 값에서는 -0이 디버깅을 헷갈리게 만들 수 있습니다.

예를 들어 화면에는 0으로 보이는데 내부 계산은 음수 방향을 유지할 수 있습니다.

js
const velocity = -0;

Object.is(velocity, -0); // true

이런 값을 화면에 보여줄 때는 도메인에 맞게 정규화하는 것도 방법입니다.

js
const normalizeZero = (value) => (Object.is(value, -0) ? 0 : value);

다만 모든 곳에서 -0을 없애야 한다는 뜻은 아닙니다. 방향 정보가 필요하면 보존해야 합니다. 중요한 건 “그 값이 도메인에서 의미가 있는가”입니다.


5. BigInt는 큰 정수를 위한 별도 길이다

안전한 정수 범위를 넘는 계산이 필요하면 BigInt를 쓸 수 있습니다.

js
const id = 9007199254740993n;
typeof id; // "bigint"

BigInt는 정수를 정확하게 다룰 수 있지만, number와 자동으로 섞이지 않습니다.

js
1n + 1; // TypeError
1n + 1n; // 2n

이 제약은 불편하지만 오히려 장점이기도 합니다. 서로 다른 숫자 모델을 조용히 섞으면 더 위험하기 때문입니다.

프론트엔드에서는 BigInt를 무조건 쓰기보다 먼저 경계를 봐야 합니다.

상황더 나은 선택
큰 ID를 표시/전달만 한다string
큰 정수를 실제로 계산한다bigint
소수 계산이 필요하다number 또는 decimal 라이브러리
금액 계산이 필요하다최소 단위 정수 또는 전용 decimal 모델

BigInt는 JSON에서 바로 직렬화되지 않는 점도 주의해야 합니다.

js
JSON.stringify({ id: 1n }); // TypeError

API 경계에서는 문자열로 주고받는 설계가 더 단순할 때가 많습니다.


프론트엔드 코드 리뷰 체크포인트

숫자 코드를 볼 때는 문법보다 의도를 먼저 봐야 합니다.

text
1. 이 값은 계산해야 하는 숫자인가, 정확히 보존해야 하는 식별자인가?
2. 소수 계산 결과를 ===로 비교하고 있지 않은가?
3. 서버에서 내려온 큰 정수를 number로 받고 있지 않은가?
4. 입력값 파싱 결과가 NaN일 때 UI 상태가 깨지지 않는가?
5. Infinity, -Infinity, -0이 화면/차트/요청 파라미터로 흘러가지 않는가?
6. BigInt가 필요한 문제인지, 문자열 ID면 충분한 문제인지 구분했는가?

특히 AI가 만든 코드를 리뷰할 때는 number를 너무 쉽게 쓰는지 봐야 합니다. AI는 id: number, price: number, amount: number처럼 그럴듯한 타입을 자주 만듭니다. 하지만 프론트엔드에서 중요한 건 “숫자 타입이 맞나”가 아니라 “이 값의 정확도와 표현 방식이 도메인에 맞나”입니다.


오늘의 정리

  • 자바스크립트 number는 대부분 IEEE 754 double이다.
  • 소수 계산은 작은 오차를 가질 수 있다.
  • 안전한 정수 범위는 ±(2^53 - 1)이다.
  • 큰 ID는 number보다 string으로 보존하는 편이 안전할 수 있다.
  • NaN은 number 타입이지만 자기 자신과 같지 않다.
  • -0은 0처럼 보이지만 Object.is와 나눗셈에서 차이가 드러난다.
  • BigInt는 큰 정수를 정확히 다루지만 number와 자동으로 섞이지 않는다.

참고한 자료

  • 『프런트엔드 레벨을 높이는 자바스크립트 퀴즈북』 CHAPTER 01 타입
  • MDN Web Docs, Number
  • MDN Web Docs, Number.isNaN()
  • MDN Web Docs, BigInt
  • MDN Web Docs, Object.is()

퀴즈

Quiz1 / 4
Q.다음 코드의 결과로 가장 맞는 것은 무엇일까요?
js
console.log(0.1 + 0.2 === 0.3);