Develop

Next.js 다국어 i18n 완벽 가이드 — next-intl로 다국어 처리하는 방법

Next.js App Router 아키텍처 환경에서, 다국어 URL 라우팅 세팅 및 번역 리소스 관리를 서버 컴포넌트 스펙에 호환되도록 next-intl 라이브러리를 사용해 우아하게 다국어 사이트를 구축하는 요령을 전수합니다.

Next.jsi18nnext-intl다국어frontend
Next.js App Router에서 next-intl로 한국어와 영어 다국어 라우팅이 동작하는 화면 — i18n 설정 예시
  • ·Next.js App Router는 [locale] 동적 세그먼트로 다국어 라우팅을 구현한다
  • ·next-intl은 Next.js App Router 전용으로 설계된 i18n 라이브러리로 서버 컴포넌트를 완전 지원한다
  • ·setRequestLocale을 호출해야 정적 렌더링(generateStaticParams)과 함께 다국어 페이지를 빌드할 수 있다
  • ·번역 파일은 messages/ko.json, messages/en.json 형태로 관리하며 중첩 키를 지원한다
블로그 사이트의 글로벌 확장을 위해 한국어와 영어를 동시에 번역 노출시키는 다국어 환경을 `next-intl` 모듈로 직접 구축했습니다. 처음에 미들웨어 파일 연동 단에서 createMiddleware 라우팅 설정을 비정상으로 기재한 탓에, 사용자가 영국 브라우저로 접근해도 줄곧 한국어로만 메인 페이지 리다이렉트가 꼬이는 다국어 에러를 겪었습니다. 공식 매뉴얼 문서의 라우팅 컴파일 단계 구조를 차분히 대조 분석하여, `defineRouting` 스펙으로 바인딩을 교정해 준 이후에야 비로소 URL 경로 기반 언어 스위칭이 자연스럽게 연동되는 쾌거를 거두었습니다.

1. i18n 라이브러리 선정과 구조

서버 컴포넌트를 지원하는 Next.js next-intl 다국어 스펙의 이점

React Pages Router 시절 널리 활약하던 next-i18next 라이브러리는 렌더링 방식의 차이로 인해 모던 App Router의 서버 컴포넌트(Server Component) 환경에서 제대로 동작하지 않고 에러를 내뿜습니다. next-intl 은 이러한 Next.js App Router의 내장 사상을 온전히 수용해 설계된 전용 국제화(i18n) 도구입니다. 브라우저 단에서 번역 JS 파일을 다운받고 리렌더링을 태우는 수고로움 없이, 서버 사이드 단에서 미리 완벽하게 번역이 마감된 깨끗한 HTML 본문을 클라이언트에 뿌려 주므로 로딩 속도 향상과 SEO 인덱싱 측면에서 비교 불가한 차이를 냅니다.

중첩 번역 템플릿 파일 설계와 Next.js 다국어 메시지 관리 요령

다국어 텍스트들은 프로젝트 루트의 messages/ 폴더 하위에 ko.jsonen.json 과 같은 고유한 언어 코드 파일 세트로 통제 관리합니다. JSON 규격 내부에 중첩 객체 구조(nav.home.title) 형태로 카테고리를 나누어 번역 키를 엮어두면 가독성에 매우 유리하죠. {name} 형식의 변수 보간이나 복수형 표현 처리 등을 유연하게 치환할 수 있는 ICU 메시지 규격을 네이티브로 지원하므로, 날짜 포맷팅이나 숫자 쉼표 표기까지 각 언어 문화권 표준에 맞춰 미려하게 바인딩할 수 있습니다.

2. 다국어 라우팅 및 빌드 굳히기

Next.js 미들웨어와 next-intl routing을 연동한 URL 경로 매핑

next-intl 라우팅의 핵심 뼈대는 app/[locale]/ 경로 아래에 전체 소스 파일들을 둥글게 가두는 폴더 기반 라우팅 설계입니다. URL 주소창에 /ko/about 혹은 /en/about 처럼 언어 세그먼트를 맵핑해 기재하는 형태로 제어하죠. i18n/routing.ts 파일에 defineRouting 설정으로 기본 로케일(defaultLocale: 'ko')과 지원 범위 리스트를 박아두면, 젠킨스 수준이 아닌 Next.js 미들웨어 단에서 브라우저 언어 환경 정보를 채가서 어울리는 로케일 경로로 초고속 리다이렉션을 단행해 줍니다.

