단위가 있는 측정값 목록을 어떻게 형식화하나요?
JavaScript의 Intl API를 사용하여 5 km, 10 km, 15 km와 같은 여러 측정값을 로케일에 적합한 목록 형식으로 표시하세요
소개
측정값을 표시하는 애플리케이션은 종종 여러 값을 함께 표시해야 합니다. 피트니스 앱은 구간 기록을 "5 km, 10 km, 15 km"로 표시할 수 있습니다. 날씨 앱은 일주일 동안의 온도를 "20°C, 22°C, 25°C, 23°C"로 표시할 수 있습니다. 레시피는 재료 양을 "2컵, 1테이블스푼, 3티스푼"으로 나열할 수 있습니다.
이러한 목록은 두 가지 국제화 과제를 결합합니다. 첫째, 각 측정값은 로케일에 적합한 단위 형식이 필요합니다. 둘째, 목록 자체는 대상 언어에 적합한 구두점과 구분 기호가 필요합니다. 영어는 쉼표와 때로는 "and"와 같은 접속사를 사용합니다. 다른 언어는 다른 구분 기호를 사용하고 다른 문법 규칙을 따릅니다.
JavaScript는 이 문제를 해결하기 위해 두 가지 API를 제공합니다. Intl.NumberFormat는 단위가 포함된 개별 측정값을 형식화합니다. Intl.ListFormat는 여러 값을 문법적으로 올바른 목록으로 결합합니다. 이 레슨에서는 두 API를 함께 사용하여 모든 로케일에서 사용자 기대에 부합하는 측정값 목록을 형식화하는 방법을 설명합니다.
측정값 목록에는 두 가지 형식화 단계가 필요합니다
측정값 목록을 형식화할 때 두 형식화 단계 중 어느 것도 건너뛸 수 없습니다. 측정값을 형식화하지 않고 목록을 형식화하면 로케일에 적합한 구분 기호를 얻지만 단위 표시가 올바르지 않습니다. 목록을 형식화하지 않고 측정값을 형식화하면 올바른 단위를 얻지만 구분 기호가 올바르지 않습니다.
const distances = [5, 10, 15];
// Wrong: list formatted but not measurements
console.log(distances.join(', '));
// Output: "5, 10, 15" (missing units)
// Wrong: measurements formatted but not list
const formatter = new Intl.NumberFormat('en-US', {
style: 'unit',
unit: 'kilometer'
});
console.log(distances.map(d => formatter.format(d)).join(', '));
// Output: "5 km, 10 km, 15 km" (hardcoded comma might be wrong for some locales)
올바른 접근 방식은 먼저 측정값을 형식화한 다음 결과 문자열 배열을 목록으로 형식화하는 것입니다.
const distances = [5, 10, 15];
const numberFormatter = new Intl.NumberFormat('en-US', {
style: 'unit',
unit: 'kilometer'
});
const formattedMeasurements = distances.map(d => numberFormatter.format(d));
// Result: ["5 km", "10 km", "15 km"]
const listFormatter = new Intl.ListFormat('en-US', {
type: 'unit'
});
console.log(listFormatter.format(formattedMeasurements));
// Output: "5 km, 10 km, 15 km"
이 패턴은 모든 측정 유형과 모든 로케일에서 작동합니다. 각 측정값을 단위와 함께 형식화한 다음 형식화된 문자열 배열을 목록으로 형식화합니다.
측정 목록에 unit 타입 사용
Intl.ListFormat 생성자는 목록 항목이 결합되는 방식을 제어하는 type 옵션을 허용합니다. type: 'unit' 옵션은 기술 및 과학 데이터에 대한 규칙에 따라 목록을 형식화합니다.
const measurements = ['5 km', '10 km', '15 km'];
const unitList = new Intl.ListFormat('en-US', {
type: 'unit'
});
console.log(unitList.format(measurements));
// Output: "5 km, 10 km, 15 km"
type: 'unit'가 적용된 목록은 "and" 또는 "or"와 같은 접속사를 생략합니다. 항목 사이에 단순한 구분 기호를 사용합니다. 이는 기술적 맥락에서 측정값이 일반적으로 작성되는 방식과 일치합니다.
이를 마지막 항목 앞에 "and"를 추가하는 type: 'conjunction'와 비교해 보세요.
const measurements = ['5 km', '10 km', '15 km'];
const conjunctionList = new Intl.ListFormat('en-US', {
type: 'conjunction'
});
console.log(conjunctionList.format(measurements));
// Output: "5 km, 10 km, and 15 km"
접속사 형식은 산문에서는 자연스럽게 읽히지만 기술적 맥락에서는 부정확해 보입니다. 여러 측정값을 표시할 때는 type: 'unit'를 사용하여 과학 및 기술 문서 작성의 표준 규칙을 따르세요.
목록에서 거리 측정값 형식화
거리 측정은 kilometer, meter, mile, foot와 같은 단위 식별자를 사용합니다. 각 거리를 단위와 함께 형식화한 후 목록으로 결합합니다.
const distances = [5, 10, 15, 20];
const numberFormatter = new Intl.NumberFormat('en-US', {
style: 'unit',
unit: 'kilometer'
});
const formattedDistances = distances.map(d => numberFormatter.format(d));
const listFormatter = new Intl.ListFormat('en-US', {
type: 'unit'
});
console.log(listFormatter.format(formattedDistances));
// Output: "5 km, 10 km, 15 km, 20 km"
마일에도 동일한 패턴이 적용됩니다.
const distances = [3, 6, 9];
const numberFormatter = new Intl.NumberFormat('en-US', {
style: 'unit',
unit: 'mile'
});
const formattedDistances = distances.map(d => numberFormatter.format(d));
const listFormatter = new Intl.ListFormat('en-US', {
type: 'unit'
});
console.log(listFormatter.format(formattedDistances));
// Output: "3 mi, 6 mi, 9 mi"
숫자 형식화 옵션을 설정하여 소수점 이하 자릿수가 있는 거리를 형식화할 수 있습니다.
const distances = [5.2, 10.7, 15.3];
const numberFormatter = new Intl.NumberFormat('en-US', {
style: 'unit',
unit: 'kilometer',
maximumFractionDigits: 1
});
const formattedDistances = distances.map(d => numberFormatter.format(d));
const listFormatter = new Intl.ListFormat('en-US', {
type: 'unit'
});
console.log(listFormatter.format(formattedDistances));
// Output: "5.2 km, 10.7 km, 15.3 km"
숫자 포맷터는 목록 포맷터가 값을 결합하기 전에 반올림 및 소수점 이하 자릿수를 처리합니다.
목록에서 무게 측정값 형식화
무게 측정은 kilogram, pound, ounce, gram와 같은 단위 식별자를 사용하여 동일한 패턴을 따릅니다.
const weights = [50, 75, 100];
const numberFormatter = new Intl.NumberFormat('en-US', {
style: 'unit',
unit: 'kilogram'
});
const formattedWeights = weights.map(w => numberFormatter.format(w));
const listFormatter = new Intl.ListFormat('en-US', {
type: 'unit'
});
console.log(listFormatter.format(formattedWeights));
// Output: "50 kg, 75 kg, 100 kg"
대신 파운드 단위로 무게를 표시할 수 있습니다.
const weights = [110, 165, 220];
const numberFormatter = new Intl.NumberFormat('en-US', {
style: 'unit',
unit: 'pound'
});
const formattedWeights = weights.map(w => numberFormatter.format(w));
const listFormatter = new Intl.ListFormat('en-US', {
type: 'unit'
});
console.log(listFormatter.format(formattedWeights));
// Output: "110 lb, 165 lb, 220 lb"
숫자 포맷터는 각 단위에 대해 올바른 약어를 자동으로 사용합니다.
목록에서 온도 측정값 형식화
온도 측정은 celsius 및 fahrenheit와 같은 단위 식별자를 사용합니다.
const temperatures = [20, 22, 25, 23, 21];
const numberFormatter = new Intl.NumberFormat('en-US', {
style: 'unit',
unit: 'celsius'
});
const formattedTemperatures = temperatures.map(t => numberFormatter.format(t));
const listFormatter = new Intl.ListFormat('en-US', {
type: 'unit'
});
console.log(listFormatter.format(formattedTemperatures));
// Output: "20°C, 22°C, 25°C, 23°C, 21°C"
온도 포맷터는 출력에 도 기호를 자동으로 포함합니다.
화씨도 동일한 방식으로 작동합니다.
const temperatures = [68, 72, 77, 73, 70];
const numberFormatter = new Intl.NumberFormat('en-US', {
style: 'unit',
unit: 'fahrenheit'
});
const formattedTemperatures = temperatures.map(t => numberFormatter.format(t));
const listFormatter = new Intl.ListFormat('en-US', {
type: 'unit'
});
console.log(listFormatter.format(formattedTemperatures));
// Output: "68°F, 72°F, 77°F, 73°F, 70°F"
패턴은 다양한 측정 유형에서 동일하게 유지됩니다. 단위 식별자만 변경됩니다.
목록에서 부피 측정값 형식 지정
부피 측정은 liter, gallon, milliliter, fluid-ounce와 같은 단위 식별자를 사용합니다.
const volumes = [1, 2, 3];
const numberFormatter = new Intl.NumberFormat('en-US', {
style: 'unit',
unit: 'liter'
});
const formattedVolumes = volumes.map(v => numberFormatter.format(v));
const listFormatter = new Intl.ListFormat('en-US', {
type: 'unit'
});
console.log(listFormatter.format(formattedVolumes));
// Output: "1 L, 2 L, 3 L"
부피 측정은 소수점 값과 함께 작동합니다.
const volumes = [0.5, 1.5, 2.5];
const numberFormatter = new Intl.NumberFormat('en-US', {
style: 'unit',
unit: 'liter',
maximumFractionDigits: 1
});
const formattedVolumes = volumes.map(v => numberFormatter.format(v));
const listFormatter = new Intl.ListFormat('en-US', {
type: 'unit'
});
console.log(listFormatter.format(formattedVolumes));
// Output: "0.5 L, 1.5 L, 2.5 L"
숫자 포맷터가 목록 포맷터가 값을 처리하기 전에 소수점 정밀도를 처리합니다.
목록에서 속도 측정값 형식 지정
속도 측정은 kilometer-per-hour 및 mile-per-hour와 같은 복합 단위를 사용합니다.
const speeds = [50, 75, 100];
const numberFormatter = new Intl.NumberFormat('en-US', {
style: 'unit',
unit: 'kilometer-per-hour'
});
const formattedSpeeds = speeds.map(s => numberFormatter.format(s));
const listFormatter = new Intl.ListFormat('en-US', {
type: 'unit'
});
console.log(listFormatter.format(formattedSpeeds));
// Output: "50 km/h, 75 km/h, 100 km/h"
시속 마일도 동일한 방식으로 작동합니다.
const speeds = [30, 45, 60];
const numberFormatter = new Intl.NumberFormat('en-US', {
style: 'unit',
unit: 'mile-per-hour'
});
const formattedSpeeds = speeds.map(s => numberFormatter.format(s));
const listFormatter = new Intl.ListFormat('en-US', {
type: 'unit'
});
console.log(listFormatter.format(formattedSpeeds));
// Output: "30 mph, 45 mph, 60 mph"
복합 단위는 올바른 약어와 구분 기호로 자동으로 형식이 지정됩니다.
로케일이 목록 구분 기호 형식 결정
로케일 매개변수는 목록 항목이 구분되고 구두점이 표시되는 방식을 제어합니다. 언어마다 목록 형식 지정에 대한 규칙이 다릅니다.
const distances = [5, 10, 15];
const numberFormatter = new Intl.NumberFormat('en-US', {
style: 'unit',
unit: 'kilometer'
});
const formattedDistances = distances.map(d => numberFormatter.format(d));
const enList = new Intl.ListFormat('en-US', {
type: 'unit'
});
const frList = new Intl.ListFormat('fr-FR', {
type: 'unit'
});
const deList = new Intl.ListFormat('de-DE', {
type: 'unit'
});
console.log(enList.format(formattedDistances));
// Output: "5 km, 10 km, 15 km"
console.log(frList.format(formattedDistances));
// Output: "5 km, 10 km, 15 km"
console.log(deList.format(formattedDistances));
// Output: "5 km, 10 km, 15 km"
킬로미터 약어는 이러한 로케일에서 유사하게 유지되지만 간격 및 구분 기호 규칙은 다를 수 있습니다. Intl.ListFormat API는 이러한 로케일별 형식 규칙을 자동으로 처리합니다.
일부 언어는 목록에 대해 다른 구분 기호 또는 구두점 패턴을 사용합니다. API는 특정 규칙을 알 필요 없이 각 로케일에 대한 올바른 규칙을 목록이 따르도록 보장합니다.
숫자 로케일을 목록 로케일과 일치
측정값 목록의 형식을 지정할 때 숫자 포맷터와 목록 포맷터 모두에 동일한 로케일을 사용하세요. 이렇게 하면 출력 전체에서 일관된 형식이 보장됩니다.
const distances = [1000, 2000, 3000];
const locale = 'de-DE';
const numberFormatter = new Intl.NumberFormat(locale, {
style: 'unit',
unit: 'meter'
});
const formattedDistances = distances.map(d => numberFormatter.format(d));
const listFormatter = new Intl.ListFormat(locale, {
type: 'unit'
});
console.log(listFormatter.format(formattedDistances));
// Output: "1.000 m, 2.000 m, 3.000 m"
독일어 형식 지정은 마침표를 천 단위 구분 기호로 사용합니다. 숫자 포맷터와 목록 포맷터 모두 동일한 로케일을 공유하므로 독일어 규칙을 사용합니다.
숫자 및 목록 형식 지정에 다른 로케일을 사용하면 일관되지 않은 출력이 생성됩니다.
const distances = [1000, 2000, 3000];
const numberFormatter = new Intl.NumberFormat('de-DE', {
style: 'unit',
unit: 'meter'
});
const formattedDistances = distances.map(d => numberFormatter.format(d));
const listFormatter = new Intl.ListFormat('en-US', {
type: 'unit'
});
console.log(listFormatter.format(formattedDistances));
// Output: "1.000 m, 2.000 m, 3.000 m"
이는 숫자는 독일어 규칙을 사용하지만 목록은 영어 규칙을 사용하는 혼합 형식을 생성합니다. 두 포매터 모두에 항상 동일한 로케일을 사용하세요.
목록 표시 스타일 제어
style 옵션은 목록 형식이 얼마나 자세하게 표시되는지 제어합니다. 이 옵션은 "long", "short", "narrow"의 세 가지 값을 허용합니다.
const measurements = ['5 km', '10 km', '15 km'];
const longList = new Intl.ListFormat('en-US', {
type: 'unit',
style: 'long'
});
const shortList = new Intl.ListFormat('en-US', {
type: 'unit',
style: 'short'
});
const narrowList = new Intl.ListFormat('en-US', {
type: 'unit',
style: 'narrow'
});
console.log(longList.format(measurements));
// Output: "5 km, 10 km, 15 km"
console.log(shortList.format(measurements));
// Output: "5 km, 10 km, 15 km"
console.log(narrowList.format(measurements));
// Output: "5 km 10 km 15 km"
long 및 short 스타일은 영어에서 단위 목록에 대해 유사한 출력을 생성합니다. narrow 스타일은 최소한의 간격을 사용하고 항목 간 구분 기호를 생략합니다.
로케일마다 스타일 간 차이가 더 크게 나타납니다. 로케일은 각 스타일 수준에 대한 정확한 형식을 결정합니다.
긴 단위 이름과 결합
숫자 포맷터에서 unitDisplay: 'long'를 설정하여 약어 대신 전체 단위 이름으로 측정값을 형식화할 수 있습니다.
const distances = [5, 10, 15];
const numberFormatter = new Intl.NumberFormat('en-US', {
style: 'unit',
unit: 'kilometer',
unitDisplay: 'long'
});
const formattedDistances = distances.map(d => numberFormatter.format(d));
const listFormatter = new Intl.ListFormat('en-US', {
type: 'unit'
});
console.log(listFormatter.format(formattedDistances));
// Output: "5 kilometers, 10 kilometers, 15 kilometers"
숫자 포매터는 단수형과 복수형을 자동으로 처리합니다. 목록 포매터는 약어를 사용하든 전체 이름을 사용하든 관계없이 형식화된 문자열을 결합합니다.
const distances = [1, 5];
const numberFormatter = new Intl.NumberFormat('en-US', {
style: 'unit',
unit: 'kilometer',
unitDisplay: 'long'
});
const formattedDistances = distances.map(d => numberFormatter.format(d));
const listFormatter = new Intl.ListFormat('en-US', {
type: 'unit'
});
console.log(listFormatter.format(formattedDistances));
// Output: "1 kilometer, 5 kilometers"
숫자 포매터는 1에 대해 "kilometer"를 사용하고 5에 대해 "kilometers"를 사용합니다. 목록 포매터는 적절한 구분 기호로 이들을 결합합니다.
더 나은 성능을 위해 포매터 재사용
Intl.NumberFormat 및 Intl.ListFormat 인스턴스를 생성하려면 로케일 데이터를 로드하고 옵션을 처리해야 합니다. 여러 측정값 목록을 형식화할 때는 포맷터를 한 번 생성하고 재사용하세요.
const numberFormatter = new Intl.NumberFormat('en-US', {
style: 'unit',
unit: 'kilometer'
});
const listFormatter = new Intl.ListFormat('en-US', {
type: 'unit'
});
const distanceLists = [
[5, 10, 15],
[20, 25, 30],
[35, 40, 45]
];
distanceLists.forEach(distances => {
const formattedDistances = distances.map(d => numberFormatter.format(d));
console.log(listFormatter.format(formattedDistances));
});
// Output:
// "5 km, 10 km, 15 km"
// "20 km, 25 km, 30 km"
// "35 km, 40 km, 45 km"
이 패턴은 각 포매터를 한 번 생성하고 여러 번 사용합니다. 많은 목록을 형식화할 때 성능 차이가 상당해집니다.
재사용 가능한 포매터 함수 생성
두 단계 형식화 패턴을 재사용 가능한 함수로 캡슐화할 수 있습니다.
function formatMeasurementList(values, locale, unit) {
const numberFormatter = new Intl.NumberFormat(locale, {
style: 'unit',
unit: unit
});
const formattedValues = values.map(v => numberFormatter.format(v));
const listFormatter = new Intl.ListFormat(locale, {
type: 'unit'
});
return listFormatter.format(formattedValues);
}
console.log(formatMeasurementList([5, 10, 15], 'en-US', 'kilometer'));
// Output: "5 km, 10 km, 15 km"
console.log(formatMeasurementList([50, 75, 100], 'en-US', 'kilogram'));
// Output: "50 kg, 75 kg, 100 kg"
console.log(formatMeasurementList([20, 22, 25], 'en-US', 'celsius'));
// Output: "20°C, 22°C, 25°C"
이 함수는 모든 측정 유형과 로케일을 처리합니다. 추가 형식화 옵션을 허용하도록 확장할 수 있습니다.
function formatMeasurementList(values, locale, unit, options = {}) {
const numberFormatter = new Intl.NumberFormat(locale, {
style: 'unit',
unit: unit,
...options
});
const formattedValues = values.map(v => numberFormatter.format(v));
const listFormatter = new Intl.ListFormat(locale, {
type: 'unit'
});
return listFormatter.format(formattedValues);
}
console.log(formatMeasurementList(
[5.123, 10.789, 15.456],
'en-US',
'kilometer',
{ maximumFractionDigits: 1 }
));
// Output: "5.1 km, 10.8 km, 15.5 km"
console.log(formatMeasurementList(
[1, 5, 10],
'en-US',
'kilometer',
{ unitDisplay: 'long' }
));
// Output: "1 kilometer, 5 kilometers, 10 kilometers"
이 함수는 추가 옵션을 숫자 포매터에 전달하여 소수 자릿수, 단위 표시 및 기타 형식화 설정을 제어할 수 있습니다.
사용자 로케일에 맞게 목록 형식 지정
특정 로케일을 하드코딩하는 대신 사용자의 브라우저 언어 기본 설정을 사용할 수 있습니다. navigator.language 속성은 사용자가 선호하는 로케일을 반환합니다.
const userLocale = navigator.language;
const distances = [5, 10, 15];
const numberFormatter = new Intl.NumberFormat(userLocale, {
style: 'unit',
unit: 'kilometer'
});
const formattedDistances = distances.map(d => numberFormatter.format(d));
const listFormatter = new Intl.ListFormat(userLocale, {
type: 'unit'
});
console.log(listFormatter.format(formattedDistances));
// Output varies by user's locale
이 접근 방식은 각 사용자의 형식 지정 기대에 따라 측정 목록을 표시합니다. 서로 다른 사용자는 자신의 로케일 규칙에 따라 형식이 지정된 동일한 데이터를 보게 됩니다.
애플리케이션에서 측정 목록 표시
사용자에게 여러 측정값을 표시하는 모든 곳에서 이 패턴을 사용할 수 있습니다. 여기에는 구간 기록을 표시하는 피트니스 애플리케이션, 온도 예보를 표시하는 날씨 애플리케이션, 재료 양을 표시하는 레시피 애플리케이션, 실험 데이터를 표시하는 과학 애플리케이션이 포함됩니다.
const splitTimes = [5, 10, 15, 20];
const numberFormatter = new Intl.NumberFormat(navigator.language, {
style: 'unit',
unit: 'kilometer',
maximumFractionDigits: 1
});
const formattedTimes = splitTimes.map(t => numberFormatter.format(t));
const listFormatter = new Intl.ListFormat(navigator.language, {
type: 'unit'
});
const result = listFormatter.format(formattedTimes);
document.getElementById('split-times').textContent = result;
// Displays: "5 km, 10 km, 15 km, 20 km" (or locale equivalent)
형식이 지정된 문자열은 다른 문자열 값과 동일하게 작동합니다. 텍스트 콘텐츠, 속성 또는 사용자에게 정보를 표시하는 모든 컨텍스트에 삽입할 수 있습니다.