BigInt가 필요한 이유는?

IEEE 754 부동소수점 표준의 한계로 인한 정수 표현 범위 문제를 이해하고, 이를 해결하기 위해 BigInt 타입이 도입된 이유를 학습합니다

중급 15분 BigInt IEEE 754 부동소수점 정수 표현

JavaScript의 기본 숫자 타입인 Number는 IEEE 754 배정도 부동소수점 표준을 따르기 때문에, 안전하게 표현할 수 있는 정수의 범위에 명확한 한계가 존재합니다. 이 한계를 넘어서는 순간 숫자는 조용히 정밀도를 잃어버리며, 두 개의 서로 다른 큰 정수가 동일한 값으로 취급되는 등 예측하기 어려운 버그가 발생합니다. BigInt는 바로 이 문제를 해결하기 위해 ES2020에서 공식 도입된 새로운 원시 타입으로, 이론적으로 메모리가 허용하는 한 얼마든지 큰 정수를 정확하게 표현할 수 있습니다. BigInt가 왜 필요한지를 이해하는 것은 단순히 새로운 문법을 배우는 것이 아니라, JavaScript 숫자 시스템의 근본적인 구조와 그 한계를 파악하는 과정입니다.

🔍 핵심 문제점

  • JavaScript Number 타입은 정수와 실수를 모두 하나의 64비트 부동소수점 형식으로 저장하기 때문에, 안전하게 표현 가능한 정수 범위(Number.MAX_SAFE_INTEGER)가 약 9천조(9,007,199,254,740,991)로 제한됩니다
  • 이 범위를 초과하는 정수 연산에서는 계산 결과가 틀려도 JavaScript 엔진이 오류를 발생시키지 않고 조용히 잘못된 값을 반환합니다
  • 금융 거래 금액, 암호화폐 단위, 데이터베이스의 64비트 정수 ID, 고정밀 타임스탬프 등 실무에서 큰 정수가 필요한 상황은 생각보다 훨씬 자주 등장합니다
  • BigInt는 기존 Number와 별개의 독립된 타입으로 존재하며, 혼합 연산 시 명시적인 타입 변환을 요구함으로써 개발자가 의도하지 않은 정밀도 손실을 미연에 방지합니다
  • Number로 처리하던 큰 정수 값을 BigInt로 전환할 때는 관련 라이브러리나 외부 API와의 호환성도 함께 고려해야 합니다

💡 실무에서의 영향

프론트엔드 개발에서 BigInt의 필요성은 특히 백엔드 또는 외부 시스템과 데이터를 주고받을 때 두드러집니다. 예를 들어 일부 데이터베이스나 서버는 64비트 정수 형식의 고유 ID를 반환하는데, 이 값을 JavaScript의 Number로 파싱하면 하위 비트가 손실되어 전혀 다른 ID를 가리키는 치명적인 오류로 이어질 수 있습니다. 블록체인이나 암호화폐 관련 애플리케이션에서는 wei 단위처럼 매우 정밀한 대규모 정수 연산이 필수적이며, 이 경우 BigInt 없이는 정확한 계산 자체가 불가능합니다. 또한 고해상도 타이머나 Unix 타임스탬프를 마이크로초 단위까지 다루는 상황에서도 Number의 정밀도 한계로 인해 미묘한 시간 오차가 발생할 수 있습니다. BigInt를 적절히 이해하고 사용하면 이러한 종류의 잠재적 데이터 손실 버그를 원천 차단할 수 있으며, 결과적으로 코드의 신뢰성과 유지보수성을 크게 높일 수 있습니다.


핵심 개념

IEEE 754와 Number 타입의 구조

입문

JavaScript에서 모든 숫자는 딱 하나의 방식으로 저장돼요. 그 방식이 바로 ‘IEEE 754’인데, 이 방식이 왜 정수를 다루는 데 한계가 있는지 알아볼게요!

📏 숫자를 저장하는 64칸짜리 격자 컴퓨터는 숫자를 0과 1로 이루어진 64개의 칸에 저장해요. 마치 64칸짜리 달력처럼요. 이 64칸을 모두 활용해서 정수도 저장하고, 소수도 저장해요.

🍕 64칸을 나눠 쓰는 방식 64칸 중에서 1칸은 ‘양수인지 음수인지’ 표시에 쓰고, 11칸은 ‘소수점이 어디에 있는지’ 위치 표시에 쓰고, 나머지 52칸만 실제 숫자 값을 저장해요. 마치 피자를 한 조각은 치즈용, 한 조각은 소스용으로 쓰고 나머지만 먹는 것처럼요.

