icon안동민 개발노트

국제화 (i18n) 구현


 Next.js App Router를 사용하는 애플리케이션에서 다국어 지원을 구현하는 것은 글로벌 사용자 기반을 확보하는 데 중요합니다.

 이 절에서는 next-intl 라이브러리를 사용하여 효율적인 국제화 솔루션을 구현하는 방법을 알아보겠습니다.

next-intl 설정

 1. 라이브러리 설치

npm install next-intl

 2. 다국어 설정 파일 생성 (i18n.js)

i18n.js
import {notFound} from 'next/navigation';
import {getRequestConfig} from 'next-intl/server';
 
export default getRequestConfig(async ({locale}) => {
  if (!['en', 'ko'].includes(locale)) notFound();
 
  return {
    messages: (await import(`./messages/${locale}.json`)).default
  };
});

 3. next.config.js 수정

next.config.js
const withNextIntl = require('next-intl/plugin')();
 
module.exports = withNextIntl({
  // 기타 Next.js 설정
});

언어 파일 구조화

 messages 디렉토리에 각 언어별 JSON 파일을 생성합니다.

messages/en.json
{
  "hello": "Hello",
  "welcome": "Welcome to our site"
}
messages/ko.json
{
  "hello": "안녕하세요",
  "welcome": "우리 사이트에 오신 것을 환영합니다"
}

서버 컴포넌트에서의 번역 처리

import {useTranslations} from 'next-intl';
 
export default function ServerComponent() {
  const t = useTranslations('Index');
  return <h1>{t('title')}</h1>;
}

클라이언트 컴포넌트에서의 번역 처리

'use client';
 
import {useTranslations} from 'next-intl';
 
export default function ClientComponent() {
  const t = useTranslations('Index');
  return <button>{t('button.label')}</button>;
}

동적 라우팅을 활용한 언어 전환

 1. app 디렉토리 구조 설정

app
├── [locale]
│   ├── layout.js
│   ├── page.js
│   └── [...rest]
│       └── page.js
└── i18n.js

 2. 동적 라우트 구현 (app/[locale]/layout.js)

app/[locale]/layout.js
import {useLocale} from 'next-intl';
import {notFound} from 'next/navigation';
 
export default function LocaleLayout({children, params}) {
  const locale = useLocale();
 
  // Validate that the incoming `locale` parameter is valid
  if (params.locale !== locale) {
    notFound();
  }
 
  return (
    <html lang={locale}>
      <body>{children}</body>
    </html>
  );
}

 3. 언어 전환 링크 구현

import {useTranslations} from 'next-intl';
import {Link} from 'next-intl';
 
export default function LocaleSwitcher() {
  const t = useTranslations('LocaleSwitcher');
 
  return (
    <ul>
      <li>
        <Link href="/" locale="en">
          {t('en')}
        </Link>
      </li>
      <li>
        <Link href="/" locale="ko">
          {t('ko')}
        </Link>
      </li>
    </ul>
  );
}

SEO를 고려한 다국어 메타데이터 설정

import {useTranslations} from 'next-intl';
 
export function generateMetadata({params: {locale}}) {
  const t = useTranslations('Metadata');
 
  return {
    title: t('title'),
    description: t('description'),
    openGraph: {
      title: t('og.title'),
      description: t('og.description'),
    },
  };
}

13장 SEO 및 메타데이터와의 연관성

 16장의 국제화 구현은 13장에서 다룬 SEO 및 메타데이터와 밀접하게 연관됩니다.

 다국어 지원은 각 언어별로 최적화된 메타데이터를 제공함으로써 검색 엔진 최적화에 크게 기여합니다.

 특히, generateMetadata 함수를 사용하여 동적으로 다국어 메타데이터를 생성하는 방식은 SEO 성능을 향상시키는 데 중요한 역할을 합니다.

