AD JB Toolbox 01

JavaScript / 숫자에 천 단위 쉼표 추가하는 방법, 제거하는 방법

숫자에 천 단위 쉼표를 표시하려면 toLocaleString("ko-KR") 또는 Intl.NumberFormat("ko-KR")을 사용합니다. 쉼표가 있는 문자열을 계산하려면 먼저 입력 형식과 쉼표 위치를 검사한 뒤 쉼표를 제거하고 숫자로 변환하세요. 표시 문자열과 계산용 숫자는 별도로 관리하는 것이 좋습니다.

로케일을 지정해 쉼표로 표시하기

(123456789).toLocaleString("ko-KR"); // "123,456,789"
(123456789).toLocaleString("de-DE"); // "123.456.789"

const formatter = new Intl.NumberFormat("ko-KR");
formatter.format(123456789);        // "123,456,789"

로케일(locale)은 언어·지역별 표시 규칙을 지정하는 값입니다. 생략하면 실행 환경의 기본 로케일을 사용하므로 구분 기호가 항상 쉼표라고 가정하면 안 됩니다. 같은 옵션으로 여러 값을 표시한다면 Intl.NumberFormat 객체를 만들어 재사용할 수 있습니다. 반환값은 계산용 숫자가 아니라 문자열입니다. toLocaleString()의 로케일 지정과 Intl.NumberFormat 안내를 참고하세요.

소수 자릿수와 통화 옵션

const decimal = new Intl.NumberFormat("ko-KR", {
  minimumFractionDigits: 2,
  maximumFractionDigits: 2
});
decimal.format(1234.5); // "1,234.50"

const won = new Intl.NumberFormat("ko-KR", {
  style: "currency",
  currency: "KRW"
});
won.format(123456789); // 원화 기호와 천 단위 구분으로 표시

최소·최대 소수 자릿수를 함께 지정하면 표시 길이와 반올림 범위를 분명히 할 수 있습니다. 일반 숫자 표시의 기본 최대 소수 자릿수는 3이므로, 더 많은 소수를 보이려면 옵션을 지정하세요. 통화 스타일은 통화별 기본 소수 자릿수를 적용합니다. 표시 과정의 반올림은 원래 변수에 저장한 숫자를 변경하지 않습니다. 옵션별 차이는 NumberFormat 생성자 옵션에서 확인할 수 있습니다.

쉼표 제거와 숫자 변환은 별도 작업입니다

const text = "123,456,789";
const plain = text.replace(/,/g, "");
plain;          // "123456789"
typeof plain;   // "string"
Number(plain);  // 123456789

/,/g는 쉼표를 모두 찾는 정규표현식입니다. 정규표현식은 문자열의 패턴을 검사하거나 치환하는 표기이며, g는 첫 일치에서 멈추지 않고 전체를 대상으로 한다는 뜻입니다. replace()는 새 문자열을 반환하므로 원래 문자열 자체를 숫자로 바꾸지 않습니다.

이 단순 치환만으로는 입력이 올바른지 알 수 없습니다. "12,34"는 잘못된 묶음인데 쉼표를 제거하면 1234가 되어 오류가 숨겨집니다. 숫자 외의 모든 문자를 제거하는 방식은 -12.5를 125로 바꾸는 등 값을 훼손할 수 있으므로 피하세요.

전체 예제: 입력 형식부터 검사하기

아래 코드를 UTF-8의 number-grouping.html로 저장해 브라우저로 여세요. 이 예제는 앞뒤 공백, 선택적인 부호, 정수부와 선택적인 소수부를 허용합니다. 쉼표가 있으면 첫 묶음은 1~3자리, 뒤의 묶음은 정확히 3자리여야 합니다.

<!doctype html>
<html lang="ko">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>천 단위 쉼표와 입력 검사</title>
  <style>
    body { margin: 24px; font: 16px/1.7 sans-serif; }
    input, button, select { font: inherit; max-width: 100%; }
    label { display: block; margin-top: 12px; }
    #output { white-space: pre-wrap; overflow-wrap: anywhere; }
  </style>
</head>
<body>
<label for="value">쉼표가 있거나 없는 십진수</label>
<input id="value" type="text" value="1,234,567.89">
<button id="format" type="button">검사하고 표시</button>
  <pre id="output" aria-live="polite"></pre>
  <script>
    function parseGroupedDecimal(input) {
      const text = input.trim();
      const pattern = /^[+-]?(?:\d+|\d{1,3}(?:,\d{3})+)(?:\.\d+)?$/;
      if (!pattern.test(text)) return null;
      const value = Number(text.replace(/,/g, ""));
      return Number.isFinite(value) ? value : null;
    }
    const formatter = new Intl.NumberFormat("ko-KR", {
      useGrouping: true,
      maximumFractionDigits: 20
    });
    function show() {
      const input = document.getElementById("value").value;
      const value = parseGroupedDecimal(input);
      const output = document.getElementById("output");
      if (value === null) {
        output.textContent = "쉼표 위치와 숫자 형식을 확인하세요.";
        return;
      }
      output.textContent = `숫자: ${value}\n표시: ${formatter.format(value)}\n자료형: ${typeof value}`;
    }
    document.getElementById("format").addEventListener("click", show);
    show();
  </script>
