JavaScript에서 A, B, C와 같은 목록을 어떻게 포맷팅하나요?

Intl.ListFormat를 사용하여 로케일별 접속사와 구분자가 포함된 배열을 포맷팅하세요.

소개

사용자에게 항목 목록을 표시할 때, 쉼표와 "그리고"와 같은 접속사로 항목들을 연결해야 합니다. 목록 형식에 대한 규칙은 언어마다 다릅니다. 영어는 쉼표와 "and"를 사용하고, 스페인어는 "y"를, 프랑스어는 "et"를 사용하며, 중국어는 완전히 다른 구두점을 사용합니다.

Intl.ListFormat API는 배열을 해당 로케일에 적합한 문자열로 형식화하여 올바른 구분자와 접속사를 사용합니다. 이는 목록 형식의 문화적 차이를 자동으로 처리합니다.

수동 목록 형식화의 문제점

배열 요소를 join() 메서드를 사용하여 쉼표로 연결할 수 있습니다.

const fruits = ["apples", "oranges", "bananas"];
const list = fruits.join(", ");
console.log(list);
// "apples, oranges, bananas"

이 접근 방식에는 두 가지 문제가 있습니다. 첫째, 마지막 항목 앞에 접속사를 추가하지 않습니다. 둘째, 다른 언어에서는 작동하지 않는 영어 구두점을 사용합니다.

마지막 항목 앞에 "and"를 수동으로 추가할 수 있습니다.

const fruits = ["apples", "oranges", "bananas"];
const lastFruit = fruits[fruits.length - 1];
const otherFruits = fruits.slice(0, -1);
const list = otherFruits.join(", ") + ", and " + lastFruit;
console.log(list);
// "apples, oranges, and bananas"

이 코드는 영어에서만 작동합니다. 스페인어 사용자는 "apples, oranges y bananas" 대신 "apples, oranges, and bananas"를 보게 됩니다. 프랑스어 사용자는 "et" 대신 "and"를 보게 됩니다. 구두점과 접속사 규칙은 언어마다 다릅니다.

Intl.ListFormat를 사용하여 목록 형식화하기

'Intl.ListFormat' 생성자는 배열을 로케일에 적합한 목록 문자열로 변환하는 포맷터를 생성합니다.

const formatter = new Intl.ListFormat("en");
const fruits = ["apples", "oranges", "bananas"];
console.log(formatter.format(fruits));
// "apples, oranges, and bananas"

포맷터는 지정된 로케일에 맞는 올바른 구분자와 접속사를 사용합니다. 생성자의 첫 번째 인수로 로케일을 전달합니다.

const enFormatter = new Intl.ListFormat("en");
const esFormatter = new Intl.ListFormat("es");
const frFormatter = new Intl.ListFormat("fr");

const fruits = ["apples", "oranges", "bananas"];

console.log(enFormatter.format(fruits));
// "apples, oranges, and bananas"

console.log(esFormatter.format(fruits));
// "apples, oranges y bananas"

console.log(frFormatter.format(fruits));
// "apples, oranges et bananas"

포맷터는 각 로케일에 대한 구두점과 접속사 규칙을 자동으로 적용합니다.

"and"를 사용한 목록 서식 지정

기본적으로 Intl.ListFormat는 "and" 또는 다른 언어에서의 이에 상응하는 접속사를 사용합니다. 이를 접속 서식이라고 합니다.

const formatter = new Intl.ListFormat("en", { type: "conjunction" });
const items = ["bread", "milk", "eggs"];
console.log(formatter.format(items));
// "bread, milk, and eggs"

type 옵션은 항목 사이에 나타나는 연결자를 제어합니다. "conjunction" 값은 "and"를 사용하는 목록을 생성합니다. 이는 기본값이므로 생략할 수 있습니다.

목록 유형 옵션 이해하기

type 옵션은 항목 연결 방식을 제어하는 세 가지 값을 허용합니다.

"conjunction" 유형은 "and" 또는 이에 상응하는 표현을 사용합니다.

const formatter = new Intl.ListFormat("en", { type: "conjunction" });
console.log(formatter.format(["red", "green", "blue"]));
// "red, green, and blue"

"disjunction" 유형은 "or" 또는 이에 상응하는 표현을 사용합니다.

const formatter = new Intl.ListFormat("en", { type: "disjunction" });
console.log(formatter.format(["red", "green", "blue"]));
// "red, green, or blue"

"unit" 유형은 접속사 없이 측정값이나 수량의 목록을 서식화합니다.

const formatter = new Intl.ListFormat("en", { type: "unit" });
console.log(formatter.format(["5 pounds", "12 ounces"]));
// "5 pounds, 12 ounces"

단위 유형은 기술적 또는 측정 데이터에 적합한 최소한의 구두점을 사용합니다.

스타일 옵션 이해하기

'style' 옵션은 서식이 지정된 출력의 길이와 형식을 제어합니다. 세 가지 값을 허용합니다.

