본문 바로가기
일상이 개발

Next.js 다국어(i18n) 전략 완전 정복 – locale 라우팅부터 번역 최적화까지 실전 가이드

by 아빠고미 2025. 5. 13.
반응형

Next.js 앱에서 다국어(i18n) 전략 완전 정복 – locale 구성, 언어 스위칭, 서버/클라이언트 렌더링 최적화

글로벌 시대, 제품이나 서비스의 확장은 다국어(i18n) 설계에서 시작됩니다.

Next.js는 기본적으로 i18n 지원을 내장하고 있으며, 클라이언트/서버 모두에서 효율적이고 SEO 친화적인 다국어 지원이 가능합니다.

이번 포스팅에서는 Next.js 기반 앱에서 i18n 전략을 전방위적으로 다루며, 단순한 번역을 넘어서 라우팅 설계, 언어 전환, 상태 유지, 렌더링 최적화까지 실무 중심으로 설명합니다.

  • ✅ Next.js 내장 i18n 설정
  • ✅ 번역 라이브러리별 비교 (next-intl, react-intl, i18next 등)
  • ✅ 다국어 라우팅과 SEO
  • ✅ 클라이언트/서버 렌더링 최적화
  • ✅ 언어 스위치 UX
  • ✅ 실전 프로젝트 설계 예시

1. 🌍 Next.js 내장 i18n 기능 이해하기

📦 기본 설정 방법

// next.config.js
module.exports = {
  i18n: {
    locales: ['en', 'ko', 'ja'],
    defaultLocale: 'en',
    localeDetection: true,
  },
};

✅ 구성 요소 설명

  • locales: 지원할 언어 목록
  • defaultLocale: 기본 언어
  • localeDetection: 브라우저 언어 감지 여부

🧭 URL 경로 구조

  • /en/about
  • /ko/about
  • /ja/about

➡️ 기본적으로 Next.js는 각 언어별로 라우팅이 나뉘며, SEO에 유리한 구조를 제공합니다.


2. ⚙️ 라우팅 전략 – 언어 기반 경로 설계

✅ Link 컴포넌트에서 locale 지정

import Link from 'next/link';

<Link href="/" locale="ko">
  한국어
</Link>

✅ 현재 언어 확인하기

import { useRouter } from 'next/router';

const { locale, locales, defaultLocale } = useRouter();

➡️ 이 데이터를 기반으로 언어 전환 버튼, 다국어 드롭다운 등을 구현할 수 있습니다.

✅ SSR 환경에서 locale 사용

export async function getServerSideProps(context) {
  const { locale } = context;

  return {
    props: {
      currentLocale: locale,
    },
  };
}

➡️ 서버 측에서도 사용자 언어에 따른 데이터를 미리 준비할 수 있습니다.

3. 📚 번역 라이브러리 비교 – 어떤 툴을 쓸까?

Next.js는 기본적인 locale 라우팅을 제공하지만, 실제 텍스트 번역을 위해서는 별도의 라이브러리가 필요합니다.

✅ 대표 라이브러리 비교

라이브러리 특징 SSR 지원
next-intl Next.js 전용, 간결한 API, SSR 친화적
i18next 가장 유연하고 강력하지만 설정이 복잡
react-intl 국제 표준 지원, 포맷팅 다양
next-translate 폴더 기반 번역 구조, 간편함

➡️ 복잡한 CMS 기반이 아니라면 next-intl이 가장 실용적입니다.


4. ✨ next-intl 실전 적용

✅ 설치

npm install next-intl

✅ app/layout.tsx 또는 _app.tsx에서 Provider 등록

// app/[locale]/layout.tsx
import { NextIntlClientProvider } from 'next-intl';

export default function LocaleLayout({ children, params: { locale } }) {
  const messages = await getMessages(locale); // JSON 불러오기
  return (
    <html lang={locale}>
      <body>
        <NextIntlClientProvider locale={locale} messages={messages}>
          {children}
        </NextIntlClientProvider>
      </body>
    </html>
  );
}

