Next.js(Pages Router) v16에서 통화 금액을 포맷하는 방법

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

문제

통화 값을 표시하려면 두 가지 별개의 현지화 문제를 조정해야 합니다: 통화 자체와 사용자 지역의 숫자 형식 규칙입니다. 1200.50의 가격은 미국 영어 사용자에게는 "$1,200.50"으로 표시되어야 하지만 독일 사용자에게는 "1 200,50 €"로 표시되어야 합니다. 통화 기호 위치, 소수점 구분 기호, 천 단위 구분 기호 및 간격은 모두 로케일에 따라 다릅니다. 이러한 요소가 잘못 정렬되거나 하드코딩되면 사용자는 표시된 금액이 정확한지에 대한 의심을 불러일으키는 익숙하지 않은 형식을 보게 되어 가격 정보에 대한 신뢰를 훼손합니다.

시각적 일관성을 넘어서, 잘못된 통화 형식은 실제 혼란을 야기할 수 있습니다. 천 단위 구분 기호로 쉼표에 익숙한 사용자는 "1.200"을 천이백이 아닌 일점이로 잘못 읽을 수 있습니다. 마찬가지로, 잘못 배치된 통화 기호는 가격이 비전문적으로 보이거나 완전히 다른 통화를 암시할 수 있습니다. 적절한 통화 형식은 통화 코드와 사용자의 로케일별 숫자 규칙을 모두 존중하여 가격이 즉시 명확하고 신뢰할 수 있도록 합니다.

해결책

ISO 4217 통화 코드와 사용자의 활성 로케일을 결합하여 지역에 적합한 숫자 형식을 생성하는 방식으로 통화 값을 형식화합니다. 이 접근 방식은 기호 배치, 구분 기호 선택 및 간격 규칙을 국제화 라이브러리에 위임하여 각 로케일-통화 쌍에 대해 올바른 규칙을 적용합니다. 그 결과 애플리케이션 코드에서 수동 문자열 조작이나 로케일별 로직 없이 사용자 기대에 맞는 가격 표시가 가능합니다.

단계

1. 재사용 가능한 통화 형식 컴포넌트 만들기

숫자 값과 통화 코드를 받아 react-intl의 컨텍스트에서 현재 로케일을 사용하여 가격을 형식화하는 컴포넌트를 구축합니다.

import { FormattedNumber } from "react-intl";

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

export default function Price({ value, currency }: PriceProps) {
  return <FormattedNumber value={value} style="currency" currency={currency} />;
}

FormattedNumber 컴포넌트는 가장 가까운 IntlProvider에서 로케일을 읽고 통화 기호와 로케일별 숫자 형식 규칙을 자동으로 적용합니다.

2. 동적 가격 데이터가 있는 페이지에서 컴포넌트 사용하기

숫자 금액과 통화 코드를 컴포넌트에 전달하여 가격을 렌더링하면 사용자의 로케일에 맞게 형식이 조정됩니다.

import { GetServerSideProps } from "next";
import Price from "../components/Price";

interface Product {
  id: string;
  name: string;
  price: number;
  currency: string;
}

interface ProductPageProps {
  product: Product;
}

export default function ProductPage({ product }: ProductPageProps) {
  return (
    <div>
      <h1>{product.name}</h1>
      <p>
        <Price value={product.price} currency={product.currency} />
      </p>
    </div>
  );
}

export const getServerSideProps: GetServerSideProps = async () => {
  const product = {
    id: "1",
    name: "Wireless Headphones",
    price: 1299.99,
    currency: "USD",
  };

  return {
    props: {
      product,
    },
  };
};

이 페이지는 통화 코드를 포함한 제품 데이터를 가져와 Price 컴포넌트에 전달하며, 컴포넌트는 활성 로케일에 따라 금액 형식을 지정합니다.

3. 명령형 통화 형식 지정을 위한 헬퍼 생성하기

React 컴포넌트를 사용할 수 없는 시나리오(예: 속성 설정 또는 JSX가 아닌 컨텍스트용 데이터 준비)의 경우, useIntl 훅을 사용하여 형식 지정 함수를 노출합니다.

import { useIntl } from "react-intl";

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

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

이 훅은 통화 값을 문자열로 형식화하는 함수를 반환하며, aria 레이블, 메타 태그 또는 컴포넌트가 적합하지 않은 텍스트 전용 컨텍스트에 유용합니다.

4. 속성 컨텍스트에 포맷터 적용하기

React 요소가 아닌 일반 텍스트가 필요한 HTML 속성을 채우기 위해 명령형 포맷터를 사용합니다.

import { useCurrencyFormatter } from "../hooks/useCurrencyFormatter";

interface ProductCardProps {
  name: string;
  price: number;
  currency: string;
  imageUrl: string;
}

export default function ProductCard({
  name,
  price,
  currency,
  imageUrl,
}: ProductCardProps) {
  const formatCurrency = useCurrencyFormatter();
  const priceLabel = formatCurrency(price, currency);

  return (
    <article aria-label={`${name}, ${priceLabel}`}>
      <img src={imageUrl} alt={name} />
      <h2>{name}</h2>
      <p>{priceLabel}</p>
    </article>
  );
}

포맷터는 aria-label 속성에 포함될 수 있는 지역화된 통화 문자열을 생성하여 보조 기술이 사용자의 로케일에 맞는 올바른 형식으로 가격을 발표하도록 보장합니다.