🔢 정수와 소수를 함께 처리하는 대가 정수만 저장하는 전용 타입이 아니라서, 큰 정수를 저장하려 하면 52칸으로 표현할 수 없는 숫자들은 ‘반올림’이 됩니다. 예를 들어 학교 출석부에 학생이 딱 52명까지만 적을 수 있다면, 53번째 학생은 다른 학생으로 잘못 기록될 수 있는 것처럼요.

💡 왜 이 방식을 쓰나요? 이 방식을 쓰면 소수점 아래 아주 작은 숫자부터 엄청 큰 숫자까지 하나의 규칙으로 다룰 수 있어요. 대부분의 경우에는 충분하지만, 아주 큰 정수를 다룰 때만 문제가 생겨요.

중급

JavaScript의 Number 타입은 IEEE 754 배정도(double-precision) 부동소수점 형식을 사용합니다. 64비트 중 1비트는 부호(sign), 11비트는 지수부(exponent), 52비트는 가수부(mantissa)로 구성됩니다. 이 구조 덕분에 하나의 타입으로 정수와 실수를 모두 표현할 수 있지만, 가수부 52비트라는 물리적 제약이 정수 정밀도의 상한선을 결정합니다.

가수부 52비트에 암묵적으로 포함되는 선행 1비트(implicit leading bit)까지 합치면 총 53비트로 정수를 표현할 수 있습니다. 이는 2^53 - 1 = 9,007,199,254,740,991이 안전하게 표현 가능한 최대 정수임을 의미합니다.

// 가수부 53비트의 한계 확인
console.log(Number.MAX_SAFE_INTEGER); // 9007199254740991 (2^53 - 1)
console.log(Number.MIN_SAFE_INTEGER); // -9007199254740991

// 64비트 부동소수점 구조 시각화
// [1비트: 부호] [11비트: 지수부] [52비트: 가수부]
// 정수와 실수를 모두 같은 형식으로 저장
console.log(Number.MAX_SAFE_INTEGER === Math.pow(2, 53) - 1); // true

정수 전용 타입이 없는 이유 초기 JavaScript 설계 당시 단순성을 위해 숫자 타입을 하나로 통일했습니다. 이 선택은 대부분의 웹 애플리케이션에서는 문제가 없었지만, 현대의 분산 시스템, 암호화폐, 대규모 ID 시스템 등이 보편화되면서 한계가 드러나게 되었습니다.

심화

JavaScript Number 타입은 IEEE 754-2008 표준의 binary64(배정도 부동소수점) 형식을 따르며, 이 구조는 정수 표현 정밀도에 근본적인 제약을 가집니다.

IEEE 754 binary64 메모리 레이아웃 64비트 표현은 다음과 같이 분할됩니다: 부호 비트(s) 1비트, 지수 비트(e) 11비트(바이어스 1023), 가수 비트(f) 52비트. 값은 (-1)^s × 2^(e-1023) × (1.f) 공식으로 계산됩니다. 정규화된 수(normalized number)에서는 선행 비트가 항상 1이므로 암묵적으로 포함됩니다(implicit leading bit). 따라서 유효 자릿수는 53비트(약 15-17자리 십진수)입니다.

ECMAScript 명세와 정수 정밀도 ECMAScript 2023 명세 6.1.6.1절(The Number Type)에 따르면, Number 타입은 IEEE 754-2008 double precision 형식의 모든 값을 포함합니다. Number.MAX_SAFE_INTEGER는 명세 21.1.2.6절에서 2^53 - 1로 정의되며, 이 범위 내에서만 정수 동일성이 보장됩니다.

V8 엔진의 숫자 내부 표현 V8은 정수 연산 최적화를 위해 SMI(Small Integer)와 HeapNumber 두 가지 내부 표현을 사용합니다. SMI는 31비트(32비트 시스템) 또는 32비트(64비트 시스템) 범위의 정수를 포인터 태깅(pointer tagging) 기법으로 힙 할당 없이 처리합니다. SMI 범위를 초과하는 값은 HeapNumber로 박싱(boxing)되어 IEEE 754 double 형식으로 힙에 저장됩니다. 이 구조에서 대형 정수의 정밀도 손실은 HeapNumber 표현의 물리적 한계에서 기인합니다.

