기술공부/언어

[Node.js] 왜 pg 라이브러리에서 bigint를 string으로 인식할까?

봉두두 2024. 8. 26. 16:10
728x90

현재 진행하고 있는 프로젝트에서 postgresql의 stored procedure를 활용하는 케이스가 많은데,

집계함수 sum을 사용해 반환되는 값은 integer가 아닌 bigint로 반환이 된다.

이를 node.js에서 받아서 처리하려고 하다 보니 return값이 string으로 오는 것을 발견했다.

(나는 분명 count를 누적했는데 01011201 이런값으로 누적이 되네..?)

 

원인을 좀 찾아보니 node.js에서 사용중인 pg라이브러리의 처리 로직이 bigint를 string으로 받아 처리한다는 게 원인이었음을 알았다. 데이터 소실 이슈 발생을 막기 위해서라는데.

 

내가 문서를 제대로 읽지 않은 탓이겠지..?

 

아래는 chatGPT에서 답변한 내용이다.

 

나의 질문_PostgreSQL에서 sum() 함수의 반환값은 bigint야?

ChatGPT 답변

PostgreSQL에서 SUM() 함수의 반환 형식은 해당 열의 데이터 형식에 따라 달라집니다. 기본적으로 SUM() 함수는 합산할 열의 데이터 형식을 따라가며, 이에 따라 반환되는 값의 데이터 형식도 결정됩니다.

  • 정수형 데이터 타입 (e.g., INT, BIGINT):
    • SUM() 함수가 INTEGER 타입 열에 대해 사용될 경우, 결과는 기본적으로 BIGINT 타입으로 반환됩니다. 이는 합계가 INTEGER 범위를 초과할 수 있기 때문에, BIGINT로 반환하여 데이터 범위를 안전하게 처리하기 위함입니다.
    • BIGINT 타입 열에 대해 사용될 경우, 결과는 역시 BIGINT 타입으로 반환됩니다.
  • 부동소수점 숫자형 데이터 타입 (e.g., NUMERIC, FLOAT):
    • SUM() 함수가 NUMERIC 또는 DECIMAL 타입 열에 대해 사용될 경우, 결과는 NUMERIC 또는 DECIMAL 타입으로 반환됩니다.
    • FLOAT 또는 REAL 타입 열에 대해 사용될 경우, 결과는 같은 타입(FLOAT 또는 REAL)으로 반환됩니다.

예제:

  1. 정수형 열에 대한 합계:
    • 만약 column_name이 INTEGER 타입이라면, 반환 값은 BIGINT 타입입니다.
  2.  
    SELECT SUM(column_name) FROM table_name;
  3. sql
    코드 복사
  4. 부동소수점 숫자형 열에 대한 합계:
    • 만약 column_name이 NUMERIC 타입이라면, 반환 값도 NUMERIC 타입입니다.
  5. sql
    코드 복사
    SELECT SUM(column_name) FROM table_name;

요약:

  • 정수형 열 (INT, BIGINT): SUM() 결과는 BIGINT로 반환됩니다.
  • 부동소수점 숫자형 열 (NUMERIC, DECIMAL, FLOAT, REAL): SUM() 결과는 원래 데이터 타입을 유지하여 반환됩니다.

따라서, PostgreSQL에서 SUM() 함수는 열의 데이터 타입에 따라 반환 타입을 결정하며, 정수형 데이터 타입의 경우 반환 값이 BIGINT일 가능성이 큽니다.

 

 

 

나의 질문_ 혹시 postgresql에서 bigint로 반환해서 nodejs에서 string으로 인식하는걸까?

ChatGPT 답변

네, PostgreSQL에서 BIGINT로 반환된 값이 Node.js에서 string으로 인식되는 현상은 Node.js의 pg (node-postgres) 라이브러리의 기본 동작 때문입니다.

이유:

  • JavaScript의 숫자 타입 한계: JavaScript의 Number 타입은 IEEE 754 표준에 따라 64비트 부동소수점으로 표현되며, 안전하게 표현할 수 있는 정수 범위는 -(2^53 - 1)부터 2^53 - 1까지입니다. 이 범위를 벗어나는 정수를 다루게 되면 정확도가 떨어집니다.
  • PostgreSQL의 BIGINT 타입: BIGINT는 64비트 정수로, 범위가 -9223372036854775808에서 9223372036854775807까지입니다. 이 범위는 JavaScript의 안전한 정수 범위(Number.MAX_SAFE_INTEGER = 9007199254740991)를 초과할 수 있습니다.
  • node-postgres 라이브러리의 처리: pg 라이브러리는 PostgreSQL의 BIGINT와 NUMERIC 타입을 기본적으로 string으로 반환합니다. 이는 큰 정수의 정확도를 보존하기 위해서입니다. 만약 pg가 BIGINT 값을 number로 반환하게 한다면, JavaScript에서 안전하게 처리할 수 없는 큰 정수는 손실되거나 부정확한 값으로 처리될 수 있기 때문입니다.

해결 방법:

  1. 필요에 따라 string으로 처리: pg가 반환한 BIGINT 값을 string으로 그대로 사용합니다. 이 방법은 가장 안전하게 큰 정수를 처리할 수 있습니다.
  2. bigint로 변환하여 사용: Node.js에서 BIGINT 타입을 지원하는 ES2020의 BigInt 타입을 사용할 수 있습니다.
  3. javascript
    코드 복사
    const bigIntValue = BigInt(dbResult.rows[0].bigint_column);
  4. 타입 캐스팅 (작은 값만 처리할 때): 만약 반환된 값이 JavaScript에서 안전하게 처리할 수 있는 범위 내에 있다고 확신할 수 있다면, Number로 변환할 수 있습니다.하지만 이 방법은 안전한 범위를 초과하는 값에 대해 위험할 수 있습니다.
  5. javascript
    코드 복사
    const numberValue = Number(dbResult.rows[0].bigint_column);

요약:

PostgreSQL에서 BIGINT로 반환된 값이 Node.js에서 string으로 인식되는 것은 pg 라이브러리의 의도된 동작입니다. 이는 JavaScript의 Number 타입이 BIGINT의 모든 값을 안전하게 표현할 수 없기 때문에, 데이터의 정확도를 보존하기 위해서입니다. 필요한 경우 BigInt로 변환하거나, 작은 값이라면 Number로 변환하여 사용할 수 있습니다.

 

728x90
728x90