개발자가 되고 싶은 개발자

JavaScript의 Number 표현범위 (Java의 int를 곁들인…) 본문

Dev/JavaScript & TypeScript

JavaScript의 Number 표현범위 (Java의 int를 곁들인…)

Fullth 2024. 7. 18. 22:27
 

Number - JavaScript | MDN

Number values represent floating-point numbers like 37 or -9.25.

developer.mozilla.org

아래와 같이 일반적인 자료형의 범위를 넘어가는 요청을 방지하고자 하는 작업이 존재하였습니다.
처리하는 과정에서 JS의 기초적인 부분에 대해 망각하고 있어 정리합니다.

GET /items?page[offset]=0&page[limit]=200000000000000000000

 

쿼리스트링

잠시 쿼리스트링에 대해서 얘기해보겠습니다. 

 

쿼리스트링은 데이터를 전달하는 기본적인 방법 중 하나입니다. URL의 일부이고, 이름에서 알 수 있듯이 문자열입니다.

 

HTTP 요청은 텍스트 기반이므로 쿼리스트링을 포함한 요청은 문자열로 데이터가 전송되게 됩니다.

 

요청 파라미터 검증

API 서버에서는 보통 미들웨어에서 파라미터에 대한 검증을 진행합니다.


Spring 프로젝트를 진행하는 동료분께 어떻게 방지하고 계신는지 여쭤보니 숫자형으로 변환하여 자료형의 범위를 벗어나는 것으로 에러를 반환하는 형태로 처리하신다고 들었습니다.

제가 담당중인 Node.js 환경의 미들웨어에도 분명 숫자형으로 변환하고 있었지만, 범위에 대한 에러는 발생하지 않았고 내부까지 도달하여 에러를 반환한 원인을 파악하고 있었습니다.

 

Java의 int

 

 

Primitive Data Types (The Java™ Tutorials > Learning the Java Language > Language Basics)

The Java Tutorials have been written for JDK 8. Examples and practices described in this page don't take advantage of improvements introduced in later releases and might use technology no longer available. See Java Language Changes for a summary of updated

docs.oracle.com

Java에는 표현 가능한 범위에 따라 int, double 등 여러 자료형들이 존재합니다.

 

int의 허용범위는 아래와 같습니다.

  • 최소값: -2,147,483,648
  • 최대값: 2,147,483,647
int: By default, the int data type is a 32-bit signed two's complement integer, which has a minimum value of -2^31  and a maximum value of 2^31-1.

 

일반적인 데이터의 경우 int 형으로 변환했을 것이고, 본문 서두에서 작성한 요청은 NumberFormatException이 발생할 것입니다.

String largeNumberStr = "200000000000000000000";
int convertedNumber = Integer.parseInt(largeNumberStr);

 

JavaScript의 number

JavaScript의 number 타입은 Java의 double과 같이 IEEE 754 표준을 따르는 64비트 부동소수점 형식을 사용합니다.

 

IEEE 754 - 위키백과, 우리 모두의 백과사전

위키백과, 우리 모두의 백과사전. IEEE 754는 IEEE에서 개발한 컴퓨터에서 부동소수점을 표현하는 가장 널리 쓰이는 표준이다. ±0 등의 수와 무한, NaN 등의 기호를 표시하는 법과 이러한 수에 대한

ko.wikipedia.org

 

부동소수점 방식을 사용하기 때문에 정밀도가 떨어져 정확한 값을 표현할 수 없을 순 있어도 변환할 수 없는 값은 아니었기에 에러가 발생하지 않았고 그대로 내부 로직까지 도달할 수 있었습니다.

실제 발생했던 에러도 2.0E20… 와 같이 변환된 값이 에러 메시지에 노출되는 것을 확인할 수 있었습니다.

 

MAX_SAFE_INTEGER

조사하면서 Number. MAX_SAFE_INTEGER와 같은 정적 프로퍼티를 확인하였습니다.
추가로, Number.isSafeInteger() 메서드를 사용하여 안전한 정수 범위 내의 값인지 확인할 수 있습니다.

const limit = Number(req.query.page.limit);
if (!Number.isSafeInteger(limit) || limit > Number.MAX_SAFE_INTEGER) {
  return res.status(400).json({ error: '유효하지 않은 limit 값입니다.' });
}


에러를 발생시키는 것도 아니고, 정확한 값도 아닐 수도 있다는 점은 금융거래 관련 작업에서 큰 문제를 야기할 수 있는 부분이기에 정리하였다.


정밀데이터를 다룰 때는 기본자료형 중 Bigint 혹은 Decimal과 같은 라이브러리의 도입을 검토할 필요가 있습니다.

새삼 점점 더 기본기의 중요성을 깨닫게 되는 요즘입니다.