안전 정수 범위와 정밀도 손실

입문

JavaScript에서 숫자가 너무 커지면 아무 경고도 없이 살짝 틀린 값이 돼요. 이걸 ‘정밀도 손실’이라고 하는데, 왜 위험한지 알아볼게요!

🧮 안전한 숫자 범위가 있어요 약 9천조(9,007,199,254,740,991)까지의 정수는 JavaScript가 완벽하게 기억할 수 있어요. 마치 책에 9천조 번까지는 정확히 페이지 번호를 적을 수 있는 것처럼요. 이 범위를 ‘안전 정수 범위’라고 불러요.

🤔 그 범위를 넘으면 어떻게 되나요? 9천조를 넘어서면 JavaScript가 숫자를 조금씩 반올림하기 시작해요. 예를 들어 9천조에 1을 더해도 결과가 9천조와 똑같아 보이는 일이 생겨요. 마치 아주 긴 척도기에서 1mm가 너무 작아서 눈으로 구별이 안 되는 것처럼요.

🚨 왜 이게 특히 위험한가요? 가장 무서운 점은 JavaScript가 틀린 계산을 해도 오류 메시지를 전혀 보여주지 않는다는 거예요. 조용히 잘못된 답을 내놓기 때문에 버그를 찾기가 매우 어렵습니다. 마치 계산기가 틀린 답을 보여주는데도 ‘계산 성공’이라고 표시하는 것과 같아요.

💸 실제로 어떤 피해가 생길까요? 만약 은행 시스템에서 아주 큰 금액을 다루거나, 온라인 게임에서 엄청나게 높은 점수를 기록하거나, 데이터베이스의 아이디 번호가 매우 클 때 이 문제가 생길 수 있어요. 두 개의 서로 다른 계좌 번호가 JavaScript에서 같은 값으로 읽힌다면 매우 심각한 문제가 됩니다.

중급

Number.MAX_SAFE_INTEGER(2^53 - 1)를 초과하는 정수는 IEEE 754 부동소수점으로 정확히 표현할 수 없습니다. 이 범위를 넘는 연산에서는 엔진이 가장 가까운 표현 가능한 값으로 반올림(round-to-nearest-even)하며, 에러 없이 잘못된 결과를 반환합니다.

const max = Number.MAX_SAFE_INTEGER; // 9007199254740991

// 범위 내: 정확
console.log(max);     // 9007199254740991
console.log(max - 1); // 9007199254740990

// 범위 초과: 정밀도 손실 발생
console.log(max + 1); // 9007199254740992 (정확)
console.log(max + 2); // 9007199254740992 (틀림! max+1과 동일)
console.log(max + 3); // 9007199254740994 (틀림!)

// 서로 다른 값이 같다고 판정되는 문제
console.log(max + 1 === max + 2); // true (심각한 버그!)
// 백엔드에서 받은 64비트 정수 ID (JSON 파싱)
const response = JSON.parse('{"userId": 9007199254740993}');
console.log(response.userId); // 9007199254740992 (잘못된 ID!)

// userId가 실제 사용자와 달라져 잘못된 데이터를 조회할 수 있음
// Number.isSafeInteger()으로 안전 여부 확인 가능
console.log(Number.isSafeInteger(9007199254740993)); // false

심화

안전 정수 범위 초과 시의 정밀도 손실은 IEEE 754의 round-to-nearest-even(RNE) 반올림 모드에 의해 결정적으로 발생합니다.

정밀도 손실의 수학적 메커니즘 2^53보다 큰 정수 n을 표현하려면 지수부 e가 53 이상이어야 하므로, 표현 가능한 연속 정수 간격이 2^(e-52)로 늘어납니다. 예를 들어 2^53 ~ 2^54 범위에서 연속 표현 가능한 정수의 간격은 2이고, 2^54 ~ 2^55 범위에서는 4입니다. IEEE 754 RNE 규칙에 따라 중간값은 가수부 최하위 비트가 0인 쪽으로 반올림됩니다.

ECMAScript 정수 안전성 명세 ECMAScript 2023 명세 21.1.2.6절과 21.1.2.8절은 Number.MAX_SAFE_INTEGERNumber.MIN_SAFE_INTEGER를 각각 2^53 - 1, -(2^53 - 1)로 정의합니다. 6.1.6.1.3절(Number::sameValueZero)과 7.2.13절(IsIntegralNumber)에 따르면, 정수 동일성 비교는 안전 범위 내에서만 신뢰할 수 있습니다. Number.isSafeInteger(n)은 n이 Number이고 Math.abs(n) <= 2^53 - 1이며 Math.floor(n) === n인 경우에만 true를 반환합니다(21.1.2.5절).