</body>
</html>

초기 입력은 숫자 1234567.89로 변환되고 1,234,567.89로 표시됩니다. -12,345.6과 0은 허용하지만 12,34, 1,234,, ₩1,000, 빈 값은 거부합니다. 실패를 null로 반환하므로 유효한 숫자 0과 구분할 수 있습니다. 최대 소수 자릿수 20은 표시 옵션일 뿐, Number의 실제 정밀도를 늘리지 않습니다.

정규표현식으로 표시 문자열을 직접 만들 때

const text = "-1234567.8900";
const [integer, fraction] = text.split(".");
const grouped = integer.replace(/\B(?=(\d{3})+(?!\d))/g, ",");
const result = fraction === undefined
  ? grouped
  : `${grouped}.${fraction}`;
console.log(result); // -1,234,567.8900

이 방식은 이미 형식을 검사한 십진 문자열의 정수부에만 쉼표를 넣습니다. 소수부를 분리하지 않고 전체 문자열에 숫자 묶음 패턴을 적용하면 소수부에도 쉼표가 생길 수 있습니다. 기존 소수부의 끝 0을 그대로 보관할 필요가 있을 때는 문자열 처리가 유용하지만, 지수 표기나 다른 지역 형식까지 자동 처리하는 범용 숫자 포맷터는 아닙니다.

다른 지역 형식과 큰 정수의 한계

  • 독일어 표기의 "1.234,56"는 이 예제의 입력 형식이 아닙니다. Intl.NumberFormat은 표시 기능이며 역변환용 범용 파서가 아니므로, 입력에 허용할 지역 규칙을 먼저 정하세요.
  • Number의 안전한 정수 범위를 넘으면 자릿수가 손실될 수 있습니다. 큰 정수는 문자열을 보관한 뒤 허용한 정수 형식에 한해 BigInt로 처리할 수 있지만, BigInt는 소수를 저장하지 않습니다.
  • 입력값의 유한성·자료형 검사는 Number() 변환과 검사를, 계산 결과의 자릿수 처리는 내림·올림·반올림의 차이를 참고하세요.
같은 카테고리의 다른 글
JavaScript / 내림, 올림, 반올림

JavaScript / 내림, 올림, 반올림

Math.floor(), Math.ceil(), Math.round()의 차이와 음수의 처리 방향을 비교합니다. 자릿수 변경, Math.trunc()와의 차이, 소수 오차와 표시 형식도 함께 설명합니다.

JavaScript / 메모

JavaScript / 메모

JavaScript의 숫자 표시, URI 인코딩·디코딩과 검색 매개변수 생성 코드를 정리합니다. 오래된 escape() 사용과 IE8용 선택자 보완 메모를 현재 코드에 적용할 때의 차이도 설명합니다.

JavaScript / 함수 / Number() - 문자열을 숫자로 변환하는 함수

JavaScript / 함수 / Number() - 문자열을 숫자로 변환하는 함수

Number()로 문자열을 숫자로 변환하는 문법과 빈 문자열·NaN·Infinity 처리 방법을 설명합니다. 입력값 검사와 parseInt(), parseFloat()의 차이도 예제로 비교합니다.

JavaScript / 함수 / String() - 숫자를 문자열로 변환하는 함수

JavaScript / 함수 / String() - 숫자를 문자열로 변환하는 함수

String()으로 숫자를 문자열로 바꾸는 방법과 덧셈·문자열 연결의 차이를 설명합니다. 빈 값, new String(), 숫자 표시 형식의 주의점도 확인할 수 있습니다.

JavaScript / 조건문 / if, else if, else, switch

JavaScript / 조건문 / if, else if, else, switch

if·else if·else와 switch로 실행 경로를 선택하는 방법을 설명합니다. 입력값 검증, 엄격한 비교, break 누락과 case의 실행 범위를 예제로 확인할 수 있습니다.

JavaScript / 반복문 / while, do - while, for

JavaScript / 반복문 / while, do - while, for

while, do...while, for의 실행 순서와 선택 기준을 비교합니다. 0부터 9까지 출력하는 전체 예제와 무한 반복, break·continue의 주의점을 설명합니다.

JavaScript / 숫자에 천 단위 쉼표 추가하는 방법, 제거하는 방법

JavaScript / 숫자에 천 단위 쉼표 추가하는 방법, 제거하는 방법

toLocaleString()과 Intl.NumberFormat으로 천 단위 쉼표를 표시하고, 쉼표가 있는 입력을 검증해 숫자로 변환하는 방법을 설명합니다. 소수·음수·큰 정수의 한계도 다룹니다.