1. JavaScript와 Java에서 64비트 데이터를 다루는 방법
- ULog 비행로그의 data를 리펙토링하다가 java에서는 올바르게 time_utc_usec의 값이 변환되었지만 js에서는 time_utc_usec 값이 올바르게 변환이 되지않기에 찾아보다가 java와 JavaScript에서 데이터를 다루는 방법이 다른걸 알게되어서 이번 블로그 글을 작성한다.
- 개발을 하다 보면 64비트 정수를 다뤄야 할 때가 있다. 하지만 각 언어마다 64비트를 다루는 방식이 다르고, 특히 JavaScript에서는 나처럼 예상치 못한 오류를 만날 수 있다.
- 이번 글에서는 Java와 JavaScript에서 64비트 데이터를 어떻게 처리하는지, 그 차이점과 올바르게 64비트 데이터를 다루는 방법에 대해 알아보자.
2. Java 64비트 정수 처리
- 먼저, 각 언어에서 64비트 정수를 어떻게 처리하는지 알아보자.
- Java는 long 타입으로 기본적으로 64비트 정수를 지원한다.
- Java에서 64비트 처리 : Java에서는 long 타입이 64비트 정수다. 별다른 추가 작업 없이 long을 사용하면 된다.
- Java의 경우 내부적으로 64비트 정수를 처리하기 때문에 메모리나 CPU가 32비트 기반이라도 자동으로 상위 32비트와 하위 32비트를 결합해 64비트 정수를 처리할 수 있다.
long value = 9223372036854775807L; // 64비트 정수
3. JavaScript 64비트 정수 처리
- 하지만 JavaScript는 BigInt라는 새로운 타입을 사용해 64비트 이상의 정수를 다룬다.
- JavaScript는 Number 타입이 기본적으로 부동소수점 기반의 64비트 정수지만, 실제로는 안전하게 사용할 수 있는 정수 범위가 제한적이다.
- Number로는 2^53 범위 안에서만 안전하게 정수를 다룰 수 있다. 그 이상 큰 정수를 다루기 위해서는 BigInt라는 별도의 타입을 사용해야 한다.
- 즉, JavaScript에서 64비트 이상의 정수를 다루려면 반드시 BigInt를 사용해야 한다.
let bigIntValue = 9223372036854775807n; // 64비트 이상의 정수는 BigInt로 처리
4.코드 비교
- JavaScript와 Java에서 64비트 정수를 처리할 때 문제가 되는 부분임
- 아래의 코드에서는 64비트 데이터를 처리해야 하지만, getUint32로 32비트만 반환한다. 즉, 전체 64비트를 읽지 않고 하위 32비트만 처리하게 된다. 이는 64비트의 정확한 값을 읽을 수 없다는 뜻이다.
export const UINT_642 = { name: "uint64_t", byte_size: 8, func: (dv, i) => { return dv.getUint32(i, true); // 32비트만 반환 }, };
- 아래의 코드는 getBigUint64를 사용해 정확하게 64비트 데이터를 읽어온다. JavaScript에서는 이렇게 BigInt를 사용해야만 큰 정수를 안전하게 다룰 수 있다.
export const UINT_64 = { byte_size: 8, func: (dataView, index) => dataView.getBigUint64(index, true), // 64비트 정수를 정확하게 반환 };
5. Java와 JavaScript에서의 64비트 차이점
- Java: Java는 기본적으로 long 타입을 통해 64비트 정수를 안전하게 다룬다. CPU나 메모리가 32비트 기반이라도 자동으로 64비트 값을 처리할 수 있다.
- JavaScript: JavaScript의 Number 타입은 실제로 64비트 부동소수점 기반이지만, 정수로 안전하게 다룰 수 있는 범위는 2^53까지다. 64비트 이상의 정수를 안전하게 처리하려면 BigInt 타입을 사용해야 한다.
6. 왜 Java에서는 UINT_642로 충분한데 JavaScript에서는 UINT_64가 필요한가?
- Java에서는 UINT_642처럼 32비트만 처리해도 64비트 정수 처리가 어느 정도 가능하다. 이유는 Java가 64비트 정수를 기본적으로 지원하기 때문에 상위 32비트 또는 하위 32비트를 처리하는 방식이 유연하게 동작할 수 있기 때문이다.
- 반면, JavaScript에서는 64비트 이상의 정수를 정확히 처리하려면 반드시 BigInt 타입을 사용해야 한다. UINT_642처럼 32비트만 읽으면 64비트 값 중 절반만 처리하게 되어, 정확한 64비트 데이터를 다룰 수 없다. 그래서 UINT_64처럼 정확하게 64비트 데이터를 처리하는 방식이 필요하다.
7. 간단정리
- jJavaScript에서는 64bit를 다루기위해 getUint32을 사용하는게 아닌 getBigUint64를 사용해야함 이유는 getUint64가 없기때문에