V8의 최적화와 정밀도 손실 경계 V8 Turbofan 컴파일러는 정수 범위 분석(integer range analysis, RangeType)을 통해 SMI 범위 내 연산을 unboxed 64비트 정수 연산(Int64)으로 최적화합니다. 그러나 이 최적화는 런타임에 HeapNumber로 승격(deoptimization)될 수 있으며, 이때 IEEE 754 반올림이 적용됩니다. 결국 JavaScript 엔진의 내부 최적화 여부와 무관하게, 숫자가 IEEE 754 double로 노출되는 순간 안전 정수 범위를 초과한 값의 정밀도는 보장되지 않습니다.

BigInt 타입의 도입과 동작 원리

입문

BigInt는 아무리 큰 정수도 정확하게 저장할 수 있는 JavaScript의 새로운 숫자 타입이에요. 어떻게 이게 가능한지 알아볼게요!

🏗️ 기존 방식의 한계를 어떻게 해결했나요? 일반 숫자(Number)는 딱 64칸 안에 숫자를 욱여 넣었지만, BigInt는 숫자가 클수록 자동으로 더 많은 칸을 빌려 써요. 마치 일반 공책(100페이지)이 꽉 차면 새 공책을 추가로 이어 붙이는 것처럼요. 메모리가 허용하는 한 계속 이어붙일 수 있어요.

✍️ BigInt는 어떻게 만드나요? 숫자 뒤에 소문자 ‘n’을 붙이면 BigInt가 돼요. 예를 들어 9999999999999999n처럼요. ‘n’은 ‘nothing but huge number’가 아니라 그냥 BigInt를 표시하는 약속된 표시예요. 또는 BigInt(숫자)처럼 함수 형태로 만들 수도 있어요.

🚧 Number와 섞어 쓸 수 없어요 BigInt와 일반 Number를 직접 더하거나 빼면 오류가 나요. 이건 실수가 아니라 의도적인 설계예요. 두 타입을 섞으면 어느 쪽의 정밀도를 따를지 애매해지기 때문에, 명확하게 변환한 후에 계산하도록 강제합니다. 마치 킬로그램과 파운드를 바로 더할 수 없어서 같은 단위로 바꾼 후 더하는 것과 같아요.

🌍 어디서 필요한가요? 데이터베이스에서 아주 큰 고유 번호(ID)를 받을 때, 암호화폐 금액을 정확히 계산할 때, 아주 정밀한 시간을 다룰 때 BigInt가 필요해요. 이제 JavaScript도 이런 상황을 안전하게 처리할 수 있게 되었어요.

중급

BigInt는 ES2020(ECMAScript 2020)에서 도입된 원시 타입(primitive type)으로, 임의 정밀도 정수(arbitrary-precision integer) 연산을 지원합니다. 리터럴 표기는 숫자 뒤에 n을 붙이거나 BigInt() 함수를 사용합니다.

Number와 BigInt는 별개의 타입으로, 혼합 산술 연산 시 TypeError를 발생시킵니다. 이는 암묵적 변환으로 인한 정밀도 손실 사고를 방지하기 위한 설계 결정입니다.

// BigInt 리터럴 (숫자 뒤에 n)
const big = 9007199254740993n;
console.log(big); // 9007199254740993n (정확!)

// Number로 표현하면
console.log(9007199254740993); // 9007199254740992 (틀림!)

// BigInt로는 정확히 연산 가능
console.log(9007199254740991n + 2n); // 9007199254740993n
console.log(typeof 42n);             // "bigint"
// Number + BigInt 혼합 연산은 TypeError
try {
  const result = 1n + 1; // TypeError!
} catch (e) {
  console.log(e.message); // "Cannot mix BigInt and other types"
}

// 명시적 변환 후 연산
const bigValue = BigInt(Number.MAX_SAFE_INTEGER) + 100n;
console.log(bigValue); // 9007199254741091n

// BigInt를 Number로 변환 (정밀도 손실 가능성 주의)
console.log(Number(9007199254740993n)); // 9007199254740992 (손실!)

심화

