TanStack Start v1에서 통화 금액을 포맷하는 방법

통화 기호와 구분 기호를 사용하여 가격 표시

문제

가격은 두 가지 현지화 과제를 결합합니다: 통화 표현과 숫자 형식. 동일한 금액이 미국에서는 $1,200.50으로, 독일에서는 1 200,50 €로 표시됩니다. 통화 기호의 위치가 바뀌고, 소수점과 천 단위 구분 기호가 바뀌며, 심지어 간격도 변경됩니다.

이러한 관행은 선호도가 아닌 기대치입니다. 익숙하지 않은 형식으로 가격을 표시하면 사용자는 올바른 금액을 보고 있는지 의문을 갖게 됩니다. 독일 사용자에게 "1200.50 EUR"로 표시되거나 미국 사용자에게 "1.200,50$"로 표시되는 가격은 마찰을 일으키고 신뢰를 약화시킵니다.

해결책

통화와 사용자의 로케일을 모두 기반으로 금액을 형식화합니다. 이는 통화 기호 배치와 로케일별 숫자 형식 규칙을 결합하여 돈이 어떻게 보여야 하는지에 대한 지역적 기대치와 일치하는 가격을 만듭니다.

react-intl의 formatNumber 메서드를 style: 'currency' 옵션과 함께 사용하여 통화 코드와 사용자의 로케일 형식 규칙을 모두 적용합니다. 브라우저의 Intl.NumberFormat API는 기호 배치, 구분 기호 선택 및 간격을 자동으로 처리합니다.

단계

1. 통화 형식 컴포넌트 만들기

숫자 값과 통화 코드를 받아 사용자의 로케일을 사용하여 가격을 형식화하는 재사용 가능한 컴포넌트를 구축합니다.

import { useIntl } from "react-intl";

interface PriceProps {
  value: number;
  currency: string;
}

export function Price({ value, currency }: PriceProps) {
  const intl = useIntl();

  const formattedPrice = intl.formatNumber(value, {
    style: "currency",
    currency: currency,
  });

  return <span>{formattedPrice}</span>;
}

useIntl 훅은 형식화 API에 대한 접근을 제공합니다. style: 'currency'와 함께 사용하는 formatNumber 메서드는 통화 기호와 로케일별 숫자 형식을 모두 적용합니다.

2. 다양한 통화로 컴포넌트 사용하기

숫자 금액과 통화 코드를 전달하여 애플리케이션 전체에 가격을 표시합니다.

export default function ProductCard() {
  return (
    <div>
      <h2>프리미엄 플랜</h2>
      <Price value={1200.5} currency="USD" />
    </div>
  );
}

이 컴포넌트는 사용자의 로케일에 따라 가격을 자동으로 포맷합니다. 미국 사용자는 "$1,200.50"을 보게 되고 독일 사용자는 "1.200,50 $"를 보게 됩니다.

3. 사용자 지정 소수점 정밀도로 가격 포맷하기

minimumFractionDigitsmaximumFractionDigits 옵션을 추가하여 표시되는 소수점 자릿수를 제어합니다.

export function PriceWithPrecision({ value, currency }: PriceProps) {
  const intl = useIntl();

  const formattedPrice = intl.formatNumber(value, {
    style: "currency",
    currency: currency,
    minimumFractionDigits: 2,
    maximumFractionDigits: 2,
  });

  return <span>{formattedPrice}</span>;
}

이렇게 하면 값이 100과 같은 정수인 경우에도 모든 가격에서 소수점 표시가 일관되게 유지됩니다.

4. 인라인 포맷팅을 위한 헬퍼 만들기

컴포넌트 래퍼가 필요하지 않은 경우를 위해 포맷팅 헬퍼 함수를 만듭니다.

import { useIntl } from "react-intl";

export function useFormatCurrency() {
  const intl = useIntl();

  return (value: number, currency: string) => {
    return intl.formatNumber(value, {
      style: "currency",
      currency: currency,
    });
  };
}

속성, 계산된 값 또는 기타 JSX가 아닌 컨텍스트에서 포맷된 가격이 필요할 때 이 훅을 사용합니다.

export function CheckoutSummary({ total }: { total: number }) {
  const formatCurrency = useFormatCurrency();

  return (
    <button aria-label={`Pay ${formatCurrency(total, "USD")}`}>Checkout</button>
  );
}

이 헬퍼는 JSX 컴포넌트를 사용할 수 없는 모든 컨텍스트에 적합한 일반 문자열을 반환합니다.