Next.js에서 Internationalization(i18n) 적용하기: 시작부터 완성까지
2025-04-28 13:20:03Next.js에서 i18n 국제화란 무엇인가?
인터내셔널라이제이션, 흔히 줄여서 i18n(아이18엔)은 웹 애플리케이션을 다양한 언어와 지역에 적응할 수 있도록 설계하는 과정입니다. 주로 웹 앱에서 이것은 다양한 언어로 텍스트를 표시하고, 날짜, 숫자, 통화를 해당 지역의 형식에 맞춰 포맷하며, URL을 적용된 언어에 맞게 변경하는 것을 포함합니다.
next-intl을 활용한 i18n의 장점
next-intl 라이브러리는 Next.js 프로젝트에서 i18n을 구현하는 데 있어 강력한 기능을 제공합니다. 이 라이브러리는 특히 Next.js 13+의 App Router와 잘 통합되며, 다양한 언어 경로를 손쉽게 추가할 수 있게 지원합니다. 또한 클라이언트 및 서버에서 모두 사용할 수 있는 번역 훅과 미들웨어 지원으로 사용자의 브라우저 언어에 맞춰 리다이렉션 기능도 제공하여 대규모 다국어 앱에서도 유연하게 확장 가능성을 보입니다.
주요 기능
- 라우팅 지원: 각 언어에 따라 다른 경로를 설정할 수 있습니다. (/en, /bn 등)
- 서버 및 클라이언트 훅 제공:
useTranslations와 같은 훅을 통해 클라이언트 측에서 번역을 쉽게 관리할 수 있고,getTranslations로 서버 측에서 번역을 처리할 수 있습니다. - 자동 언어 감지: 사용자의 브라우저 설정을 통해 적절한 언어로 자동 리다이렉션합니다.
next-intl 설치하기
i18n 기능을 활용하기 위해 우선 next-intl 패키지를 설치해야 합니다.
npm install next-intl
폴더 구조
다음은 프로젝트 내 i18n 관련 폴더 구조 예제입니다. 직관적인 구조로 유지 보수에 용이하도록 설계해야 합니다.
src
├── app
│ ├── [locale]
│ ├── layout.tsx
│ ├── page.tsx
├── i18n
│ ├── locales
│ │ ├── en.json
│ │ ├── bn.json
│ ├── routing.ts
│ ├── navigation.ts
│ ├── request.ts
├── middleware.ts
├── next.config.js
i18n 디렉터리 생성하기
i18n 처리를 위해 프로젝트 내에서 /locales 디렉터리를 생성하고 각 언어별 JSON 파일을 추가합니다.
en.json 예시
{
"home": {
"title": "Hello world!",
"about": "Go to the about page"
}
}
bn.json 예시
{
"home": {
"title": "হ্যালো বিশ্ব!",
"about": "সম্বন্ধে পৃষ্ঠায় যান"
}
}
지원 언어 정의하기
i18n/routing.ts 파일에 지원할 언어와 기본 언어를 설정합니다.
import { defineRouting } from 'next-intl/routing';
export const routing = defineRouting({
locales: ['en', 'bn'],
defaultLocale: 'en'
});
내비게이션 정의하기
언어 설정이 완료되면 내비게이션 API를 설정할 수 있습니다. i18n/navigation.ts 파일을 생성하여 설정합니다.
import { createNavigation } from 'next-intl/navigation';
import { routing } from './routing';
export const { Link, redirect, usePathname, useRouter, getPathname } =
createNavigation(routing);
언어 감지를 위한 미들웨어 설정하기
미들웨어를 통해 사용자 브라우저의 언어 설정에 따라 자동으로 리다이렉션합니다.
import createMiddleware from 'next-intl/middleware';
import { routing } from './i18n/routing';
export default createMiddleware(routing);
export const config = {
matcher: '/((?!api|trpc|_next|_vercel|.*\\..*).*)'
};
next.config.js 설정
라우팅을 i18n 필드 없이 next-intl이 처리하도록 설정을 업데이트합니다.
import { NextConfig } from 'next';
import createNextIntlPlugin from 'next-intl/plugin';
const nextConfig: NextConfig = {};
const withNextIntl = createNextIntlPlugin();
export default withNextIntl(nextConfig);
getRequestConfig를 통해 번역 제공
getRequestConfig를 사용해 번역을 제공합니다.
import { getRequestConfig } from 'next-intl/server';
import { hasLocale } from 'next-intl';
import { routing } from './routing';
export default getRequestConfig(async ({ requestLocale }) => {
const requested = await requestLocale;
const locale = hasLocale(routing.locales, requested) ? requested : routing.defaultLocale;
return {
locale,
messages: (await import(`./locales/${locale}.json`)).default
};
});
layout.tsx에서 NextIntlClientProvider 사용하기
NextIntlClientProvider를 활용하여 레이아웃을 설정합니다.
import { NextIntlClientProvider, hasLocale } from 'next-intl';
import { notFound } from 'next/navigation';
import { routing } from '@/i18n/routing';
export default async function LocaleLayout({
children,
params
}) {
const { locale } = await params;
if (!hasLocale(routing.locales, locale)) {
notFound();
}
return (
<html lang={locale}>
<body>
<NextIntlClientProvider>{children}</NextIntlClientProvider>
</body>
</html>
);
}
페이지에서 번역 사용하기
번역 훅을 사용하여 각 페이지에서 번역을 처리합니다.
import { useTranslations } from 'next-intl';
import { Link } from '@/i18n/navigation';
export default function HomePage() {
const t = useTranslations('home');
return (
<div>
<h1>{t('title')}</h1>
<Link href="/about">{t('about')}</Link>
</div>
);
}
비동기 컴포넌트에서는 다음과 같이 할 수 있습니다.
import { getTranslations } from 'next-intl/server';
export default async function HomePage() {
const t = await getTranslations('home');
return <h1>{t('title')}</h1>;
}
결론
위 과정을 따르면 Next.js App Router에서 next-intl을 사용하여 완벽한 i18n 설정이 가능합니다. 앱은 각 언어에 따라 경로를 설정하고, 적절한 번역을 로드하며, 사용자의 언어 설정에 따른 리다이렉션 및 기본 언어 대체 기능을 수행합니다.