자바스크립트의 `Number` 클래스

자바스크립트의 `Number` 클래스

이 글에서는 자바스크립트의 Number 클래스에 대해 설명합니다.

Number의 특징, 흔한 함정, 유용한 API, 실용적인 예시를 단계별로 꼼꼼하게 설명하겠습니다.

YouTube Video

자바스크립트의 Number 클래스

Number는 자바스크립트에서 기본 숫자형 타입이며, IEEE-754 배정밀도 부동소수점(64비트)으로 표현됩니다.

기본: 숫자 표현 및 타입 확인

자바스크립트에서는 모든 숫자가 원시 타입인 number로 표현됩니다.

 1// Primitive numbers and Number object
 2const a = 42;                 // primitive number
 3const b = 3.14;               // primitive float
 4const c = Number(10);         // primitive via constructor call (function form)
 5const d = new Number(10);     // Number object (wrapper)
 6
 7console.log(typeof a);        // "number"
 8console.log(typeof d);        // "object"
 9console.log(c == d);          // true  (value coerces)
10console.log(c === d);         // false (different types)
  • 이 코드는 원시 numberNumber 래퍼 객체의 차이를 보여줍니다. 일반적으로 래퍼 객체 대신 원시값을 사용합니다.

특수 값: NaN, Infinity 및 상수

Number는 (NaN, Infinity) 같은 특수 값과 상수를 제공합니다.

 1// Special numeric values and constants
 2console.log(Number.NaN);                 // NaN
 3console.log(Number.POSITIVE_INFINITY);   // Infinity
 4console.log(Number.NEGATIVE_INFINITY);   // -Infinity
 5
 6console.log(Number.MAX_VALUE);           // largest positive representable
 7console.log(Number.MIN_VALUE);           // smallest positive representable (closest to 0)
 8console.log(Number.MAX_SAFE_INTEGER);    // 9007199254740991
 9console.log(Number.MIN_SAFE_INTEGER);    // -9007199254740991
10console.log(Number.EPSILON);             // smallest difference ~2.220446049250313e-16
  • MAX_SAFE_INTEGER 이상인 정수는 정확히 표현되지 않을 수 있습니다. 정확성이 요구될 때는 BigInt 사용을 고려하세요. EPSILON은 부동소수점 비교에 사용됩니다.

숫자 변환: Number(), parseInt, parseFloat, + 연산자

문자열을 숫자로 변환하는 방법은 여러 가지가 있으며, 각각 동작이 다릅니다.

 1// Converting strings to numbers
 2console.log(Number("42"));        // 42
 3console.log(Number("  3.14 "));   // 3.14
 4console.log(+ "7");               // 7 (unary +)
 5
 6console.log(parseInt("42px"));    // 42
 7console.log(parseFloat("3.14abc"));// 3.14
 8
 9// Careful with parseInt and radix
10console.log(parseInt("08"));      // 8
11console.log(parseInt("08", 10));  // 8 (explicit radix is safer)
  • Number()는 전체 문자열이 엄격하게 숫자 형식이어야 값을 반환하고, 그렇지 않으면 NaN을 반환합니다. 반면, parseIntparseFloat는 문자열의 처음부터 읽을 수 있는 숫자 부분만 해석합니다. parseInt를 사용할 때 항상 진법(radix)을 명시하는 것이 더 안전합니다.

NaN 처리 및 확인: isNaNNumber.isNaN

NaN(Not-A-Number)은 특별하게도 NaN !== NaN을 만족합니다. 두 함수의 동작 방식에는 차이가 있습니다. 전역 isNaN은 타입 변환을 수행하므로 오탐(false positive)이 발생할 수 있어, Number.isNaN 사용이 권장됩니다.

1// NaN detection differences
2console.log(NaN === NaN);             // false
3
4console.log(isNaN("foo"));            // true  -> because "foo" coerces to NaN
5console.log(Number.isNaN("foo"));     // false -> "foo" is not the numeric NaN
6
7console.log(Number.isNaN(NaN));       // true
  • 불필요한 타입 변환을 피하려면 숫자 확인과 계산 결과 검증에 Number.isNaN을 사용하세요.

부동소수점 오류와 Number.EPSILON을 활용한 비교

IEEE-754로 인해 0.1 + 0.2 !== 0.3과 같은 오류가 발생합니다. 엄격한 비교를 위해서는 차이와 Number.EPSILON을 활용하는 것이 일반적입니다.

1// Floating point precision example and EPSILON comparison
2const sum = 0.1 + 0.2;
3console.log(sum === 0.3);             // false
4
5function nearlyEqual(a, b, epsilon = Number.EPSILON) {
6  return Math.abs(a - b) <= epsilon * Math.max(1, Math.abs(a), Math.abs(b));
7}
8
9console.log(nearlyEqual(sum, 0.3));   // true
  • 허용 오차가 필요한 비교에는 절대값 차이뿐만 아니라 스케일링까지 고려하는 nearlyEqual 같은 견고한 구현을 추천합니다.

정수 및 안전한 정수 확인 (isInteger, isSafeInteger)

값이 정수인지, 안전한 정수 범위 내에 있는지 확인하는 API가 있습니다.

