React Router v7에서 다양한 로케일에 맞게 날짜 형식을 지정하는 방법
지역별 형식으로 날짜 표시
문제
날짜는 보편적인 표기 형식이 없습니다. 숫자 시퀀스 10/12/2025는 미국에서는 10월 12일을 의미하지만 영국에서는 12월 10일을 의미합니다. "Oct 12, 2025"와 같은 형식도 영어 월 이름과 특정 순서 규칙을 가정하므로 사용자의 기대와 일치하지 않을 수 있습니다. 애플리케이션이 단일 고정 형식으로 날짜를 표시하면 다른 규칙을 따르는 지역의 사용자에게는 낯설게 느껴져 명확성과 신뢰도가 떨어집니다.
로케일마다 날짜 표시에 대한 고유한 규칙이 있으며, 여기에는 일, 월, 연도의 순서, 구분 기호 선택, 월 이름을 전체로 표기할지 약어로 표기할지 등이 포함됩니다. 이러한 규칙을 무시하면 사용자는 날짜를 익숙한 형식으로 정신적으로 변환해야 하므로 인지 부하가 증가하고 오해의 위험이 커집니다.
솔루션
지역 규칙을 이해하는 국제화 API에 표시 로직을 위임하여 사용자의 로케일에 따라 날짜 값을 형식화합니다. 날짜 문자열을 수동으로 구성하는 대신 날짜 객체를 형식화 함수 또는 컴포넌트에 전달하여 활성 로케일에 맞는 올바른 순서, 구분 기호, 월 이름을 적용합니다.
React-intl은 표준 날짜 형식화 옵션을 허용하고 로케일 인식 문자열을 생성하는 선언적 컴포넌트와 명령형 메서드를 모두 제공합니다. 포함할 날짜 부분과 세부 수준을 지정하여 출력 스타일을 제어하는 동시에 라이브러리가 지역별 변형을 처리합니다. 이 접근 방식은 날짜 형식화 로직을 표시 컴포넌트와 분리하고 애플리케이션 전체에서 일관성을 보장합니다.
단계
1. FormattedDate로 컴포넌트에서 날짜 형식화
react-intl의 FormattedDate 컴포넌트를 사용하여 로케일별 형식으로 날짜를 렌더링하세요. 이 컴포넌트는 날짜 값과 Intl.DateTimeFormatOptions에 해당하는 형식 옵션을 받습니다.
import { FormattedDate } from "react-intl";
export default function EventCard({ event }) {
return (
<article>
<h2>{event.title}</h2>
<time>
<FormattedDate
value={event.date}
year="numeric"
month="long"
day="numeric"
/>
</time>
<p>{event.description}</p>
</article>
);
}
FormattedDate 컴포넌트는 formatDate 및 Intl.DateTimeFormat API를 사용하여 주변 IntlProvider에서 제공하는 로케일과 일치하는 문자열을 생성합니다. year, month, day 옵션은 표시할 부분과 형식을 제어합니다.
2. useIntl로 명령형으로 날짜 형식 지정하기
속성, aria 레이블 또는 데이터 변환과 같이 렌더링되지 않는 컨텍스트에서 형식화된 날짜 문자열이 필요한 경우 useIntl 훅을 사용하여 formatDate 메서드에 액세스하세요.
import { useIntl } from "react-intl";
export default function EventList({ events }) {
const intl = useIntl();
return (
<ul>
{events.map((event) => {
const formattedDate = intl.formatDate(event.date, {
year: "numeric",
month: "short",
day: "numeric",
});
return (
<li key={event.id}>
<a
href={`/events/${event.id}`}
aria-label={`${event.title} on ${formattedDate}`}
>
{event.title}
</a>
</li>
);
})}
</ul>
);
}
formatDate 함수는 날짜 값과 선택적 Intl.DateTimeFormatOptions를 받아 로케일 형식의 문자열을 반환합니다. 이는 형식화된 날짜를 다른 문자열에 포함하거나 prop 값으로 사용해야 할 때 유용합니다.
3. 재사용 가능한 날짜 포맷터 헬퍼 만들기
일반적인 날짜 형식 패턴을 intl.formatDate를 래핑하는 헬퍼 함수로 추출하여 애플리케이션 전체에서 일관성을 보장하세요.
import { useIntl } from "react-intl";
export function useDateFormatter() {
const intl = useIntl();
return {
formatShortDate: (date: Date | number) =>
intl.formatDate(date, {
year: "numeric",
month: "numeric",
day: "numeric",
}),
formatLongDate: (date: Date | number) =>
intl.formatDate(date, {
year: "numeric",
month: "long",
day: "numeric",
}),
formatDateTime: (date: Date | number) =>
intl.formatDate(date, {
year: "numeric",
month: "short",
day: "numeric",
hour: "numeric",
minute: "2-digit",
}),
};
}
이 훅은 형식 지정 로직을 중앙 집중화하고 애플리케이션 전체에 일관된 날짜 스타일을 쉽게 적용할 수 있게 합니다. 컴포넌트는 원하는 세부 수준에 따라 적절한 메서드를 호출합니다.
4. 라우트 로더에서 날짜 형식 지정하기
데이터 로딩 중에 날짜 형식이 필요한 경우 요청에서 로케일에 액세스하고 createIntl를 사용하여 로더 데이터를 반환하기 전에 날짜를 형식화하세요.
import type { Route } from "./+types/event";
import { createIntl, createIntlCache } from "react-intl";
const cache = createIntlCache();
export async function loader({ request }: Route.LoaderArgs) {
const url = new URL(request.url);
const locale = url.searchParams.get("locale") || "en";
const event = await fetchEvent();
const intl = createIntl({ locale, messages: {} }, cache);
return {
event,
formattedDate: intl.formatDate(event.date, {
year: "numeric",
month: "long",
day: "numeric",
}),
};
}
export default function Event({ loaderData }: Route.ComponentProps) {
return (
<article>
<h1>{loaderData.event.title}</h1>
<time>{loaderData.formattedDate}</time>
</article>
);
}
createIntl 함수는 React 컴포넌트 외부에서 날짜를 형식화할 수 있는 intl 객체를 생성합니다. 이 접근 방식은 서버 또는 정적 생성 중에 날짜를 미리 형식화하여 클라이언트 측 작업을 줄입니다.