"long" 스타일은 전체 단어와 표준 구두점을 사용합니다. 이것이 기본값입니다.

const formatter = new Intl.ListFormat("en", { style: "long" });
console.log(formatter.format(["Alice", "Bob", "Carol"]));
// "Alice, Bob, and Carol"

"short" 스타일은 가능한 경우 약어 형식을 사용합니다.

const formatter = new Intl.ListFormat("en", { style: "short" });
console.log(formatter.format(["Alice", "Bob", "Carol"]));
// "Alice, Bob, & Carol"

"narrow" 스타일은 가능한 가장 간결한 형식을 사용합니다.

const formatter = new Intl.ListFormat("en", { style: "narrow" });
console.log(formatter.format(["Alice", "Bob", "Carol"]));
// "Alice, Bob, Carol"

좁은 스타일은 종종 접속사를 완전히 생략합니다. 정확한 출력은 로케일에 따라 다릅니다.

다양한 로케일에서의 목록 형식 지정 방법

각 로케일은 목록 형식 지정에 대한 고유한 규칙을 가지고 있습니다. 포맷터는 이러한 규칙을 자동으로 적용합니다.

영어는 쉼표를 사용하고 "and" 앞에 옥스포드 쉼표를 포함합니다.

const formatter = new Intl.ListFormat("en");
console.log(formatter.format(["coffee", "tea", "juice"]));
// "coffee, tea, and juice"

스페인어는 쉼표와 접속사 "y"를 사용합니다.

const formatter = new Intl.ListFormat("es");
console.log(formatter.format(["café", "té", "jugo"]));
// "café, té y jugo"

프랑스어는 쉼표와 접속사 "et"를 사용합니다.

const formatter = new Intl.ListFormat("fr");
console.log(formatter.format(["café", "thé", "jus"]));
// "café, thé et jus"

중국어는 "and"를 나타내는 문자 和를 사용하고 열거형 쉼표 、를 구분자로 사용합니다.

const formatter = new Intl.ListFormat("zh");
console.log(formatter.format(["咖啡", "茶", "可乐"]));
// "咖啡、茶和可乐"

독일어는 쉼표와 접속사 "und"를 사용합니다.

const formatter = new Intl.ListFormat("de");
console.log(formatter.format(["Kaffee", "Tee", "Saft"]));
// "Kaffee, Tee und Saft"

포맷터는 각 언어의 규칙을 알 필요 없이 이러한 차이점을 처리합니다.

formatToParts를 사용하여 개별 부분 가져오기

formatToParts() 메서드는 형식이 지정된 목록의 각 부분을 나타내는 객체 배열을 반환합니다. 이는 서로 다른 부분에 개별적으로 스타일을 적용해야 할 때 유용합니다.

const formatter = new Intl.ListFormat("en");
const parts = formatter.formatToParts(["red", "green", "blue"]);
console.log(parts);

출력은 typevalue 속성을 가진 객체 배열입니다.

[
  { type: "element", value: "red" },
  { type: "literal", value: ", " },
  { type: "element", value: "green" },
  { type: "literal", value: ", and " },
  { type: "element", value: "blue" }
]

각 목록 항목은 "element" 타입을 가집니다. 구분자와 접속사는 "literal" 타입을 가집니다. 이를 사용하여 사용자 정의 스타일을 적용할 수 있습니다.

const formatter = new Intl.ListFormat("en");
const parts = formatter.formatToParts(["red", "green", "blue"]);

const html = parts
  .map((part) => {
    if (part.type === "element") {
      return `<strong>${part.value}</strong>`;
    }
    return part.value;
  })
  .join("");

console.log(html);
// "<strong>red</strong>, <strong>green</strong>, and <strong>blue</strong>"

이 접근 방식은 로케일에 적합한 구분자와 접속사를 유지하면서 형식 지정에 대한 정확한 제어를 제공합니다.

브라우저 지원

Intl.ListFormat API는 모든 최신 브라우저에서 사용할 수 있습니다. 2021년 4월부터 Chrome, Firefox, Safari, Edge 등 주요 브라우저에서 지원되고 있습니다.

사용하기 전에 API의 가용성을 확인할 수 있습니다.

if (typeof Intl.ListFormat !== "undefined") {
  const formatter = new Intl.ListFormat("en");
  console.log(formatter.format(["a", "b", "c"]));
} else {
  console.log("Intl.ListFormat is not supported");
}

구형 브라우저의 경우 대체 방법을 제공하거나 폴리필을 사용해야 합니다. 대체 방법으로는 간단한 join() 메서드를 사용할 수 있습니다.

function formatList(items, locale) {
  if (typeof Intl.ListFormat !== "undefined") {
    const formatter = new Intl.ListFormat(locale);
    return formatter.format(items);
  }
  return items.join(", ");
}

console.log(formatList(["red", "green", "blue"], "en"));
// "red, green, and blue" (또는 구형 브라우저에서는 "red, green, blue")

이렇게 하면 Intl.ListFormat를 지원하지 않는 브라우저에서도 코드가 작동합니다.