1. 개요
글로벌 웹 서비스를 구축하면서 다국어 지원(internationalization, i18n) 기능을 직접 구현했던 경험을 정리해 공유합니다.
이 글에서는 Next.js 13 이상 버전의 App Router 환경에서 `next-intl` 라이브러리를 사용해 언어별 URL 라우팅, 자동 리다이렉션, 번역 메시지 구성 등 다국어 라우팅을 설정하는 방법에 대해 단계별로 설명합니다.
✅ 이번 글에서는 `next-intl` 설정만 다루고, 다음 글(2편)에서는 실제 화면에서 다국어 메시지 렌더링, 언어 전환 UI를 구현합니다.
2. next-intl을 활용한 다국어 라우팅 설정
2-1. next-intl 라이브러리 설치
먼저, 프로젝트에 `next-intl` 패키지를 설치합니다.
npm install next-intl
React 기반의 Next.js App Router 구조와 잘 통합되어 있어서, 복잡한 설정 없이도 다국어 지원을 쉽게 구현할 수 있도록 도와줍니다.
2-2. 프로젝트 구조 설정
`next-intl` 공식 문서에서도 권장하는 구조입니다. 이대로 설정하면 유지보수 및 확장에 유리합니다.
project-root/
├── app/
│ ├── layout.tsx
│ ├── [locale]/
│ │ ├── layout.tsx
│ │ └── page.tsx
├── i18n/
│ ├── routing.ts
│ ├── request.ts
│ └── navigation.ts
├── messages/
│ ├── en.json
│ └── ko.json
├── middleware.ts
├── next.config.js
하나씩 구현해 보겠습니다.
2-3. 지원 언어 및 기본 설정
지원할 언어와 기본 언어를 `i18n/routing.ts`에서 정의합니다.
// i18n/routing.ts
import { defineRouting } from 'next-intl/routing';
export const routing = defineRouting({
locales: ['en', 'ko'], // 지원할 언어
defaultLocale: 'en', // 기본 언어
});
2-4. 언어 접두어 자동 리다이렉션 설정
URL에 언어 접두어가 없는 경우, `/ko`, `/en` 등으로 자동 리다이렉션 되도록 설정해야 합니다.
middleware를 활용하면 되고, Api 경로 또는 정적 리소스 경로는 제외되도록 했습니다.
// middleware.ts
import createMiddleware from 'next-intl/middleware';
import { routing } from './i18n/routing';
// 언어 접두어 없는 경로 → 자동 리디렉션 처리
export default createMiddleware(routing);
export const config = {
// 다음 경로는 제외:
// - /api, /trpc, /_next, /_vercel
// - 정적 리소스 (.js, .css, .ico 등)
matcher: '/((?!api|trpc|_next|_vercel|.*\\..*).*)',
};
예시 동작
요청 경로 | 리다이렉션 결과 |
/ | /ko |
/about | /ko/about |
/favicon.ico, /api/data 등 정적 리소스 | 그대로 유지 |
2-5. 언어별 메시지 분리
언어별 번역 메시지는 JSON 파일로 분리해 관리합니다.
💡 실제 운영에서는 구글 스프레드 시트 등으로 연동하여 JSON 파일을 자동 생성하는 방식이 유용합니다.
2-6. 서버 측 메시지 로딩 설정
요청된 언어에 맞는 메시지를 동적으로 import 합니다.
지원하지 않는 언어가 들어오면 `defaultLocale`로 fallback 처리됩니다.
// i18n/request.ts
import { getRequestConfig } from 'next-intl/server';
import { hasLocale } from 'next-intl';
import { routing } from './routing';
export default getRequestConfig(async ({ requestLocale }) => {
// Typically corresponds to the `[locale]` segment
const requested = await requestLocale;
const locale = hasLocale(routing.locales, requested) ? requested : routing.defaultLocale;
return {
locale,
messages: (await import(`@/messages/${locale}.json`)).default,
};
});
2-7. 라우팅 헬퍼 구성
NextJS에서 기본 `Link`나 `useRouter`를 사용할 경우 언어 접두어를 자동 처리하지 않기 때문에, `next-intl`에서 제공하는 라우팅 헬퍼로 wrapping 해줍니다.
// i18n/navigation.ts
import { createNavigation } from 'next-intl/navigation';
import { routing } from './routing';
export const { Link, redirect, usePathname, useRouter, getPathname } = createNavigation(routing);
3. 전체 구성 요약
구성 요소 | 역할 |
i18n/routing.ts | 지원 언어 및 기본 언어 정의 |
i18n/request.ts | 서버에서 언어 메시지 로딩 |
i18n/navigation.ts | NextJs의 라우팅 관련 래핑 함수 만들기 |
messages/*.json | 언어별 번역 메시지 관리 |
middleware.ts | 자동 리다이렉션 설정 (언어 감지 및 URL 리다이렉션) |
4. 결론
Next.js App Router 환경에서 `next-intl`을 활용한 다국어 설정은 복잡해 보일 수 있지만, 구조를 잘 정리하면 확장성과 유지보수성이 매우 높아집니다.
- SEO에 유리한 URL 기반 언어 구조
- 서버 사이드에서 안전하게 메시지 관리
- 사용자의 언어 설정에 따라 자동 라우팅 처리
이번 글에서는 설정 중심의 내용을 다뤘으며,
다음 글(2편)에서는 실제 다국어 텍스트를 화면에 렌더링 하고, 언어 전환 드롭다운을 구현하겠습니다.
👉 이 글의 예제 프로젝트는 아래 GitHub 저장소에서 확인하실 수 있습니다.
GitHub - taein8935/next-intl-demo
Contribute to taein8935/next-intl-demo development by creating an account on GitHub.
github.com