ToolPal
어두운 배경 위의 숫자와 수학 기호들

JavaScript 숫자 포맷팅 완벽 가이드: Intl.NumberFormat으로 다국어 숫자 표시하기

📷 Antoine Dautry / Pexels

JavaScript 숫자 포맷팅 완벽 가이드: Intl.NumberFormat으로 다국어 숫자 표시하기

국제화를 위한 숫자 포맷팅 마스터하기. JavaScript Intl.NumberFormat으로 통화, 퍼센트, 로케일별 숫자 표시 방법을 알아보세요.

2026년 4월 10일6분 소요

웹 개발을 하다 보면 숫자를 화면에 표시하는 일이 생각보다 복잡하다는 걸 느낄 때가 있습니다. 저도 처음에는 단순히 toLocaleString()만 쓰면 되겠지 싶었는데, 국제 서비스를 만들면서 생각보다 고려해야 할 것이 많다는 걸 알게 됐습니다.

특히 한국에서만 서비스하다가 글로벌로 확장할 때 "왜 독일 사용자들이 소수점 표기가 이상하다고 하지?" 같은 문제를 마주치면 당황스럽죠. 이 글에서는 Intl.NumberFormat API를 실제 업무에서 활용하는 방법을 가능한 실용적으로 정리해 보겠습니다.

나라마다 숫자 표기가 다르다는 문제

개발자 입장에서는 그냥 1234567.89를 화면에 뿌리면 되는 것 아닌가 싶지만, 사용자 입장에서는 다릅니다.

  • 한국 / 미국 / 일본: 1,234,567.89 (쉼표가 천 단위 구분자, 점이 소수점)
  • 독일 / 오스트리아: 1.234.567,89 (점이 천 단위 구분자, 쉼표가 소수점)
  • 프랑스: 1 234 567,89 (공백이 천 단위 구분자, 쉼표가 소수점)
  • 인도: 12,34,567.89 (첫 그룹만 3자리, 이후는 2자리씩 묶음)

독일 사용자에게 1,234.56을 보여주면 그 사람은 "1.234,56"으로 이해해야 맞는데 표기가 달라서 혼란스러울 수 있습니다. 금융 서비스라면 더 심각한 문제가 됩니다.

예전에는 이런 걸 처리하려고 직접 문자열 조작을 했는데, 그러다 보면 예외 케이스가 끝없이 나옵니다. 다행히 JavaScript에는 이미 훌륭한 해결책이 있습니다.

Intl.NumberFormat 기본 사용법

Intl 네임스페이스는 JavaScript 표준 국제화 API입니다. 그 중 Intl.NumberFormat이 숫자 포맷팅을 담당합니다. ES2015(ES6)부터 표준에 포함됐고, 현대 브라우저와 Node.js 10 이상에서 모두 잘 동작합니다.

// 기본 사용법
const formatter = new Intl.NumberFormat('ko-KR');
formatter.format(1234567.89);
// "1,234,567.89"

// 또는 한 번만 쓸 때는 바로 호출
new Intl.NumberFormat('de-DE').format(1234567.89);
// "1.234.567,89"

new Intl.NumberFormat('fr-FR').format(1234567.89);
// "1 234 567,89"

로케일만 바꿔도 각 국가의 표기 규칙이 자동으로 적용됩니다. 직접 구현했다면 수십 줄이 필요했을 로직이 한 줄로 해결됩니다.

소수점 자릿수 조절

// 항상 소수점 2자리 표시
new Intl.NumberFormat('ko-KR', {
  minimumFractionDigits: 2,
  maximumFractionDigits: 2
}).format(1234.5);
// "1,234.50"

// 최대 3자리, 불필요한 0은 제거
new Intl.NumberFormat('ko-KR', {
  minimumFractionDigits: 0,
  maximumFractionDigits: 3
}).format(1234.5);
// "1,234.5"

천 단위 구분자 비활성화

연도나 ID 같은 경우에는 구분자가 오히려 어색합니다:

new Intl.NumberFormat('ko-KR', {
  useGrouping: false
}).format(2024);
// "2024" (2,024 아님)

통화 포맷팅

통화 표시는 Intl.NumberFormat이 정말 빛을 발하는 부분입니다. 단순히 기호만 붙이는 게 아니라 통화별로 소수점 자릿수도 다르고, 기호 위치도 다르기 때문입니다.

// 한국 원화
new Intl.NumberFormat('ko-KR', {
  style: 'currency',
  currency: 'KRW'
}).format(1234567);
// "₩1,234,567" (원화는 소수점 없음)