✅ JSON 번역 예시

// messages/ko.json
{
  "greeting": "안녕하세요",
  "login.button": "로그인"
}

✅ 컴포넌트에서 사용

import { useTranslations } from 'next-intl';

const t = useTranslations();

return <p>{t('greeting')}</p>;

➡️ 경로 기반으로 locale을 구분하고, 언어별로 메시지를 JSON으로 관리하면 번역 유지보수도 쉬워집니다.


5. 🧱 번역 구조 설계 – 유지보수 가능한 폴더 구조

✅ 구조 예시

/messages
  ├── en.json
  ├── ko.json
  ├── ja.json

📌 실무 팁

  • 파일이 너무 커질 경우 모듈 단위 분리 (예: common.json, auth.json 등)
  • key는 namespace.key 형식으로 구분
  • 디자인 시스템에 따라 번역 key를 UI 컴포넌트와 일치시키면 관리 효율 증가

6. 🌐 언어 자동 감지 및 초기 설정 전략

✅ 브라우저 언어 감지 활용

  • Next.js 기본 설정 localeDetection: true로 사용 가능
  • 브라우저의 navigator.language 값 활용

📌 사용자 초기 언어 설정 흐름

  1. 1. 브라우저 언어 확인
  2. 2. 지원 언어와 일치 여부 확인
  3. 3. /[lang] 경로로 리디렉션
// middleware.ts
import { NextResponse } from 'next/server';

export function middleware(req) {
  const { pathname, locale } = req.nextUrl;

  if (pathname === '/') {
    const lang = req.headers.get('accept-language')?.split(',')[0] || 'en';
    const targetLocale = ['en', 'ko', 'ja'].includes(lang) ? lang : 'en';
    return NextResponse.redirect(new URL(`/${targetLocale}`, req.url));
  }
  return NextResponse.next();
}

7. ⚡ 클라이언트/서버 최적화 – 성능을 해치지 않는 번역

✅ 클라이언트에서만 번역하면 생기는 문제

  • SEO에 불리
  • 초기 깜빡임 (hydrate mismatch)

✅ SSR or Static Rendering과 함께 쓰기

export async function getStaticProps({ locale }) {
  return {
    props: {
      messages: await import(`../messages/${locale}.json`),
    },
  };
}

✅ next-intl은 서버에서 미리 번역된 상태를 렌더링하므로 검색 엔진 친화적이고 사용자 UX도 부드럽습니다.


8. 🔎 다국어 SEO와 접근성 – 검색엔진도 언어를 읽는다

✅ hreflang 메타 태그

<link rel="alternate" href="https://example.com/en" hreflang="en" />
<link rel="alternate" href="https://example.com/ko" hreflang="ko" />

✅ 페이지 별 타이틀 및 설명

  • title, meta description도 각 언어별로 분기
// Head 컴포넌트에서
<title>{t('page.title')}</title>
<meta name="description" content={t('page.description')} />

9. 🧠 마무리 – 다국어 설계는 글로벌 UX의 시작

✅ 총정리

  • Next.js의 i18n 설정으로 기본 라우팅 구조 확보
  • next-intl 또는 i18next로 다국어 번역 구현
  • 클라이언트와 서버 렌더링을 함께 고려해 깜빡임 방지
  • SEO와 접근성을 위한 메타 태그, 번역 타이틀 처리
  • 브라우저 언어 감지 및 초기 locale 리디렉션 구현

✅ 실무 팁

  • 언어 전환 시 새로고침 없는 라우팅 유지
  • fallback 언어 체계 정립
  • 문구 변경이 잦은 경우 번역 플랫폼 연동 검토 (Crowdin, Phrase 등)

긴 글 읽어주셔서 감사합니다! 공감, 댓글, 공유로 응원해주시면 다음 글 제작에 큰 힘이 됩니다 🙌

반응형