BigInt는 임의 정밀도 정수 연산을 네이티브 언어 기능으로 지원하는 원시 타입으로, TC39 제안 프로세스를 거쳐 2019년 Stage 4에 도달하고 ECMAScript 2020에 포함되었습니다.

ECMAScript 명세에서의 BigInt 타입 정의 ECMAScript 2023 명세 6.1.7절(The BigInt Type)은 BigInt를 임의 정밀도 수학적 정수의 집합으로 정의합니다. BigInt 값은 수학적 정수 n에 대응하며, 명세는 이 집합에 상한/하한이 없음을 명시합니다. BigInt 연산의 추상 연산(Abstract Operation)은 6.1.7.1절에 정의되며, BigInt::add, BigInt::multiply 등은 모두 임의 정밀도 정수 산술 규칙을 따릅니다. Number와의 혼합 연산을 금지하는 TypeError는 명세 13.15.3절(ApplyStringOrNumericBinaryOperator)에서 타입 불일치(bigint/number 혼합) 시 명시적으로 발생시키도록 규정되어 있습니다.

V8 엔진의 BigInt 구현 V8에서 BigInt는 BigInt 힙 객체로 표현됩니다. 내부적으로 digits 배열(64비트 플랫폼에서 uintptr_t 배열)과 length 필드로 구성됩니다. 작은 BigInt(1 digit)는 SMI-like 최적화가 적용되지만, 크기에 따라 동적으로 배열이 확장됩니다. 산술 연산은 GNU MP(GMP) 라이브러리와 유사한 다중 정밀도 알고리즘을 사용하며, 곱셈에는 Karatsuba 알고리즘(O(n^1.585)) 또는 Toom-Cook 알고리즘이 적용됩니다. 따라서 BigInt 연산은 Number 연산에 비해 상당한 성능 오버헤드(일반적으로 10~100배)를 가지며, 필요한 경우에만 선택적으로 사용하는 것이 권장됩니다.

타입 분리 설계와 JSON 직렬화 제약 BigInt가 Number와 혼합 연산을 허용하지 않는 것은 TC39의 의도적 설계입니다. 암묵적 변환을 허용하면 어느 쪽으로 변환할지 결정해야 하는데, Number로 변환 시 정밀도 손실, BigInt로 변환 시 소수 버림이라는 양방향 손실 가능성이 존재합니다. 또한 JSON.stringify()는 BigInt를 기본적으로 직렬화하지 않고 TypeError를 발생시키므로, API 통신 시 문자열 변환 등의 별도 처리가 필요합니다. 이는 BigInt 지원 이전에 대규모 정수를 문자열로 전송하던 기존 JSON 생태계와의 호환성 문제를 반영합니다.

BigInt가 필요한 실무 시나리오

입문

BigInt가 실제로 어떤 상황에서 필요한지 알아볼게요. 생각보다 우리 주변 가까이에 있는 이야기예요!

🏦 은행과 금융 서비스 큰 금액을 아주 정확하게 다뤄야 하는 금융 서비스에서는 아주 작은 오차도 큰 문제가 됩니다. 특히 암호화폐에서 ‘1 이더리움’은 내부적으로 ‘1,000,000,000,000,000,000(10의 18제곱)‘개의 ‘wei’라는 작은 단위로 관리돼요. 이런 숫자를 다루려면 반드시 BigInt가 필요해요.

🗃️ 데이터베이스 ID 문제 대형 서비스의 데이터베이스는 수십억 개 이상의 데이터를 관리해요. 그래서 각 데이터에 붙이는 고유 번호(ID)가 9천조를 넘을 수 있어요. 이런 ID를 JavaScript의 일반 숫자로 받으면 살짝 달라진 숫자로 읽혀서 엉뚱한 데이터를 찾아갈 수 있어요.

⏱️ 매우 정밀한 시간 측정 과학 실험이나 고성능 애플리케이션에서는 시간을 나노초(1초의 10억분의 1) 단위로 측정해요. 이런 타임스탬프 값도 9천조를 넘을 수 있기 때문에 BigInt를 활용하면 정확한 시간 계산이 가능해요.

🔐 암호화와 보안 암호화 알고리즘에서는 아주 큰 소수(素數)나 큰 정수를 곱하고 나누는 연산이 자주 나와요. 이런 계산에서 조금이라도 틀린 숫자가 쓰이면 보안이 뚫릴 수 있기 때문에 BigInt의 정확성이 꼭 필요합니다.

중급

