프론트 개발자를 위한 여정

모든 영역을 안내하는 개발자

Frontend/JavaScript

JavaScript에서 int 범위를 초과하는 값 관리하기 : BigInt

ji-frontdev 2025. 4. 3. 10:00
728x90
반응형

JavaScript에서 큰 숫자를 다뤄야 하는 경우가 종종 있습니다.

특히 팩토리얼 같은 연산을 할 때 Number 타입의 한계를 경험하게 됩니다.

이 글에서는 JavaScript에서 큰 숫자를 관리하는 방법과 BigInt의 필요성,

그리고 실무에서 BigInt가 사용되는 사례까지 살펴보겠습니다. 💡


1. JavaScript number 타입의 한계 🚧 

JavaScript의 기본 숫자 타입인 Number64비트 부동소수점(double-precision floating point) 으로 표현됩니다.

JavaScript에서 오차 없이 안전하게 표현할 수 있는 정수의 범위는 다음과 같습니다.

console.log(Number.MAX_SAFE_INTEGER); // 9007199254740991
console.log(Number.MIN_SAFE_INTEGER); // -9007199254740991

 

하지만 모든 정수를 안전하게 표현할 수 있는 것은 아닙니다.

가장 중요한 제한은 안전한 정수 범위입니다. 

즉, 9007199254740991 (약 9경) 이상의 숫자는 정확도가 보장되지 않습니다! 🚨

console.log(9007199254740991 + 1); // 9007199254740992 (정확)
console.log(9007199254740991 + 2); // 9007199254740992 (오차 발생)

위와 같이 MAX_SAFE_INTEGER를 초과하면 연산이 정확하지 않게 됩니다.

그렇다면 이를 해결할 방법은 무엇일까요? 🤔


2. BigInt의 등장 🎉

이러한 number 타입의 한계를 극복하기 위해 JavaScript ES2020에서 새롭게 도입된 타입이 바로 BigInt 입니다.

BigInt는 임의의 정밀도로 정수를 표현할 수 있는 특별한 숫자 타입입니다.

즉, number 타입처럼 표현 범위에 제한이 없어 아무리 큰 정수라도 정확하게 다룰 수 있습니다. 🎉

 

BigIntn을 붙여서 선언하거나 BigInt() 생성자를 이용해 만들 수 있습니다.

const bigNum1 = 9007199254740991n; // BigInt 리터럴
const bigNum2 = BigInt("9007199254740991"); // 문자열을 BigInt로 변환
console.log(bigNum1 + 1n); // 9007199254740992n

 

BigInt끼리는 일반적인 산술 연산(+, -, *, /, %, **)을 대부분 지원합니다.

다만, number 타입과의 혼합 연산은 명시적인 형 변환 없이는 불가능하며,

부동 소수점 연산은 BigInt에서 지원하지 않습니다.

 

🔹 BigInt의 특징:

  • Number보다 훨씬 큰 정수를 표현 가능
  • n을 붙여서 사용하는 타입 (예: 123456789n)
  • 부동소수점 연산이 아니라 정수 연산만 가능

하지만 BigIntNumber와 혼합해서 사용할 수 없습니다. ⛔

console.log(10n + 5); // TypeError: Cannot mix BigInt and other types

BigIntNumber와 함께 사용하려면 명시적으로 변환해야 합니다.

console.log(Number(10n) + 5); // 15
console.log(BigInt(5) + 10n); // 15n

 

BigInt의 동작 방식 (내부 구조) ⚙️

number 타입이 고정된 크기의 메모리 공간에 값을 저장하는 반면,

BigInt는 숫자를 문자열처럼 일련의 자릿수로 취급하여 내부적으로 관리합니다.

마치 우리가 손으로 큰 숫자를 계산할 때처럼, 필요한 만큼 메모리 공간을 늘려가며 숫자를 표현할 수 있습니다.

이러한 구조 덕분에 BigInt는 number 타입의 안전한 정수 범위를 초과하는 매우 큰 숫자도 정확하게 저장하고 연산할 수 있습니다.

하지만 이러한 유연성 때문에 BigInt의 연산 속도는 일반적인 number 타입의 연산보다 약간 느릴 수 있습니다.

특히 작은 숫자에 대한 연산에서는 고정 크기의 number 타입이 더 효율적입니다.

 


3. Number vs BigInt 비교 ⚖️

특징NumberBigInt

최대 정밀도 53비트 무제한
안전한 정수 범위 ±(2^53 - 1) 제한 없음
소수점 지원
연산 방식 부동소수점 정수 연산
속도 상대적으로 빠름 느림
사용 가능 연산 +, -, *, /, %, ** +, -, *, /, %, **

언제 Number를 사용해야 할까?

  • 대부분의 연산에서 Number는 충분히 크고 빠름
  • 소수점을 다뤄야 하는 경우 BigInt는 사용할 수 없음

언제 BigInt를 사용해야 할까?

  • 팩토리얼 같은 연산 (100! 계산 등)
  • 금융 및 암호화 관련 연산 (정확도가 중요한 경우)
  • UUID, 블록체인 해시값 등 매우 큰 숫자 관리

4. 실무에서 BigInt가 필요한 경우 💼

✅ 1. 팩토리얼 계산 (100!)

100! (100 팩토리얼)은 일반 Number로 표현할 수 없는 크기입니다.

function factorial(n) {
let result = 1n;
for (let i = 2n; i <= n; i++) {
result *= i;
}
return result;
}
console.log(factorial(100n)); // 엄청 큰 숫자 출력

✅ 2. 금융 및 암호화 연산

금융 계산에서는 1원 단위까지 정확한 연산이 필요할 때가 많습니다. BigInt를 사용하면 정밀도를 유지할 수 있습니다.

const amount1 = BigInt("100000000000000000000"); // 100경 원
const amount2 = BigInt("50000000000000000000"); // 50경 원
console.log(amount1 + amount2); // 150경 원

✅ 3. 블록체인 및 데이터베이스 ID 관리

블록체인의 블록 번호, 해시 값, 대형 ID 값은 BigInt로 관리하는 것이 유리합니다.

const transactionId = BigInt("12839128391283918239812398123");
console.log(transactionId);

5. 결론 🎯

🚀 JavaScript에서 큰 숫자를 다룰 때는 Number의 한계를 이해하고, 필요한 경우 BigInt를 적극 활용해야 합니다.

물론, 모든 경우에 BigInt가 최선은 아닙니다. 작은 정수 연산에서는 number 타입이 더 빠르고 효율적일 수 있습니다.
따라서 상황에 맞춰 적절한 숫자 타입을 선택하는 것이 중요합니다.

 

핵심 정리:

  • Number.MAX_SAFE_INTEGER를 초과하는 정수는 정확도가 깨질 수 있음
  • BigInt는 무제한 크기의 정수를 다룰 수 있지만 소수점 연산은 불가능
  • 금융, 암호화, 블록체인, 팩토리얼 같은 문제에서는 BigInt가 필수
  • NumberBigInt는 혼합해서 사용할 수 없으며 명시적 변환이 필요
728x90
반응형