실습 : 다국어 블로그 페이지 구현

 동적 라우팅을 사용하여 다국어 블로그 페이지를 구현하고, 언어 전환 기능을 추가해보세요.

  1. 프로젝트 구조 설정
app
├── [locale]
│   ├── blog
│   │   ├── [slug]
│   │   │   └── page.js
│   │   └── page.js
│   ├── layout.js
│   └── page.js
├── i18n.js
└── messages
    ├── en.json
    └── ko.json
  1. 블로그 페이지 구현 (app/[locale]/blog/page.js)
app/[locale]/blog/page.js
import {useTranslations} from 'next-intl';
import {Link} from 'next-intl';
 
export default function BlogPage() {
  const t = useTranslations('Blog');
 
  const posts = [
    { id: 1, title: t('post1.title'), slug: 'first-post' },
    { id: 2, title: t('post2.title'), slug: 'second-post' },
  ];
 
  return (
    <div>
      <h1>{t('title')}</h1>
      <ul>
        {posts.map(post => (
          <li key={post.id}>
            <Link href={`/blog/${post.slug}`}>{post.title}</Link>
          </li>
        ))}
      </ul>
    </div>
  );
}
  1. 블로그 포스트 페이지 구현 (app/[locale]/blog/[slug]/page.js)
app/[locale]/blog/[slug]/page.js
import {useTranslations} from 'next-intl';
 
export default function BlogPost({params}) {
  const t = useTranslations(`Blog.posts.${params.slug}`);
 
  return (
    <article>
      <h1>{t('title')}</h1>
      <p>{t('content')}</p>
    </article>
  );
}
  1. 언어 전환 컴포넌트 구현 및 레이아웃에 추가
app/[locale]/components/LocaleSwitcher.js
'use client';
 
import {usePathname} from 'next-intl/client';
import {Link, useLocale} from 'next-intl';
 
export default function LocaleSwitcher() {
  const pathname = usePathname();
  const locale = useLocale();
 
  return (
    <div>
      <Link href={pathname} locale="en">English</Link>
      <Link href={pathname} locale="ko">한국어</Link>
    </div>
  );
}
app/[locale]/layout.js
import LocaleSwitcher from './components/LocaleSwitcher';
 
export default function Layout({children}) {
  return (
    <div>
      <LocaleSwitcher />
      {children}
    </div>
  );
}
  1. 번역 파일 업데이트
messages/en.json
{
  "Blog": {
    "title": "Blog",
    "post1": {
      "title": "First Post"
    },
    "post2": {
      "title": "Second Post"
    },
    "posts": {
      "first-post": {
        "title": "First Post",
        "content": "This is the content of the first post."
      },
      "second-post": {
        "title": "Second Post",
        "content": "This is the content of the second post."
      }
    }
  }
}
messages/ko.json
{
  "Blog": {
    "title": "블로그",
    "post1": {
      "title": "첫 번째 글"
    },
    "post2": {
      "title": "두 번째 글"
    },
    "posts": {
      "first-post": {
        "title": "첫 번째 글",
        "content": "이것은 첫 번째 글의 내용입니다."
      },
      "second-post": {
        "title": "두 번째 글",
        "content": "이것은 두 번째 글의 내용입니다."
      }
    }
  }
}

 이 실습을 통해 Next.js App Router 환경에서 동적 라우팅을 활용한 다국어 웹사이트를 구현하고 언어 전환 기능을 추가하는 방법을 경험할 수 있습니다.

 이는 실제 다국어 웹사이트 구축에 필요한 핵심 기술을 포함하고 있습니다.

 Next.js App Router를 사용한 국제화 구현은 글로벌 사용자 기반을 확보하고 다양한 언어권의 사용자에게 최적화된 경험을 제공하는 데 중요합니다.

 동적 라우팅을 활용한 언어 전환, 효율적인 번역 관리, 그리고 SEO를 고려한 메타데이터 설정을 통해 높은 품질의 다국어 웹 애플리케이션을 구축할 수 있습니다.