문제
숫자를 넣었을 때, 3자리 수마다 콤마 ','
가 찍히는 input을 구현하는 중에 느닷없는 도전과제가 발생했다.
일반적으로 사용하는 수는 16자리 이내이기 때문에 아래의 코드로도 충분히 동작하지만 아래 코드는 치명적인 문제가 하나 있었다. 입력된 숫자의 길이가 16을 넘어가면 값이 뭉개지는 문제가 있다. 지수형 값으로 변환되어 발생하는 것으로 예를 들어 “1234567890123456789” 라는 숫자를 입력한 경우 “1,234,567,890,123,457,000”로 출력된다.
// 값이 변경되면 저장하는 함수, 천단위마다 ','를 입력함
const priceChangeHandler = function (event) {
let inputPrice = event.target.value.replace(/,/g, "");
if (!inputPrice) { // 입력된 값이 없을 경우 0으로 초기화
setPrice("0");
return;
}
if (!/^\d+$/.test(inputPrice)) return;
const newPrice = parseInt(inputPrice).toLocaleString();
setPrice(newPrice);
};
TRY …
1. 문자열로 처리해 보기
const newPrice = inputPrice.replace(/\B(?=(\d{3})+(?!\d))/g, ",");
문자열로써 세자리 마다 콤마를 찍어주는 것으로 해결할 수 있다.
그러나 이 방법을 사용하면 문제가 발생한다.
Input
의 초기값 0
이 입력 값 앞에 붙어 입력된다. 123
이라는 값을 입력했다고 하면 0,123
으로 출력된다.
또한 입력 후 앞의 0
을 지운다고 해도 문제가 발생한다. 01,234
라는 값에서 앞의 0
을 지우면 1,234
와 같이 문제가 해결된 것처럼 보인다. 그러나, 데이터를 지울때 문제가 발생한다. 값을 잘못 입력했다고 생각해 값을 모두 지우면 맨 앞에 있던 1
이 남아 지워지지 않게 된다.
문제를 해결하려면 복잡해질 것이 예상되어 다른 방법을 찾아보기로 했다.
2. Javascript의 BigInt를 사용해보기
const newPrice = parseInt(inputPrice).toLocaleString();
setPrice(newPrice);
=> const newPrice = BigInt(inputPrice).toLocaleString();
setPrice(newPrice);
C 언어에 long
, long long
과 같이 큰 수를 사용하기 위한 방법이 있듯이 자바스크립트에도 비슷한 것이 있다. ES2020에서 추가된 내장 객체 BigInt
는 Number
원시 값이 안정적으로 나타낼 수 있는 최대치인 2^53 - 1보다 큰 정수를 표현할 수 있는 내장 객체이기 때문에 사용할 수 있을 것이라고 생각했다. 그러나…
내장 객체인데 no-undef
에러가 발생…
BigInt
가 정의되지 않았다는 에러가 발생하고 있었다.
왜 안되는가?
MDN 문서를 살펴보았지만 문제가 될만한 요소를 찾지 못했다.
현재 테스트에 사용하는 브라우저는 Safari와 Chrome이기 때문에 브라우저 호환성 문제와도 관련이 없으며 위 에러 메세지는 BigInt가 정의되지 않아 발생하는 에러 메세지이기 때문이다.
그렇다면 React에서 BigInt
를 사용하려면 별도로 import
해야하는 라이브러리가 있는것인가하면 그것도 아니다. 왜냐하면 자바스크립트 내장 객체이므로 별도의 import
가 필요하지 않다.
이미 나와 비슷한 고민을 했던 개발자가 있었을 것이므로 스택오버플로우에 도움을 요청하기로 했다.
해결
스택오버플로우에서 내가 찾은 방법은 다음과 같다.
React에서 BigInt
를 사용하려면 활성화를 시켜주어야한다. 활성화하는 방법은 아래의 주석을 코드에 추가하는 것이다.
/* global BigInt */
이 주석을 추가하면 전역에서 BigInt
를 사용할 수 있게 된다.
최종적으로 아래와 같이 코드를 작성하여 문제가 해결되었다.
import React from "react";
import { useState } from "react";
import * as S from "../Styled";
/* global BigInt */
function Input() {
// 입력을 받을 상태값
const [price, setPrice] = useState(0);
const [name, setName] = useState("");
// 값이 변경되면 저장하는 함수, 천단위마다 ','를 입력함
const priceChangeHandler = function (event) {
let inputPrice = event.target.value.replace(/,/g, "");
if (!inputPrice) { // 입력된 값이 없을 경우 0으로 초기화
setPrice("0");
return;
}
// 입력값을 검사하여 숫자가 아닌 경우 함수를 종료 = 숫자만 입력 가능
if (!/^\d+$/.test(inputPrice)) return;
const newPrice = BigInt(inputPrice).toLocaleString();
setPrice(newPrice);
};
'Develop > TIL' 카테고리의 다른 글
항해99 실전 프로젝트를 앞두고 (0) | 2023.06.09 |
---|---|
<WIL> 첫 협동프로젝트 : 프론트 엔드는 생각보다 작업량이 많았다. (0) | 2023.05.26 |
<WIL> REACT 기초 입문 (0) | 2023.05.02 |
[프론트엔드] 브라우저 저장소 학습하기 (0) | 2023.04.24 |
React 프로젝트 생성 후 수정할 수 없는 문제 (0) | 2023.04.22 |