// 미국 달러
new Intl.NumberFormat('en-US', {
  style: 'currency',
  currency: 'USD'
}).format(1234.56);
// "$1,234.56"

// 유로 (독일식 표기)
new Intl.NumberFormat('de-DE', {
  style: 'currency',
  currency: 'EUR'
}).format(1234.56);
// "1.234,56 €"

// 일본 엔화
new Intl.NumberFormat('ja-JP', {
  style: 'currency',
  currency: 'JPY'
}).format(1234);
// "¥1,234" (엔화도 소수점 없음)

중요한 포인트: currency(통화 종류)와 로케일(표기 방식)은 서로 독립적입니다. 예를 들어 한국 사용자에게 USD 가격을 보여줄 때 한국식 구분자를 쓰면서 달러 기호를 표시할 수 있습니다:

new Intl.NumberFormat('ko-KR', {
  style: 'currency',
  currency: 'USD'
}).format(1234.56);
// "US$1,234.56"

통화 표시 방식 선택

const amount = 1234.56;

// 기호 표시 (기본값)
new Intl.NumberFormat('ko-KR', {
  style: 'currency',
  currency: 'USD',
  currencyDisplay: 'symbol'
}).format(amount);
// "US$1,234.56"

// ISO 코드 표시
new Intl.NumberFormat('ko-KR', {
  style: 'currency',
  currency: 'USD',
  currencyDisplay: 'code'
}).format(amount);
// "USD 1,234.56"

// 통화 이름 전체
new Intl.NumberFormat('ko-KR', {
  style: 'currency',
  currency: 'USD',
  currencyDisplay: 'name'
}).format(amount);
// "1,234.56 미국 달러"

currencyDisplay: 'name'을 한국어 로케일로 쓰면 "미국 달러"라고 한국어로 나오는 게 신기하더라고요. 이런 부분이 Intl API의 힘입니다.

주의사항: 원화(KRW), 엔화(JPY), 원(KRW) 같은 통화는 소수점 단위가 없습니다. currency 스타일로 이 통화들을 사용하면 소수점 자리가 표시되지 않고, 소수점이 있는 값을 넣으면 자동으로 반올림됩니다.

퍼센트 포맷팅

퍼센트 표시는 생각보다 주의할 점이 있습니다:

// 주의: 소수 형태로 전달 (0.75 = 75%)
new Intl.NumberFormat('ko-KR', {
  style: 'percent'
}).format(0.75);
// "75%"

// 소수점 자릿수 지정
new Intl.NumberFormat('ko-KR', {
  style: 'percent',
  minimumFractionDigits: 1,
  maximumFractionDigits: 1
}).format(0.7523);
// "75.2%"

흔한 실수: percent 스타일은 입력값을 100배 해서 표시합니다. 75를 넣으면 7500%가 나옵니다. 이미 퍼센트 값(75)을 가지고 있다면 반드시 100으로 나눠서 넣어야 합니다:

const percentValue = 75; // 이미 퍼센트 값
new Intl.NumberFormat('ko-KR', {
  style: 'percent'
}).format(percentValue / 100); // 100으로 나눠서 전달
// "75%"

이걸 처음에 모르고 엉뚱한 값이 나와서 당황했던 기억이 있습니다. 문서를 잘 읽자는 교훈을 얻었죠.

과학적 표기법

과학이나 공학 계산 결과를 표시할 때 유용합니다:

new Intl.NumberFormat('ko-KR', {
  notation: 'scientific'
}).format(1234567890);
// "1.235E9"

new Intl.NumberFormat('ko-KR', {
  notation: 'engineering'
}).format(1234567890);
// "1.235E9" (엔지니어링 표기는 지수를 3의 배수로 유지)

컴팩트 표기법 (만, 억 단위)

대시보드나 통계 화면에서 큰 숫자를 간결하게 표시할 때 정말 유용한 기능입니다. 특히 한국어 로케일에서는 만/억 단위를 잘 지원합니다:

// 한국어 로케일 - 만/억 단위 사용
new Intl.NumberFormat('ko-KR', {
  notation: 'compact'
}).format(10000);
// "1만"

new Intl.NumberFormat('ko-KR', {
  notation: 'compact'
}).format(35000000);
// "3500만"

new Intl.NumberFormat('ko-KR', {
  notation: 'compact'
}).format(1000000000);
// "10억"

// 영어 로케일 - K/M/B 단위 사용
new Intl.NumberFormat('en-US', {
  notation: 'compact'
}).format(1200);
// "1.2K"

// compactDisplay: 'long'으로 전체 단어 표시
new Intl.NumberFormat('ko-KR', {
  notation: 'compact',
  compactDisplay: 'long'
}).format(10000);
// "1만"

