이 페이지와 원하는 AI 어시스턴트를 사용하여 문서를 요약합니다
이 페이지의 콘텐츠는 AI를 사용하여 번역되었습니다.
영어 원본 내용의 최신 버전을 보기If you have an idea for improving this documentation, please feel free to contribute by submitting a pull request on GitHub.
GitHub link to the documentationCopy doc Markdown to clipboard
새로운 Intlayer v9 - 무엇이 달라졌나요?
Intlayer v9에 오신 것을 환영합니다! 이번 메이저 릴리스는 주요 i18n 라이브러리(react-i18next, next-intl, vue-i18n 등)를 위한 호환 어댑터 패키지(Compat Adapter Packages)를 통해 Intlayer로의 마이그레이션 경로를 획기적으로 단순화하고, 컬렉션(Collections) 및 베리언트(Variants)와 같은 풍부한 콘텐츠 구조 지원을 추가하는 큰 이정표를 세웠습니다.
목차
호환 어댑터 패키지 (Compat Adapter Packages)
인기 있는 i18n 라이브러리에서 Intlayer로 마이그레이션하는 것이 그 어느 때보다 쉬워졌습니다. 표준 i18n 라이브러리와 완전히 동일한 공개 API를 노출하면서 런타임 시 모든 번역 작업을 Intlayer에 위임하는 5개의 호환 패키지를 출시했습니다.
엄격한 타입 지정을 통한 동일한 공개 API 노출
임포트(import) 경로를 바꾸는 것만으로, 최소한의 코드 변경을 통해 실제 딕셔너리에 대한 컴파일 타임 타입 안전성을 포함한 Intlayer의 모든 이점을 누릴 수 있습니다:
@intlayer/i18next@intlayer/react-i18next@intlayer/next-intl@intlayer/react-intl@intlayer/next-i18next@intlayer/vue-i18n@intlayer/lingui
예를 들어, 다음과 같이 간단히 변경하면 됩니다:
코드를 클립보드에 복사
import { useTranslation } from "react-i18next";을 다음과 같이 변경합니다:
코드를 클립보드에 복사
import { useTranslation } from "@intlayer/react-i18next";이제 키는 Intlayer 딕셔너리에 대해 엄격하게 타입 지정(strictly typed)되어 IDE에서 완전한 점 표기법(dot-path) 자동 완성을 제공합니다!
번들러 에일리어스 플러그인 (Vite, Next.js, Turbopack)
모든 임포트 문을 수동으로 다시 작성하지 않고도 마이그레이션할 수 있도록, 각 호환 어댑터 패키지에는 /plugin 서브패스 아래에 커스텀 번들러 플러그인(Vite 또는 Next.js)이 포함되어 있습니다.
이 플러그인들은 빌드 타임에 기존 임포트(예: react-i18next 또는 next-intl)를 그에 해당하는 @intlayer/* 패키지로 자동 변환합니다.
Next.js (Webpack / Turbopack) 예시
withIntlayer 대신, Next.js 설정을 호환 플러그인으로 감싸세요:
코드를 클립보드에 복사
import { createNextI18nPlugin } from "@intlayer/next-i18next/plugin";import type { NextConfig } from "next";const withIntlayer = createNextI18nPlugin();const nextConfig: NextConfig = {};export default withIntlayer(nextConfig);Vite (React, Vue, Solid, Svelte) 예시
코드를 클립보드에 복사
import vueI18nVitePlugin from "@intlayer/vue-i18n/plugin";export default defineConfig({ plugins: [vueI18nVitePlugin()],});통합 런타임 리졸버 (Mutualized Runtime Resolver)
모든 호환 어댑터는 이제 고도로 최적화된 단일 런타임 파서인 @intlayer/core/messageFormat을 통해 번역 해석을 라우팅합니다.
- 메시지 보간 (Interpolate Message): 표준
{{var}}(공백 및 점 표기법 경로), ICU 포맷 인수 ({v, number, percent}등), 그리고 기본{var}템플릿을 해석합니다. - 메시지 노드 리졸버 (Message Node Resolver): 중첩된 노드들을 해석합니다:
insert(),plural()(CLDR 복수형 규칙),enu()(열거형),gender(), HTML 태그, 배열, 그리고 호출 가능한 함수 노드. - 토큰화된 태그 파서 (Tokenized Tag Parser): 인라인 XML/HTML 태그 및 번호가 매겨진 태그(예:
<1>children</1>)를 지원하여 서식 있는 텍스트(rich-text) 렌더링을 기본적으로 지원합니다.
기능 사양: 컬렉션 및 베리언트
Intlayer v9은 정적인 키-값 객체를 넘어, 딕셔너리가 처음부터 끝까지 완전히 타입 지정된 동적 레이아웃 구조를 선언할 수 있도록 확장되었습니다.
1. 컬렉션 (Collections)
CMS에서 관리하는 순서가 있는 아이템 목록(예: FAQ, 제품 또는 블로그 목록)을 정의합니다:
코드를 클립보드에 복사
import { t, type Dictionary } from "intlayer";export default { key: "faq", item: 1, content: { question: t({ en: "What is Intlayer?", fr: "Qu'est-ce qu'Intlayer ?" }), answer: t({ en: "An i18n toolkit.", fr: "Une boîte à outils i18n." }), },} satisfies Dictionary;코드를 클립보드에 복사
import { t, type Dictionary } from "intlayer";export default { key: "faq", item: 2, content: { question: t({ en: "Is it free?", fr: "Est-ce gratuit ?" }), answer: t({ en: "Yes, open-source.", fr: "Oui, open-source." }), },} satisfies Dictionary;사용법:
코드를 클립보드에 복사
// Fetch all items as an arrayconst allFaqs = useIntlayer("faq"); // -> { question: string, answer: string }[]// Fetch a single item by indexconst faq = useIntlayer("faq", { item: 2 }); // -> { question: string, answer: string }2. 베리언트 (Variants)
A/B 테스트, 시즌별 헤더, 피처 플래그(feature flags) 또는 커스텀 랜딩 페이지를 제공합니다:
문자열 베리언트 (예: A/B 테스트)
코드를 클립보드에 복사
import { t, type Dictionary } from "intlayer";export default { key: "hero-banner", variant: "default", content: { control: t({ ko: "환영합니다", en: "Welcome", fr: "Bienvenue" }), black_friday: t({ ko: "지금 쇼핑하기", en: "Shop now", fr: "Acheter maintenant", }), },} satisfies Dictionary;사용법:
코드를 클립보드에 복사
const banner = useIntlayer("hero-banner", { variant: "black_friday" });객체 베리언트 (예: 동적 레코드)
코드를 클립보드에 복사
import { t, type Dictionary } from "intlayer";export default { key: "product-copy", variant: { id: "prod_123", category: "books", }, content: { title: t({ ko: "클린 코드", en: "Clean Code", fr: "Code Propre" }), },} satisfies Dictionary;사용법:
코드를 클립보드에 복사
// 요청된 아이템만 동적으로 가져옵니다 (Suspense 필요)const product = useIntlayer("product-copy", { variant: { id: "prod_123", category: "books" },});Vite Plugin: 번들된 컴파일러 & 프록시
intlayer() Vite 플러그인은 이제 컴파일러와 로케일 라우팅 프록시를 직접 번들로 제공하므로, 대부분의 프로젝트는 vite.config.ts에서 단일 플러그인만 필요합니다:
코드를 클립보드에 복사
import { defineConfig } from "vite";import { intlayer } from "vite-intlayer";export default defineConfig({ plugins: [intlayer()],});- Compiler:
compiler.enabled가true로 설정되고compiler.output경로가 구성되면 자동으로 활성화됩니다. 더 이상intlayerCompiler()를 별도로 등록할 필요가 없습니다. - Proxy: 새로운
routing.enableProxy옵션(기본값: true)을 기반으로 자동으로 활성화됩니다. 개발, 미리보기 및 프로덕션 SSR에서 로케일 감지 / 리다이렉트 / 재작성 미들웨어를 연결합니다. 더 이상intlayerProxy()를 별도로 등록할 필요가 없습니다.
routing.enableProxy 옵션
새로운 routing.enableProxy 옵션은 locale-routing proxy가 연결되는지 여부를 제어합니다. 기본값은 true입니다. locale routing을 직접 처리하고 싶을 때 비활성화하세요:
코드를 클립보드에 복사
import type { IntlayerConfig } from "intlayer";const config: IntlayerConfig = { routing: { enableProxy: false, // 기본값: true },};export default config;독립형 intlayerCompiler() 및 intlayerProxy() 플러그인은 고급 설정을 위해 계속 내보내집니다. 이들을 intlayer()와 함께 등록하는 것은 안전합니다 — 각 플러그인은 자동으로 중복을 제거하고 한 번만 실행됩니다.
컴파일러는 기본적으로 비활성화
Intlayer v9부터 컴파일러는 기본적으로 비활성화됩니다(compiler.enabled의 기본값이 이제 false입니다). .content.ts 파일의 빌드 타임 추출을 활성화하려면 구성에서 compiler.enabled: true를 설정하세요:
코드를 클립보드에 복사
import type { IntlayerConfig } from "intlayer";const config: IntlayerConfig = { compiler: { enabled: true, // 기본값: false — v9부터 컴파일러를 활성화하는 데 필요 output: ({ fileName }) => `./${fileName}.content.ts`, },};export default config;컴파일러가 비활성화되면 Intlayer는 빌드 타임 추출 단계를 건너뛰고 이미 선언한 딕셔너리에 의존합니다. 번들러 플러그인(@intlayer/swc, @intlayer/babel 또는 intlayer() Vite 플러그인)이 콘텐츠를 자동으로 추출하기를 원할 때만 활성화하세요.
React Native: 단일 패키지 임포트
React Native 또는 Expo 앱에서는 더 이상 react-intlayer와 react-native-intlayer를 번갈아 사용할 필요가 없습니다. react-native-intlayer 패키지는 이제 react-intlayer의 전체 API를 다시 내보내며 (훅, 유틸리티 및 /format, /html, /markdown 하위 경로), IntlayerProvider는 React Native 폴리필을 자동으로 적용합니다.
단일 react-native-intlayer 패키지에서 모든 것을 임포트하세요:
코드를 클립보드에 복사
import { IntlayerProvider, useIntlayer, useLocale,} from "react-native-intlayer";코드를 클립보드에 복사
npm install intlayer react-native-intlayerreact-intlayer에서 임포트하는 것도 계속 작동하지만, 이제 React Native에 권장되는 단일 진입점은react-native-intlayer입니다. 이 패키지의 프로바이더는 웹 지향적인react-intlayer프로바이더에는 없는 폴리필을 제공합니다.
CMS SDK: Intlayer를 헤드리스 콘텐츠 데이터베이스로 사용하기
Intlayer v9는 CMS를 프로그래밍 방식으로 다루기 위한 깔끔하고 자동 인증되는 SDK를 @intlayer/api에 포함합니다. 프로젝트 가져오기, 사전 가져오기, 그리고 자체 서버·스크립트·CI에서의 푸시 또는 업데이트가 가능합니다. 인증(OAuth2 client_credentials)은 자동으로 처리되고 갱신됩니다.
SDK는 두 개의 분리된 import로 나뉘어, 실제로 사용하는 도메인만 번들에 포함됩니다:
createIntlayerCMS— 자격 증명과 관리되는 토큰을 보유하는 가벼운 인증기(도메인 클라이언트는 번들되지 않음).dictionaryEndpoint,projectEndpoint, … — 도메인별 엔드포인트 바인더로, 각각 자체 서브패스에서 가져옵니다.
코드를 클립보드에 복사
import { createIntlayerCMS } from "@intlayer/api";import { dictionaryEndpoint } from "@intlayer/api/dictionary";// 구성은 선택 사항입니다: 자격 증명은 INTLAYER_CLIENT_ID /// INTLAYER_CLIENT_SECRET(`@intlayer/config/built`로 해석됨)로 폴백됩니다.const cms = createIntlayerCMS();// 읽기const { data: dictionaries } = await dictionaryEndpoint(cms).getDictionaries();// 쓰기 — CMS를 데이터베이스처럼 사용await dictionaryEndpoint(cms).pushDictionaries([myDictionary]);보안: CMS 자격 증명은 콘텐츠에 대한 쓰기 권한을 부여합니다. 인증기는 항상 서버 측에서만 생성하고,clientId/clientSecret을 브라우저로 절대 보내지 마세요.
v8에서의 마이그레이션 노트
v8에서 업그레이드하는 경우, v9에는 하위 호환성을 깨뜨리는 변경 사항(breaking changes)이 포함되어 있지 않습니다. 하지만 다음과 같은 주요 변경 사항이 있습니다:
- 컴파일러는 기본적으로 비활성화:
compiler.enabled의 기본값이 이제false입니다..content.ts파일의 빌드 타임 추출에 의존하는 경우intlayer.config.ts에서compiler.enabled: true를 설정하세요. - 로케일 및 다이얼렉트 (Locales & Dialects): 외부 i18n 의존성을 사용하는 경우, 설정 또는 번들러 구성에 해당 호환 어댑터 플러그인을 추가하여 임포트를 자동으로 변환하세요.
- 커스텀 셀렉터 (Custom Selectors):
useIntlayer를 호출할 때 두 번째 매개변수는 이제{ locale, item, variant }를 포함하는 옵션 객체 전용으로 예약됩니다. 이전에 로케일 문자열을 직접 전달했다면 여전히 그렇게 사용할 수 있지만, 고급 선택을 위해서는 옵션 객체를 사용하는 것을 권장합니다.