JavaScript 숫자 포맷팅 완벽 가이드: Intl.NumberFormat으로 다국어 숫자 표시하기
📷 Antoine Dautry / PexelsJavaScript 숫자 포맷팅 완벽 가이드: Intl.NumberFormat으로 다국어 숫자 표시하기
국제화를 위한 숫자 포맷팅 마스터하기. JavaScript Intl.NumberFormat으로 통화, 퍼센트, 로케일별 숫자 표시 방법을 알아보세요.
웹 개발을 하다 보면 숫자를 화면에 표시하는 일이 생각보다 복잡하다는 걸 느낄 때가 있습니다. 저도 처음에는 단순히 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 도구를 이용해보세요.
- 포맷팅할 숫자를 입력합니다
- 로케일을 선택합니다 (한국어, 영어, 독일어 등 30개 이상 지원)
- 스타일을 선택합니다 (decimal, currency, percent, scientific)
- 통화를 선택하면 해당 통화 기호로 표시됩니다
- 소수점 자릿수를 설정합니다
- 천 단위 구분자 사용 여부를 선택합니다
- 결과를 즉시 확인하고 코드를 복사할 수 있습니다
낯선 로케일에서 숫자가 어떻게 보이는지 미리 확인할 때 유용합니다.
관련 도구
숫자 처리와 관련해서 함께 사용하면 유용한 도구들:
마치며
Intl.NumberFormat은 JavaScript 표준 라이브러리 중에서 꽤 잘 만들어진 API라고 생각합니다. 처음에는 단순해 보이지만 currency, percent, compact notation 등 파고들수록 유용한 기능이 많습니다.
핵심 정리:
- 로케일별 숫자 포맷팅은 반드시
Intl.NumberFormat을 쓰자 - 통화 코드와 로케일은 독립적으로 설정 가능
percent스타일은 100을 곱하므로 소수 형태로 전달compact표기법에서 한국어는 만/억 단위 자동 지원- 같은 설정으로 반복 포맷팅 시에는 인스턴스를 재사용
사용자에게 보여주는 숫자 하나하나에 신경을 쓰면 서비스 전체의 완성도가 올라갑니다. 작은 차이지만 사용자는 분명 알아챕니다.