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에 접근할 수 있습니다. formatNumber 메서드와 style: 'currency' 옵션으로 통화 기호와 로케일 특화 숫자 포맷이 적용됩니다.

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

앱 전반에 걸쳐, 숫자 금액과 통화 코드를 넘겨주며 가격을 표시하세요.

export default function ProductCard() {
  return (
    <div>
      <h2>Premium Plan</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 컴포넌트를 사용할 수 없는 어떤 상황에서도 쓸 수 있는 순수 문자열을 반환합니다.