// i18n/routing.ts - 다국어 라우팅 핵심 정의
import { defineRouting } from 'next-intl/navigation';

export const routing = defineRouting({
  locales: ['ko', 'en'], // 지원할 국가 언어 팩
  defaultLocale: 'ko' // 기본 번역 로케일
});

// middleware.ts - 언어 주소 매칭 프록시 설정
import createMiddleware from 'next-intl/middleware';
import { routing } from './i18n/routing';

export default createMiddleware(routing);

export const config = {
  // 내부 api 및 정적 리소스 파일은 다국어 매핑 검사에서 제외 처리
  matcher: ['/', '/(ko|en)/:path*', '/((?!_next|_vercel|.*\\\\..*).*)']
};

next-intl setRequestLocale을 활용한 정적 i18n 빌드 최적화

다국어 사이트를 Vercel이나 CDN 서버로 빌드할 때 아주 흔히 마주치는 오류 중 하나는, 다국어 동적 세그먼트로 인해 정적 빌드(output: 'export' 혹은 정적 생성)가 누락되며 런타임 성능이 나빠지는 현상입니다. 이 현상을 깔끔하게 격파하려면 layout.tsxpage.tsx 내부 시작 진입점에 **반드시 setRequestLocale(locale) 함수를 소환해 주어야 합니다.** 이 가드 명령이 선언되어 있어야만 Next.js 컴파일러가 안심하고 빌드 타임에 언어별 페이지 세트를 정적 HTML로 안전하게 깎아내어 보관하며, 빌드 에러 없이 매끈한 정적 컴파일 성공 코드를 내뿜게 됩니다.

3. 컴포넌트 내 텍스트 매핑 실무

Next.js 서버 및 클라이언트 컴포넌트 각각에서 다국어 메시지 주입법

실제 코딩 시에는 번역이 뿌려질 컴포넌트 성격에 맞춰 호출 수단을 다르게 태워야 합니다. 서버 컴포넌트 환경이라면 비동기 getTranslations 함수를 소환해 const t = await getTranslations('nav') 형태로 비동기 긁어오기를 단행하고, 클라이언트 컴포넌트 환경('use client')이라면 useTranslations 훅을 불러다 const t = useTranslations('nav') 형태로 얕은 로딩 매핑을 엮어주면 끝납니다. 어떤 환경이든 타입 선언 꼬임 없이 JSON 키 정보에 일치하는 번역 텍스트가 미려하게 전송 렌더링됩니다.

// app/[locale]/page.tsx - 서버 컴포넌트 다국어 렌더링 정석 코드
import { getTranslations, setRequestLocale } from 'next-intl/server';

export default async function IndexPage({ params }: { params: Promise<{ locale: string }> }) {
  const { locale } = await params;
  // 정적 페이지 빌드 생성을 위해 로케일 할당 의무 선언
  setRequestLocale(locale);

  const t = await getTranslations('blog');

  return (
    <main className="p-8">
      <h1 className="text-3xl font-bold">{t('title')}</h1>
      <p>{t('readMore')}</p>
    </main>
  );
}

자주 묻는 질문

generateMetadata 함수 내부에서도 next-intl 번역 텍스트를 적용해 검색엔진 메타태그 다국어 처리가 가능한가요?+

네, 완벽히 가능합니다. 메타데이터 생성용 헬퍼 함수 내부에서 `const t = await getTranslations({locale, namespace: 'meta'})` 형태로 호출해 넘겨받은 t 함수로 타이틀과 설명문을 지정해 주시면, 검색 봇이 수집할 때 로케일별 최적화된 메타 태그가 깔끔히 탑재됩니다.

next-intl 설정 후 일반 Link 컴포넌트 사용 시 locale 경로가 누락되어 언어 팩이 풀립니다. 해결책이 있나요?+

일반 `next/link` 모듈을 쓰면 언어 경로 누락이 생기므로, `i18n/routing.ts` 에서 export 해둔 커스텀 다국어 전용 Link 컴포넌트(`export const { Link, redirect, useRouter } = createNavigation(routing)`)를 import 해서 쓰셔야 현재 설정된 locale 경로를 자동으로 엮어 자연스럽게 이동시켜 줍니다.

관련 글