1// Integer and safe integer checks
2console.log(Number.isInteger(3));                 // true
3console.log(Number.isInteger(3.0));               // true
4console.log(Number.isInteger(3.1));               // false
5
6console.log(Number.isSafeInteger(Number.MAX_SAFE_INTEGER)); // true
7console.log(Number.isSafeInteger(Number.MAX_SAFE_INTEGER + 1)); // false
  • 큰 정수의 정확성이 필요하다면 Number.isSafeInteger로 확인하고, 범위를 초과하는 경우 BigInt 사용을 고려하세요.

표시와 포맷팅: toFixed, toPrecision, toString

숫자 표시를 제어할 수 있는 메서드들이 있습니다. toFixed는 지정한 소수점 자리수를 가진 문자열을 반환하며, 반올림에 주의해야 합니다.

1// Formatting numbers for display
2const x = 1.23456;
3console.log(x.toFixed(2));         // "1.23"   (string)
4console.log(x.toPrecision(3));     // "1.23"   (string with total significant digits)
5console.log((255).toString(16));   // "ff"     (hexadecimal string)
  • toFixed는 문자열을 반환하므로, 계산에 사용할 때는 숫자로 다시 변환된 값을 확인하세요.

문자열 결합과 + 연산자 사용 시 주의점

+ 연산자는 숫자 덧셈과 문자열 결합 양쪽에서 사용되므로 데이터 타입에 따라 의도치 않은 결과가 발생할 수 있습니다.

1// Pitfall with + operator and type coercion
2console.log(1 + 2 + "px");    // "3px"
3console.log("px" + 1 + 2);    // "px12"
4console.log(1 + "2" - 0);     // 3  (string coerced to number for subtraction)
  • 문자열과 숫자가 혼합된 경우 암묵적 타입 변환을 피하기 위해 String(), Number(), 템플릿 리터럴 등을 명시적으로 사용하는 것이 안전합니다.

고급 활용: Number.parseInt / Number.parseFloat, valueOf

Number.parseIntNumber.parseFloat는 전역 함수의 별칭입니다. valueOfNumber 객체에서 원시값을 얻을 때 사용하지만, 실제로는 거의 사용할 일이 없습니다.

1// Number.parseInt/parseFloat aliases and valueOf example
2console.log(Number.parseInt("100", 10));   // 100
3console.log(Number.parseFloat("3.14"));    // 3.14
4
5const nObj = new Number(5);
6console.log(nObj.valueOf());               // 5
7console.log(nObj + 1);                     // 6  (object coerced to primitive)
  • Number.parseInt, Number.parseFloat 사용 시 진법(radix) 지정과 입력 문자열의 공백 제거에 주의하세요. 래퍼 객체는 일반적으로 사용을 피합니다.

참고: 소형 유틸리티 예시 - 숫자 검증 함수

자주 사용하는 확인 작업을 모은 간단한 유틸리티 함수들입니다. 이로 인해 입력 검증 등의 작업을 쉽게 처리할 수 있습니다.

 1// Small number utility functions
 2function toNumberStrict(value) {
 3  // Return a Number or throw for invalid numeric strings
 4  const n = Number(value);
 5  if (typeof value === "string" && value.trim() === "") {
 6    throw new Error("Empty string is not a valid number");
 7  }
 8  if (Number.isNaN(n)) {
 9    throw new Error(`Invalid number: ${value}`);
10  }
11  return n;
12}
13
14function almostEqual(a, b, eps = Number.EPSILON) {
15  // Robust relative comparison
16  return Math.abs(a - b) <= eps * Math.max(1, Math.abs(a), Math.abs(b));
17}
  • 입력 처리와 비교 작업에 반복적으로 사용할 수 있는 매우 유용한 함수들입니다. 오류를 던지는(throw) 구현 예시는 검증 용도로 유용합니다.

성능 및 베스트 프랙티스 요약

Number 사용 시 실용적인 주의사항은 다음과 같습니다.

  • 기본적으로 원시 타입 number를 사용하며, new Number()는 피하세요.
  • 용도에 따라 문자열을 숫자로 변환할 때는 Number()(엄격한 변환)나 parseInt/parseFloat(부분 추출) 중에 선택하세요.
  • 안전한 검사를 위해 Number.isNaNNumber.isFinite를 사용하세요.
  • 부동소수점 비교 시 Number.EPSILON 사용 또는 전용 비교 함수를 작성해서 활용하세요.
  • 정수의 정확성이 필요한 경우 Number.isSafeInteger를 이용하고, 범위를 넘을 경우 BigInt를 사용하세요.
  • toFixedtoPrecision을 표시용 반올림에 사용할 수 있지만, 반환 값이 문자열임을 유의하세요.

요약

Number는 자바스크립트에서 모든 숫자(정수, 소수, 특수값 NaNInfinity)의 기본 타입입니다. 타입 변환과 부동소수점 오류에 주의하고, Number.isNaN, Number.EPSILON 등의 메서드를 올바르게 사용하는 것이 중요합니다. 안전한 정수 범위를 초과하는 경우에는 BigInt를 사용하고, 반올림 및 표시 목적으로는 toFixedtoPrecision을 활용하세요.

위의 기사를 보면서 Visual Studio Code를 사용해 우리 유튜브 채널에서 함께 따라할 수 있습니다. 유튜브 채널도 확인해 주세요.

YouTube Video