BigInt가 실제로 필요한 상황은 크게 네 가지 영역으로 나뉩니다.

1. 64비트 정수 ID 처리: 많은 백엔드 시스템(PostgreSQL의 bigint, Twitter Snowflake ID 등)은 2^63 - 1 범위의 64비트 정수 ID를 사용합니다. 이 값은 Number.MAX_SAFE_INTEGER(2^53 - 1)를 초과하므로 JSON 파싱 시 정밀도 손실이 발생합니다.

2. 암호화폐 단위 계산: Ethereum의 wei(1 ETH = 10^18 wei)처럼 소수점 이하 18자리를 정수로 표현하면 2^53을 크게 초과합니다.

3. 고정밀 타임스탬프: process.hrtime.bigint()(Node.js)는 나노초 단위 Unix 타임스탬프를 BigInt로 반환합니다. 현재 나노초 타임스탬프는 약 1.7 × 10^18 수준으로 안전 정수 범위를 초과합니다.

4. 암호학적 연산: RSA, Diffie-Hellman 등 공개키 암호화 알고리즘에서 사용하는 큰 소수는 수백 ~ 수천 비트 크기입니다.

// 1. Twitter Snowflake ID 처리 (64비트 정수)
const snowflakeId = BigInt("1234567890123456789");
const timestamp = snowflakeId >> 22n; // 비트 연산도 지원

// 2. Ethereum wei 계산 (1 ETH = 10^18 wei)
const oneEth = 1_000_000_000_000_000_000n; // 10^18
const gas = 21000n;
const gasPrice = 20_000_000_000n; // 20 Gwei
const totalCost = gas * gasPrice; // 420000000000000n (정확!)

// 3. 고정밀 타임스탬프 (Node.js)
// const nanoTime = process.hrtime.bigint(); // BigInt 반환
console.log(typeof oneEth); // "bigint"

JSON과의 호환성 문제 BigInt는 JSON.stringify()를 통해 직렬화되지 않으므로, API 응답에서 대규모 정수 ID를 받을 때는 서버가 문자열로 전송하고 클라이언트에서 BigInt(stringId)로 변환하는 패턴을 사용합니다.

심화

BigInt의 실무 필요성은 분산 시스템, 금융 시스템, 암호학의 도메인별 요구사항에서 구체적으로 드러납니다.

분산 시스템 ID와 Snowflake 아키텍처 Twitter에서 고안한 Snowflake ID는 64비트 정수로 구성됩니다(41비트 타임스탬프 + 10비트 머신 ID + 12비트 시퀀스). 현재(2024년) 기준 타임스탬프 부분만으로도 약 1.7 × 10^12 수준이며, 전체 Snowflake ID는 2^63에 근접합니다. ECMAScript 명세의 Number.MAX_SAFE_INTEGER(2^53 - 1)를 훨씬 초과하므로, JSON 파싱 시 하위 비트 손실이 불가피합니다. 이에 따라 대규모 분산 시스템에서는 ID를 문자열로 직렬화하거나, JSON 스펙의 확장으로 BigInt 직렬화를 지원하는 json-bigint 라이브러리를 활용하는 패턴이 보편화되었습니다.

암호화폐 및 블록체인 도메인 Ethereum의 기본 단위인 wei(1 ETH = 10^18 wei)는 2^59.79에 해당하므로 Number로는 정밀하게 표현할 수 없습니다. ethers.js 5.x 이상에서는 모든 토큰 양을 BigInt로 처리하며, Web3.js 4.x도 BigInt를 기본 숫자 타입으로 채택했습니다. EVM(Ethereum Virtual Machine) 자체가 256비트 정수 연산을 기반으로 설계되었기 때문에, JavaScript 클라이언트 라이브러리가 BigInt를 필수적으로 사용하는 것은 자연스러운 귀결입니다.

암호학적 연산과 성능 트레이드오프 WebCrypto API는 키 소재를 ArrayBuffer로 관리하므로 BigInt 직접 연산이 필요하지 않지만, 순수 JavaScript로 구현된 암호 라이브러리(예: forge, node-forge)는 RSA 키 생성, 모듈러 지수 연산(modular exponentiation) 등에 BigInt를 활용합니다. 다만 V8의 BigInt 연산은 WASM(WebAssembly)의 i64 또는 네이티브 GMP 기반 C 구현보다 10~100배 느리므로, 성능이 중요한 암호화 연산에서는 WASM 모듈을 우선 고려해야 합니다.