TanStack Start v1에서 다양한 로케일에 맞게 숫자 형식을 지정하는 방법
로케일별 구분 기호로 숫자 표시
문제
숫자는 전 세계적으로 다르게 표기됩니다. 미국에서 10,000.5로 표시되는 숫자가 독일에서는 10.000,5가 되며, 쉼표와 마침표의 역할이 완전히 바뀝니다. 이것은 선호도나 스타일의 문제가 아니라 가독성의 문제입니다. 독일 사용자가 10,000.5를 보면 그룹 구분 기호를 무시하고 10으로 읽을 수 있습니다. 미국 사용자가 10.000,5를 보면 소수점 구분 기호를 무시하고 만으로 읽을 수 있습니다. 같은 숫자이지만 정반대의 의미입니다.
애플리케이션이 지역별 형식 규칙을 고려하지 않고 숫자를 표시하면 혼란을 야기하고 신뢰를 떨어뜨립니다. 사용자는 숫자가 they가 학습한 패턴을 따르기를 기대하며, 이러한 패턴에서 벗어나면 사용자는 멈춰서 재해석하고 데이터가 올바른지 의문을 갖게 됩니다.
솔루션
사용자의 로케일을 기반으로 숫자 형식을 지정하고, 소수점 및 그룹 구분 기호에 대한 지역별 규칙을 사용합니다. 이를 통해 숫자 값을 해당 지역 사용자에게 익숙한 형식 규칙을 따르는 문자열로 변환합니다.
React-intl은 브라우저에 내장된 Intl.NumberFormat API를 활용하여 로케일별 형식을 적용하는 컴포넌트와 훅을 제공합니다. 숫자 값과 현재 로케일을 전달하면 이러한 도구가 자동으로 올바른 구분 기호, 숫자 그룹화 및 기타 지역 규칙을 선택합니다. 그 결과 컴포넌트에서 수동 문자열 조작이나 로케일별 로직 없이도 사용자 기대에 부합하는 형식화된 문자열을 얻을 수 있습니다.
단계
1. FormattedNumber를 사용하여 숫자 표시 컴포넌트 생성
숫자 값을 받아 react-intl의 FormattedNumber 컴포넌트를 사용하여 로케일에 적합한 형식으로 렌더링하는 컴포넌트를 구축하세요.
import { FormattedNumber } from "react-intl";
interface PriceDisplayProps {
value: number;
}
export function PriceDisplay({ value }: PriceDisplayProps) {
return (
<div>
<FormattedNumber value={value} />
</div>
);
}
FormattedNumber 컴포넌트는 로케일의 소수점 및 그룹화 구분 기호를 자동으로 적용합니다. 컴포넌트 트리에서 가장 가까운 IntlProvider로부터 로케일을 읽어 그에 따라 숫자를 형식화합니다.
2. 특정 스타일로 숫자 형식화
통화, 백분율 또는 단위에 대한 스타일 옵션을 FormattedNumber에 전달하여 숫자 형식을 사용자 정의하세요.
import { FormattedNumber } from "react-intl";
interface MetricsProps {
revenue: number;
growthRate: number;
fileSize: number;
}
export function Metrics({ revenue, growthRate, fileSize }: MetricsProps) {
return (
<div>
<p>
Revenue:{" "}
<FormattedNumber value={revenue} style="currency" currency="USD" />
</p>
<p>
Growth: <FormattedNumber value={growthRate} style="percent" />
</p>
<p>
Size:{" "}
<FormattedNumber
value={fileSize}
style="unit"
unit="megabyte"
unitDisplay="short"
/>
</p>
</div>
);
}
style 속성은 형식화 모드를 제어합니다. 통화 형식에는 currency 코드가 필요하고, 백분율 형식은 자동으로 100을 곱하며, 단위 형식에는 unit 식별자가 필요합니다. 모든 스타일은 활성 로케일의 규칙을 준수합니다.
3. useIntl로 명령형 숫자 형식화
동적 속성 생성이나 비React API용 데이터 준비와 같이 컴포넌트가 적합하지 않은 컨텍스트에서 숫자를 형식화하려면 useIntl 훅을 사용하세요.
import { useIntl } from "react-intl";
interface ChartTooltipProps {
dataPoint: number;
}
export function ChartTooltip({ dataPoint }: ChartTooltipProps) {
const intl = useIntl();
const formattedValue = intl.formatNumber(dataPoint, {
minimumFractionDigits: 2,
maximumFractionDigits: 2,
});
return <div title={formattedValue}>{formattedValue}</div>;
}
formatNumber 메서드는 형식화된 문자열을 즉시 반환하므로 속성, aria 레이블 또는 React 요소가 아닌 문자열로 형식화된 값이 필요한 모든 컨텍스트에 적합합니다.
4. 사용자 정의 형식화 옵션 적용
FormattedNumber 또는 formatNumber에 Intl.NumberFormatOptions를 전달하여 정밀도, 그룹화 및 표기법을 제어하세요.
import { FormattedNumber } from "react-intl";
interface StatisticProps {
value: number;
compact?: boolean;
}
export function Statistic({ value, compact }: StatisticProps) {
return (
<div>
<FormattedNumber
value={value}
notation={compact ? "compact" : "standard"}
minimumFractionDigits={0}
maximumFractionDigits={2}
/>
</div>
);
}
notation, minimumFractionDigits, maximumFractionDigits와 같은 옵션은 숫자가 표시되는 방식을 제어합니다. 간결한 표기법은 큰 숫자를 "1.2M"과 같은 축약된 형태로 변환하며 로케일별 축약어를 준수합니다.