JavaScript에서 숫자를 소수점 이하 2자리로 포맷하는 방법

가격, 백분율 및 측정값에 대해 정확히 소수점 이하 2자리로 숫자 표시하기

소개

많은 애플리케이션에서는 고정된 소수점 자릿수로 숫자를 표시해야 합니다. 가격은 일반적으로 $19.99와 같이 소수점 두 자리로 표시됩니다. 백분율은 종종 45.50%로 표시됩니다. 측정값은 가독성을 위해 3.14 미터와 같이 일관된 소수점 자릿수를 사용합니다.

소수점 자릿수를 제어하면 애플리케이션 전체에서 시각적 일관성을 보장할 수 있습니다. 명시적인 형식 지정 없이는 JavaScript가 실제 값에 따라 다양한 소수점 자릿수로 숫자를 표시합니다. 숫자 5는 "5"로 표시되는 반면 5.5는 "5.5"로 표시되어 정렬과 외관이 일관되지 않게 됩니다.

이 강의에서는 다양한 로케일 규칙을 존중하면서 숫자를 정확히 소수점 2자리 또는 최대 소수점 2자리까지 형식화하는 방법을 보여줍니다.

기본 형식 지정을 위한 toFixed() 사용

toFixed() 메서드는 숫자를 지정된 소수점 자릿수를 가진 문자열로 변환합니다. 소수점 자릿수를 인수로 전달합니다.

const price = 19.9;
const formatted = price.toFixed(2);
console.log(formatted);
// 출력: "19.90"

이 메서드는 항상 정확히 2개의 소수점 자릿수를 표시합니다. 숫자의 소수점 자릿수가 더 적으면 toFixed()는 0으로 채웁니다. 소수점 자릿수가 더 많으면 메서드는 2자리로 반올림합니다.

const examples = [5, 5.5, 5.555, 5.999];

examples.forEach(num => {
  console.log(num.toFixed(2));
});
// 출력:
// "5.00"
// "5.50"
// "5.56"
// "6.00"

toFixed() 메서드는 숫자가 아닌 문자열을 반환합니다. 이는 의도적인 것으로, 표시에 의미가 있는 후행 0이 숫자로 반환되면 손실되기 때문입니다.

toFixed()의 로케일 문제

toFixed() 메서드는 사용자의 로케일에 관계없이 항상 소수점 구분 기호로 마침표를 사용합니다. 많은 국가에서는 마침표 대신 쉼표를 소수점 구분 기호로 사용합니다.

const price = 19.99;
console.log(price.toFixed(2));
// 출력: "19.99" (항상 마침표 사용)

독일, 프랑스, 스페인 및 기타 많은 국가의 사용자에게는 이것이 잘못된 것처럼 보입니다. 그들은 "19.99" 대신 "19,99"를 보기를 기대합니다. toFixed() 메서드는 로케일에 적합한 출력을 생성할 수 없습니다.

다양한 로케일에 맞게 숫자를 올바르게 형식화하려면 Intl.NumberFormat API를 사용하세요.

로케일 인식 형식화를 위한 Intl.NumberFormat 사용

'Intl.NumberFormat' API는 로케일 규칙에 따라 숫자를 형식화합니다. 로케일과 옵션으로 포맷터를 생성한 다음, 숫자와 함께 'format()' 메서드를 호출하세요.

const formatter = new Intl.NumberFormat("de-DE", {
  minimumFractionDigits: 2,
  maximumFractionDigits: 2
});

const price = 19.99;
console.log(formatter.format(price));
// 출력: "19,99" (독일 로케일에서는 쉼표 사용)

동일한 포맷터는 다른 로케일에 대해 다른 출력을 생성합니다.

const price = 19.99;

const usFormatter = new Intl.NumberFormat("en-US", {
  minimumFractionDigits: 2,
  maximumFractionDigits: 2
});

const deFormatter = new Intl.NumberFormat("de-DE", {
  minimumFractionDigits: 2,
  maximumFractionDigits: 2
});

console.log(usFormatter.format(price));
// 출력: "19.99"

console.log(deFormatter.format(price));
// 출력: "19,99"

소수점 구분 기호는 로케일에 따라 자동으로 변경됩니다.

정확히 소수점 이하 2자리로 형식화하기

정확히 소수점 이하 2자리를 표시하려면 'minimumFractionDigits'와 'maximumFractionDigits'를 모두 2로 설정하세요. 이렇게 하면 출력이 항상 소수점 이하 2자리를 가지며, 필요할 때 0으로 채우고 숫자의 정밀도가 더 높을 때는 반올림합니다.

const formatter = new Intl.NumberFormat("en-US", {
  minimumFractionDigits: 2,
  maximumFractionDigits: 2
});

console.log(formatter.format(5));
// 출력: "5.00"