한국어에서 만/억 단위를 자동으로 처리해주는 건 꽤 편리합니다. 이걸 직접 구현하려면 생각보다 복잡하거든요.

실수하기 쉬운 부분들

NaN과 Infinity 처리:

new Intl.NumberFormat('ko-KR').format(NaN);
// "NaN"

new Intl.NumberFormat('ko-KR').format(Infinity);
// "∞"

사용자에게 NaN이나 ∞를 그대로 보여주는 건 좋지 않으니, 포맷팅 전에 유효성 검사를 하는 게 좋습니다.

성능 최적화: Intl.NumberFormat 인스턴스 생성에는 일정한 비용이 있습니다. 같은 옵션으로 많은 숫자를 포맷팅해야 한다면 인스턴스를 재사용하세요:

// 비효율적
numbers.forEach(n => new Intl.NumberFormat('ko-KR').format(n));

// 효율적
const formatter = new Intl.NumberFormat('ko-KR');
numbers.forEach(n => formatter.format(n));

formatToParts() 활용: 포맷팅된 숫자의 각 부분을 개별적으로 다루고 싶을 때 유용합니다. 예를 들어 통화 기호를 다른 색으로 표시하거나 스타일을 따로 주고 싶을 때:

new Intl.NumberFormat('ko-KR', {
  style: 'currency',
  currency: 'KRW'
}).formatToParts(1234567);
// [
//   { type: 'currency', value: '₩' },
//   { type: 'integer', value: '1' },
//   { type: 'group', value: ',' },
//   { type: 'integer', value: '234' },
//   { type: 'group', value: ',' },
//   { type: 'integer', value: '567' }
// ]

React에서 통화 기호에 특별한 스타일을 적용할 때 이 방법을 쓰면 깔끔합니다.

Intl.NumberFormat의 한계

솔직히 말하면 이 API도 완벽하지는 않습니다:

  • 숫자 파싱(역방향): Intl.NumberFormat은 숫자를 문자열로 변환하는 것은 잘 하지만, 로케일 포맷팅된 문자열을 다시 숫자로 파싱하는 기능은 없습니다. "1.234,56"1234.56으로 변환하려면 직접 구현해야 합니다.
  • 회계 형식: 음수를 (1,234.56) 형태로 표시하는 회계 스타일은 currencySign: 'accounting' 옵션으로 일부 지원하지만 완벽하지 않습니다.
  • 커스텀 포맷 문자열: Excel의 #,##0.00 같은 커스텀 포맷은 지원하지 않습니다. 이런 게 필요하다면 numeral.js 같은 라이브러리를 쓰는 게 낫습니다.

하지만 일반적인 웹 서비스에서 필요한 대부분의 경우는 Intl.NumberFormat으로 충분히 커버됩니다.

Number Formatter 도구 활용하기

코드 작성 없이 다양한 포맷팅 옵션을 직접 확인하고 싶다면 ToolBox Hub의 Number Formatter 도구를 이용해보세요.

  1. 포맷팅할 숫자를 입력합니다
  2. 로케일을 선택합니다 (한국어, 영어, 독일어 등 30개 이상 지원)
  3. 스타일을 선택합니다 (decimal, currency, percent, scientific)
  4. 통화를 선택하면 해당 통화 기호로 표시됩니다
  5. 소수점 자릿수를 설정합니다
  6. 천 단위 구분자 사용 여부를 선택합니다
  7. 결과를 즉시 확인하고 코드를 복사할 수 있습니다

낯선 로케일에서 숫자가 어떻게 보이는지 미리 확인할 때 유용합니다.

관련 도구

숫자 처리와 관련해서 함께 사용하면 유용한 도구들:

마치며

Intl.NumberFormat은 JavaScript 표준 라이브러리 중에서 꽤 잘 만들어진 API라고 생각합니다. 처음에는 단순해 보이지만 currency, percent, compact notation 등 파고들수록 유용한 기능이 많습니다.

핵심 정리:

  • 로케일별 숫자 포맷팅은 반드시 Intl.NumberFormat을 쓰자
  • 통화 코드와 로케일은 독립적으로 설정 가능
  • percent 스타일은 100을 곱하므로 소수 형태로 전달
  • compact 표기법에서 한국어는 만/억 단위 자동 지원
  • 같은 설정으로 반복 포맷팅 시에는 인스턴스를 재사용

사용자에게 보여주는 숫자 하나하나에 신경을 쓰면 서비스 전체의 완성도가 올라갑니다. 작은 차이지만 사용자는 분명 알아챕니다.

자주 묻는 질문

이 글 공유하기

XLinkedIn

관련 글