console.log(formatter.format(5.5));
// 출력: "5.50"

console.log(formatter.format(5.555));
// 출력: "5.56"

'minimumFractionDigits' 옵션은 후행 0을 제어합니다. 이 옵션이 없으면 소수 자릿수가 적은 숫자는 0을 표시하지 않습니다.

const withoutMinimum = new Intl.NumberFormat("en-US", {
  maximumFractionDigits: 2
});

console.log(withoutMinimum.format(5));
// 출력: "5"

const withMinimum = new Intl.NumberFormat("en-US", {
  minimumFractionDigits: 2,
  maximumFractionDigits: 2
});

console.log(withMinimum.format(5));
// 출력: "5.00"

두 옵션을 동일한 값으로 설정하면 모든 숫자에서 일관된 소수 자릿수를 보장합니다.

최대 소수점 이하 2자리까지 형식화하기

때로는 필요할 때만 소수 자릿수를 표시하고 최대 2자리까지만 표시하고 싶을 수 있습니다. 'maximumFractionDigits'를 2로 설정하고 'minimumFractionDigits'를 0으로 설정하거나 완전히 생략하세요.

const formatter = new Intl.NumberFormat("en-US", {
  minimumFractionDigits: 0,
  maximumFractionDigits: 2
});

console.log(formatter.format(5));
// 출력: "5"

console.log(formatter.format(5.5));
// 출력: "5.5"

console.log(formatter.format(5.555));
// 출력: "5.56"

이 방식은 후행 0을 제거하지만 여전히 정밀도를 소수점 이하 2자리로 제한합니다. 후행 0이 정보를 추가하지 않는 측정값이나 통계를 표시할 때 잘 작동합니다.

일반 숫자 형식화의 경우 'minimumFractionDigits'의 기본값은 0이므로 생략할 수 있습니다.

const formatter = new Intl.NumberFormat("en-US", {
  maximumFractionDigits: 2
});

console.log(formatter.format(5));
// 출력: "5"

console.log(formatter.format(5.5));
// 출력: "5.5"

더 나은 성능을 위한 포매터 재사용

새로운 Intl.NumberFormat 인스턴스를 생성하는 것은 상대적으로 비용이 많이 듭니다. 동일한 옵션으로 여러 숫자를 포맷팅하는 경우, 포매터를 한 번 생성하고 재사용하세요.

const formatter = new Intl.NumberFormat("en-US", {
  minimumFractionDigits: 2,
  maximumFractionDigits: 2
});

const prices = [19.99, 29.5, 99, 149.999];

prices.forEach(price => {
  console.log(formatter.format(price));
});
// 출력:
// "19.99"
// "29.50"
// "99.00"
// "150.00"

이 패턴은 각 숫자마다 새 포매터를 생성하는 것보다 더 효율적입니다.

각 접근 방식을 사용해야 하는 경우

가격, 통화 금액 또는 소수점 자리가 의미적 중요성을 갖는 값을 표시할 때는 정확히 소수점 이하 2자리를 사용하세요. "$5" 대신 "$5.00"을 표시하면 정밀도를 나타내고 사용자가 가격에 대해 기대하는 형식과 일치합니다.

통계, 측정값 또는 후행 0이 정보를 추가하지 않는 계산된 값을 표시할 때는 최대 소수점 이하 2자리까지 사용하세요. "5.00 meters" 대신 "5 meters"를 표시하는 것이 더 깔끔하고 가독성이 좋습니다.

toFixed()는 모든 사용자가 동일한 소수점 구분 기호 규칙을 사용하거나 출력이 사용자 대면용이 아닌 경우에만 사용하세요. 국제화된 애플리케이션의 경우 Intl.NumberFormat을 선호하세요.

사용자가 선호하는 로케일 사용하기

로케일을 하드코딩하는 대신 사용자의 브라우저 언어 환경설정을 사용하세요. navigator.language 속성은 사용자가 선호하는 로케일을 제공합니다.

const formatter = new Intl.NumberFormat(navigator.language, {
  minimumFractionDigits: 2,
  maximumFractionDigits: 2
});

const price = 19.99;
console.log(formatter.format(price));
// 출력은 사용자의 로케일에 따라 다름
// en-US의 경우: "19.99"
// de-DE의 경우: "19,99"
// fr-FR의 경우: "19,99"

전체 navigator.languages 배열을 전달하여 Intl API가 사용자 환경설정에서 지원되는 첫 번째 로케일을 선택하도록 할 수도 있습니다.

const formatter = new Intl.NumberFormat(navigator.languages, {
  minimumFractionDigits: 2,
  maximumFractionDigits: 2
});

이 접근 방식은 사용자의 첫 번째 선호도가 지원되지 않을 경우 자동 대체를 제공합니다.