์ž‘๊ฐ€:
    ์ƒ์„ฑ:2025-06-18๋งˆ์ง€๋ง‰ ์—…๋ฐ์ดํŠธ:2026-09-27

    Expo ๋ฐ React Native ์•ฑ ๋ฒˆ์—ญํ•˜๊ธฐ

    ide.intlayer.org
    intlayer-react-native.vercel.app

    ๋ชฉ์ฐจ

    ๋Œ€์•ˆ ๋Œ€๋น„ Intlayer๋ฅผ ์„ ํƒํ•˜๋Š” ์ด์œ 

    react-native-localize๋‚˜ i18next์™€ ๊ฐ™์€ ์ฃผ์š” ์†”๋ฃจ์…˜๊ณผ ๋น„๊ตํ–ˆ์„ ๋•Œ, Intlayer๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ํ†ตํ•ฉ ์ตœ์ ํ™” ๊ธฐ๋Šฅ์„ ๊ฐ–์ถ˜ ์†”๋ฃจ์…˜์ž…๋‹ˆ๋‹ค:

    Intlayer๋Š” React Native์™€ Expo์—์„œ ์™„๋ฒฝํ•˜๊ฒŒ ์ž‘๋™ํ•˜๋„๋ก ์ตœ์ ํ™”๋˜์–ด ์žˆ์œผ๋ฉฐ, ์ปดํฌ๋„ŒํŠธ ์ˆ˜์ค€์˜ ์ฝ˜ํ…์ธ  ๋ฒ”์œ„ ์ง€์ •, TypeScript ์ง€์›, ๊ทธ๋ฆฌ๊ณ  ๋ชจ๋ฐ”์ผ ์•ฑ์—์„œ ๊ตญ์ œํ™”(i18n)๋ฅผ ํ™•์žฅํ•˜๋Š” ๋ฐ ํ•„์š”ํ•œ ๋ชจ๋“  ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

    ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์ฝ˜ํ…์ธ  ๋ฒ”์œ„๋ฅผ ์ง€์ •ํ•˜๋ฉด ๋Œ€๊ทœ๋ชจ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์œ ์ง€ ๋ณด์ˆ˜๊ฐ€ ์šฉ์ดํ•ด์ง‘๋‹ˆ๋‹ค. ์ „์ฒด ์ฝ˜ํ…์ธ  ์ฝ”๋“œ๋ฒ ์ด์Šค๋ฅผ ๊ฒ€ํ† ํ•ด์•ผ ํ•˜๋Š” ๋ถ€๋‹ด ์—†์ด ๋‹จ์ผ ๊ธฐ๋Šฅ ํด๋”๋ฅผ ๋ณต์ œํ•˜๊ฑฐ๋‚˜ ์‚ญ์ œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ Intlayer๋Š” ์ฝ˜ํ…์ธ ์˜ ์ •ํ™•์„ฑ์„ ๋ณด์žฅํ•˜๊ธฐ ์œ„ํ•ด ์™„์ „ํžˆ ํƒ€์ž…์ด ์ง€์ •๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.

    ์ฝ˜ํ…์ธ ๋ฅผ ํ•จ๊ป˜ ๋ฐฐ์น˜ํ•˜๋ฉด ๋Œ€ํ˜• ์–ธ์–ด ๋ชจ๋ธ(LLM)์— ํ•„์š”ํ•œ ์ปจํ…์ŠคํŠธ๊ฐ€ ์ค„์–ด๋“ญ๋‹ˆ๋‹ค. Intlayer๋Š” ๋ˆ„๋ฝ๋œ ๋ฒˆ์—ญ์„ ํ…Œ์ŠคํŠธํ•˜๊ธฐ ์œ„ํ•œ CLI, LSP, MCP, agent skills ๋“ฑ์˜ ๋„๊ตฌ ๋ชจ์Œ์„ ์ œ๊ณตํ•˜์—ฌ AI ์—์ด์ „ํŠธ๋ฅผ ์œ„ํ•œ ๊ฐœ๋ฐœ์ž ๊ฒฝํ—˜(DX)์„ ๋”์šฑ ์›ํ™œํ•˜๊ฒŒ ํ•ฉ๋‹ˆ๋‹ค.

    AI ์ œ๊ณต์—…์ฒด ๋น„์šฉ์œผ๋กœ ์›ํ•˜๋Š” LLM์„ ์‚ฌ์šฉํ•˜์—ฌ CI/CD ํŒŒ์ดํ”„๋ผ์ธ์—์„œ ์ž๋™ํ™”๋กœ ๋ฒˆ์—ญํ•˜์„ธ์š”. Intlayer๋Š” ์ฝ˜ํ…์ธ  ์ถ”์ถœ์„ ์ž๋™ํ™”ํ•˜๋Š” ์ปดํŒŒ์ผ๋Ÿฌ์™€ ๋ฐฑ๊ทธ๋ผ์šด๋“œ์—์„œ ๋ฒˆ์—ญ์„ ๋„์™€์ฃผ๋Š” ์›น ํ”Œ๋žซํผ๋„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

    ๋Œ€์šฉ๋Ÿ‰ JSON ํŒŒ์ผ์„ ์ปดํฌ๋„ŒํŠธ์— ์—ฐ๊ฒฐํ•˜๋ฉด ์„ฑ๋Šฅ ๋ฐ ๋ฐ˜์‘์„ฑ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. Intlayer๋Š” ๋นŒ๋“œ ์‹œ ์ฝ˜ํ…์ธ  ๋กœ๋”ฉ์„ ์ตœ์ ํ™”ํ•ฉ๋‹ˆ๋‹ค.

    ๋‹จ์ˆœํ•œ i18n ์†”๋ฃจ์…˜ ์ด์ƒ์œผ๋กœ, Intlayer๋Š” ๋ฒˆ์—ญ์‚ฌ, ์นดํ”ผ๋ผ์ดํ„ฐ, ๊ธฐํƒ€ ํŒ€์›๋“ค๊ณผ์˜ ํ˜‘์—…์„ ์›ํ™œํ•˜๊ฒŒ ํ•˜๋Š” ์ž์ฒด ํ˜ธ์ŠคํŒ… ๋น„์ฃผ์–ผ ์—๋””ํ„ฐ์™€ ์™„์ „ํ•œ CMS๋ฅผ ์ œ๊ณตํ•˜์—ฌ ๋‹ค๊ตญ์–ด ์ฝ˜ํ…์ธ ๋ฅผ ์‹ค์‹œ๊ฐ„์œผ๋กœ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ฉ๋‹ˆ๋‹ค. ์ฝ˜ํ…์ธ ๋Š” ๋กœ์ปฌ ๋ฐ/๋˜๋Š” ์›๊ฒฉ์œผ๋กœ ์ €์žฅํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

    ํŽ˜์ด์ง€์— ๋Œ€์šฉ๋Ÿ‰ JSON ํŒŒ์ผ์„ ๋กœ๋“œํ•˜๋Š” ๋Œ€์‹  ํ•„์š”ํ•œ ์ฝ˜ํ…์ธ ๋งŒ ๋กœ๋“œํ•˜์„ธ์š”. Intlayer๋Š” ๋ฒˆ๋“ค ๋ฐ ๋ทฐ ํฌ๊ธฐ๋ฅผ ์ตœ๋Œ€ 50%๊นŒ์ง€ ์ค„์ด๋Š” ๋ฐ ๋„์›€์„ ์ค๋‹ˆ๋‹ค.

    1. ์˜์กด์„ฑ ์„ค์น˜

      GitHub์—์„œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ํ…œํ”Œ๋ฆฟ์„ ์ฐธ์กฐํ•˜์„ธ์š”.

      React Native ํ”„๋กœ์ ํŠธ์—์„œ ๋‹ค์Œ ํŒจํ‚ค์ง€๋“ค์„ ์„ค์น˜ํ•˜์„ธ์š”:

      bash
      npx intlayer init --interactive
      
      --interactive ํ”Œ๋ž˜๊ทธ๋Š” ์„ ํƒ ์‚ฌํ•ญ์ž…๋‹ˆ๋‹ค. AI ์—์ด์ „ํŠธ์ธ ๊ฒฝ์šฐ intlayer-cli init๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”.
      ์ด ๋ช…๋ น์€ ํ™˜๊ฒฝ์„ ๊ฐ์ง€ํ•˜๊ณ  ํ•„์š”ํ•œ ํŒจํ‚ค์ง€๋ฅผ ์„ค์น˜ํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด:
      bash
      npm install intlayer react-native-intlayer
      

      ํŒจํ‚ค์ง€

      • intlayer
        ๊ตฌ์„ฑ, ์‚ฌ์ „ ์ฝ˜ํ…์ธ , ์œ ํ˜• ์ƒ์„ฑ ๋ฐ CLI ๋ช…๋ น์„ ์œ„ํ•œ ํ•ต์‹ฌ i18n ํˆดํ‚ท์ž…๋‹ˆ๋‹ค.

      • react-native-intlayer
        ๋กœ์ผ€์ผ์„ ์–ป๊ณ  ์ „ํ™˜ํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉํ•  ์ปจํ…์ŠคํŠธ ํ”„๋กœ๋ฐ”์ด๋”์™€ React ํ›…, React Native ํด๋ฆฌํ•„, ๊ทธ๋ฆฌ๊ณ  Intlayer๋ฅผ React Native ๋ฒˆ๋“ค๋Ÿฌ์™€ ํ†ตํ•ฉํ•˜๊ธฐ ์œ„ํ•œ Metro ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ์ œ๊ณตํ•˜๋Š” React Native ํ†ตํ•ฉ์ž…๋‹ˆ๋‹ค. react-intlayer์˜ ๋ชจ๋“  ๊ฒƒ์„ ์žฌ๋‚ด๋ณด๋‚ด๋ฏ€๋กœ React Native ์•ฑ์—์„œ๋Š” ์ด ๋‹จ์ผ ํŒจํ‚ค์ง€๋งŒ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

    2. Intlayer ๊ตฌ์„ฑ ์ƒ์„ฑ

      ์•„ํ‚คํ…์ฒ˜

      ์ด ์•„ํ‚คํ…์ฒ˜์—์„œ๋Š” react-native-intlayer๊ฐ€ ๋ฃจํŠธ IntlayerProvider์™€ React Native ํ›…์„ ์ œ๊ณตํ•˜์—ฌ ํ™”๋ฉด๊ณผ ์ปดํฌ๋„ŒํŠธ ์ „๋ฐ˜์—์„œ ๋ฒˆ์—ญ์„ ๊ด€๋ฆฌํ•ฉ๋‹ˆ๋‹ค. ์ฝ˜ํ…์ธ  ์„ ์–ธ์€ ํ•ด๋‹น ์ปดํฌ๋„ŒํŠธ์™€ ํ•จ๊ป˜ ๋ฐฐ์น˜๋ฉ๋‹ˆ๋‹ค.

      bash
      .
      โ”œโ”€โ”€ app
      โ”‚   โ”œโ”€โ”€ (tabs)
      โ”‚   โ”‚   โ”œโ”€โ”€ _layout.tsx
      โ”‚   โ”‚   โ”œโ”€โ”€ explore.tsx
      โ”‚   โ”‚   โ””โ”€โ”€ index.tsx
      โ”‚   โ”œโ”€โ”€ +not-found.tsx
      โ”‚   โ””โ”€โ”€ _layout.tsx                   # Root layout with IntlayerProvider
      โ”œโ”€โ”€ components
      โ”‚   โ”œโ”€โ”€ LocaleSwitcher.content.ts
      โ”‚   โ””โ”€โ”€ LocaleSwitcher.tsx
      โ”œโ”€โ”€ app.json
      โ”œโ”€โ”€ intlayer.config.ts
      โ”œโ”€โ”€ metro.config.js
      โ”œโ”€โ”€ package.json
      โ””โ”€โ”€ tsconfig.json
      

      ์„ค์ •

      ํ”„๋กœ์ ํŠธ ๋ฃจํŠธ(๋˜๋Š” ์ ์ ˆํ•œ ๊ณณ)์— Intlayer ๊ตฌ์„ฑ ํŒŒ์ผ์„ ์ƒ์„ฑํ•˜์„ธ์š”. ์˜ˆ์‹œ:

      intlayer.config.ts
      /**
       * Locales ํƒ€์ž…์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๋Š” ๊ฒฝ์šฐ, tsconfig.json์—์„œ moduleResolution์„ "bundler"๋กœ ์„ค์ •ํ•ด ๋ณด์„ธ์š”
       */
      import { Locales, type IntlayerConfig } from "intlayer";
      
      const config: IntlayerConfig = {
        internationalization: {
          locales: [
            Locales.ENGLISH,
            Locales.FRENCH,
            Locales.SPANISH,
            // ... ํ•„์š”ํ•œ ๋‹ค๋ฅธ ๋กœ์ผ€์ผ ์ถ”๊ฐ€
          ],
          defaultLocale: Locales.ENGLISH,
        },
      };
      
      export default config;
      

      ์ด ๊ตฌ์„ฑ์—์„œ ๋‹ค์Œ์„ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:

      • ์ง€์›๋˜๋Š” ๋กœ์ผ€์ผ ๋ชฉ๋ก ๊ตฌ์„ฑ.
      • ๊ธฐ๋ณธ ๋กœ์ผ€์ผ ์„ค์ •.
      • ๋‚˜์ค‘์— ๋” ๋งŽ์€ ๊ณ ๊ธ‰ ์˜ต์…˜(๋กœ๊ทธ, ์‚ฌ์šฉ์ž ์ •์˜ ์ฝ˜ํ…์ธ  ๋””๋ ‰ํ† ๋ฆฌ ๋“ฑ)์„ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
      • ์ž์„ธํ•œ ๋‚ด์šฉ์€ Intlayer ๊ตฌ์„ฑ ๋ฌธ์„œ๋ฅผ ์ฐธ์กฐํ•˜์„ธ์š”.
    3. Metro ํ”Œ๋Ÿฌ๊ทธ์ธ ์ถ”๊ฐ€

      Metro๋Š” React Native์˜ ๋ฒˆ๋“ค๋Ÿฌ์ž…๋‹ˆ๋‹ค. react-native init ๋ช…๋ น์œผ๋กœ ์ƒ์„ฑ๋œ React Native ํ”„๋กœ์ ํŠธ์˜ ๊ธฐ๋ณธ ๋ฒˆ๋“ค๋Ÿฌ์ž…๋‹ˆ๋‹ค. Intlayer๋ฅผ Metro์™€ ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜๋ ค๋ฉด metro.config.js ํŒŒ์ผ์— ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ์ถ”๊ฐ€ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค:

      metro.config.js
      const { getDefaultConfig } = require("expo/metro-config");
      const { configMetroIntlayer } = require("react-native-intlayer/metro");
      
      module.exports = (async () => {
        const defaultConfig = getDefaultConfig(__dirname);
      
        return await configMetroIntlayer(defaultConfig);
      })();
      

      ์ฐธ๊ณ : configMetroIntlayer๋Š” Promise ํ•จ์ˆ˜์ž…๋‹ˆ๋‹ค. ๋™๊ธฐ์ ์œผ๋กœ ์‚ฌ์šฉํ•˜๊ฑฐ๋‚˜ IIFE(์ฆ‰์‹œ ํ˜ธ์ถœ ํ•จ์ˆ˜ ํ‘œํ˜„์‹)๋ฅผ ํ”ผํ•˜๋ ค๋ฉด configMetroIntlayerSync๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”. ์ฐธ๊ณ : configMetroIntlayerSync๋Š” ์„œ๋ฒ„ ์‹œ์ž‘ ์‹œ intlayer ์‚ฌ์ „ ๋นŒ๋“œ๋ฅผ ํ—ˆ์šฉํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

    4. Intlayer ํ”„๋กœ๋ฐ”์ด๋” ์ถ”๊ฐ€

      ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ „์ฒด์—์„œ ์‚ฌ์šฉ์ž ์–ธ์–ด๋ฅผ ๋™๊ธฐํ™”ํ•˜๋ ค๋ฉด ๋ฃจํŠธ ์ปดํฌ๋„ŒํŠธ๋ฅผ react-native-intlayer์˜ IntlayerProvider ์ปดํฌ๋„ŒํŠธ๋กœ ๊ฐ์‹ธ์•ผ ํ•ฉ๋‹ˆ๋‹ค.

      ํ•ญ์ƒ react-native-intlayer์—์„œ ๊ฐ€์ ธ์˜ค์„ธ์š”. ์ด ํŒจํ‚ค์ง€์˜ IntlayerProvider๋Š” Intlayer๊ฐ€ ์‚ฌ์šฉํ•˜๋Š” ์›น API์— ๋Œ€ํ•œ ํด๋ฆฌํ•„์„ ํฌํ•จํ•˜๋ฉฐ, react-intlayer์˜ ๋ชจ๋“  ํ›…๊ณผ ์œ ํ‹ธ๋ฆฌํ‹ฐ๋ฅผ ์žฌ๋‚ด๋ณด๋ƒ…๋‹ˆ๋‹ค.

      ๋˜ํ•œ Intlayer๊ฐ€ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์ž‘๋™ํ•  ์ˆ˜ ์žˆ๋„๋ก index.js ํŒŒ์ผ์— intlayerPolyfill ํ•จ์ˆ˜๋ฅผ ์ถ”๊ฐ€ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

      app/_layout.tsx
      import { Stack } from "expo-router";
      import { getLocales } from "expo-localization";
      import { IntlayerProvider } from "react-native-intlayer";
      import { type FC } from "react";
      
      const getDeviceLocale = () => getLocales()[0]?.languageTag;
      
      const RootLayout: FC = () => {
        return (
          <IntlayerProvider defaultLocale={getDeviceLocale()}>
            <Stack>
              <Stack.Screen name="(tabs)" options={{ headerShown: false }} />
            </Stack>
          </IntlayerProvider>
        );
      };
      
      export default RootLayout;
      
    5. ์ฝ˜ํ…์ธ  ์„ ์–ธํ•˜๊ธฐ

      ํ”„๋กœ์ ํŠธ ๋‚ด ์–ด๋””์—์„œ๋‚˜(์ผ๋ฐ˜์ ์œผ๋กœ src/ ๋‚ด) ์ฝ˜ํ…์ธ  ์„ ์–ธ ํŒŒ์ผ์„ ์ƒ์„ฑํ•˜์„ธ์š”. Intlayer๊ฐ€ ์ง€์›ํ•˜๋Š” ํ™•์žฅ์ž ํ˜•์‹์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:

      • .content.json
      • .content.jsonc
      • .content.json5
      • .content.ts
      • .content.tsx
      • .content.js
      • .content.jsx
      • .content.mjs
      • .content.mjx
      • .content.cjs
      • .content.md
      • .content.mdx
      • .content.yaml
      • .content.yml
      • ๊ธฐํƒ€

      Expo Router (์›น): .content.* ํŒŒ์ผ์„ app/ ๋””๋ ‰ํ† ๋ฆฌ ์™ธ๋ถ€์— ๋ณด๊ด€ํ•˜์„ธ์š”. Expo Router๋Š” app/ ๋‚ด์˜ ๋ชจ๋“  JavaScript/TypeScript ํŒŒ์ผ์„ ๋ผ์šฐํŠธ๋กœ ์ทจ๊ธ‰ํ•ฉ๋‹ˆ๋‹ค. ์›น์—์„œ๋Š” ๋ผ์šฐํŠธ ๊ฒ€์ƒ‰์ด ํŒŒ์ผ ์‹œ์Šคํ…œ์„ ์ง์ ‘ ์Šค์บ”ํ•˜๋ฉฐ Metro์˜ resolver.blockList๋ฅผ ๋”ฐ๋ฅด์ง€ ์•Š์œผ๋ฏ€๋กœ, ํ•จ๊ป˜ ์œ„์น˜ํ•œ *.content.ts๊ฐ€ ๋ผ์šฐํŠธ๋กœ ๋“ฑ๋ก๋ฉ๋‹ˆ๋‹ค. app/(tabs)/_layout.content.ts์™€ ๊ฐ™์€ ํŒŒ์ผ์€ ๋ ˆ์ด์•„์›ƒ์œผ๋กœ ํŒŒ์‹ฑ๋˜๊ธฐ๋„ ํ•˜๋ฉฐ(.content ๋ถ€๋ถ„์ด ํ”Œ๋žซํผ ์ ‘๋ฏธ์‚ฌ๋กœ ์ฝํž˜), ์ด๋Š” ์‹ค์ œ _layout.tsx์™€ ์ถฉ๋Œํ•˜์—ฌ ๋‹ค์Œ ์˜ค๋ฅ˜๋ฅผ ๋ฐœ์ƒ์‹œํ‚ต๋‹ˆ๋‹ค:

      plaintext
      The layouts "./(tabs)/_layout.content.ts" and "./(tabs)/_layout.tsx" conflict on the route "/(tabs)/_layout.content". Remove or rename one of these files.
      

      ์„ ์–ธ์„ app/ ์™ธ๋ถ€์˜ ๋””๋ ‰ํ† ๋ฆฌ(์˜ˆ: content/ ๋˜๋Š” src/content/)์— ๋ฐฐ์น˜ํ•˜์„ธ์š”. Intlayer๋Š” ํ”„๋กœ์ ํŠธ ์–ด๋””์—์„œ๋‚˜ .content.* ํŒŒ์ผ์„ ๋ฐœ๊ฒฌํ•˜๋ฉฐ ๋”•์…”๋„ˆ๋ฆฌ๋Š” ํ•ด๋‹น key๋กœ ์ฐธ์กฐ๋˜๋ฏ€๋กœ ๊ฐ€์ ธ์˜ค๊ธฐ(import)๋ฅผ ๋ณ€๊ฒฝํ•  ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ๋„ค์ดํ‹ฐ๋ธŒ์—์„œ๋Š” ์ด๊ฒƒ์ด ํ•„์š”ํ•˜์ง€ ์•Š์ง€๋งŒ(Metro์˜ blockList๊ฐ€ ์ด๋ฏธ ์ˆจ๊น€ ์ฒ˜๋ฆฌํ•จ), app/ ์™ธ๋ถ€ ๋””๋ ‰ํ† ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋‘ ํ”Œ๋žซํผ ๋ชจ๋‘ ์ •์ƒ์ ์œผ๋กœ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค.

      ์˜ˆ์‹œ (React Native์šฉ TSX ๋…ธ๋“œ๋ฅผ ํฌํ•จํ•œ TypeScript):

      src/app.content.tsx
      import { t, type Dictionary } from "intlayer";
      import type { ReactNode } from "react";
      
      /**
       * "app" ๋„๋ฉ”์ธ์šฉ ์ฝ˜ํ…์ธ  ์‚ฌ์ „
       */
      import { t, type Dictionary } from "intlayer";
      
      const homeScreenContent = {
        key: "home-screen",
        content: {
          title: t({
            en: "Welcome!",
            fr: "Bienvenue!",
            es: "ยกBienvenido!",
          }),
        },
      } satisfies Dictionary;
      
      export default homeScreenContent;
      
      ์ฝ˜ํ…์ธ  ์„ ์–ธ์— ๋Œ€ํ•œ ์ž์„ธํ•œ ๋‚ด์šฉ์€ Intlayer ์ฝ˜ํ…์ธ  ๋ฌธ์„œ๋ฅผ ์ฐธ์กฐํ•˜์„ธ์š”.
    6. ์ปดํฌ๋„ŒํŠธ์—์„œ Intlayer ์‚ฌ์šฉํ•˜๊ธฐ

      ์ž์‹ ์ปดํฌ๋„ŒํŠธ์—์„œ useIntlayer ํ›…์„ ์‚ฌ์šฉํ•˜์—ฌ ์ง€์—ญํ™”๋œ ์ฝ˜ํ…์ธ ๋ฅผ ๊ฐ€์ ธ์˜ค์„ธ์š”.

      ์˜ˆ์‹œ

      app/(tabs)/index.tsx
      import { Image, StyleSheet, Platform } from "react-native";
      import { useIntlayer } from "react-native-intlayer";
      import { HelloWave } from "@/components/HelloWave";
      import ParallaxScrollView from "@/components/ParallaxScrollView";
      import { ThemedText } from "@/components/ThemedText";
      import { ThemedView } from "@/components/ThemedView";
      import { type FC } from "react";
      
      const HomeScreen = (): FC => {
        const { title, steps } = useIntlayer("home-screen");
      
        return (
          <ParallaxScrollView
            headerBackgroundColor={{ light: "#A1CEDC", dark: "#1D3D47" }}
            headerImage={
              <Image
                source={require("@/assets/images/partial-react-logo.png")}
                style={styles.reactLogo}
              />
            }
          >
            <ThemedView style={styles.titleContainer}>
              <ThemedText type="title">{title}</ThemedText>
              <HelloWave />
            </ThemedView>
          </ParallaxScrollView>
        );
      };
      
      const styles = StyleSheet.create({
        titleContainer: {
          flexDirection: "row",
          alignItems: "center",
          gap: 8,
        },
      });
      
      export default HomeScreen;
      
      ๋ฌธ์ž์—ด ๊ธฐ๋ฐ˜ prop(์˜ˆ: ๋ฒ„ํŠผ์˜ title ๋˜๋Š” Text ์ปดํฌ๋„ŒํŠธ์˜ children)์—์„œ content.someKey๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ๋Š” ์‹ค์ œ ๋ฌธ์ž์—ด์„ ์–ป๊ธฐ ์œ„ํ•ด content.someKey.value๋ฅผ ํ˜ธ์ถœํ•˜์„ธ์š”.
      ์•ฑ์ด ์ด๋ฏธ ์กด์žฌํ•œ๋‹ค๋ฉด Intlayer Compiler์™€ extract ๋ช…๋ น์–ด๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ˆ˜์ฒœ ๊ฐœ์˜ ์ปดํฌ๋„ŒํŠธ๋ฅผ ํ•œ ๋ฒˆ์— ๋ณ€ํ™˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
    7. ์•ฑ ๋กœ์ผ€์ผ ๋ณ€๊ฒฝํ•˜๊ธฐ

      ์„ ํƒ์‚ฌํ•ญ

      ์ปดํฌ๋„ŒํŠธ ๋‚ด์—์„œ ๋กœ์ผ€์ผ์„ ์ „ํ™˜ํ•˜๋ ค๋ฉด useLocale ํ›…์˜ setLocale ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:

      src/components/LocaleSwitcher.tsx
      import { type FC } from "react";
      import { View, Text, TouchableOpacity, StyleSheet } from "react-native";
      import { getLocaleName } from "intlayer";
      import { useLocale } from "react-native-intlayer";
      
      export const LocaleSwitcher: FC = () => {
        const { setLocale, availableLocales } = useLocale();
      
        return (
          <View style={styles.container}>
            {availableLocales.map((locale) => (
              <TouchableOpacity
                key={locale}
                style={styles.button}
                onPress={() => setLocale(locale)}
              >
                <Text style={styles.text}>{getLocaleName(locale)}</Text>
              </TouchableOpacity>
            ))}
          </View>
        );
      };
      
      const styles = StyleSheet.create({
        container: {
          flexDirection: "row",
          justifyContent: "center",
          alignItems: "center",
          gap: 8,
        },
        button: {
          paddingVertical: 6,
          paddingHorizontal: 12,
          borderRadius: 6,
          backgroundColor: "#ddd",
        },
        text: {
          fontSize: 14,
          fontWeight: "500",
          color: "#333",
        },
      });
      

      ์ด ์ฝ”๋“œ๋Š” Intlayer ์ฝ˜ํ…์ธ ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ชจ๋“  ์ปดํฌ๋„ŒํŠธ์˜ ๋ฆฌ๋ Œ๋”๋ง์„ ํŠธ๋ฆฌ๊ฑฐํ•˜๋ฉฐ, ์ด์ œ ์ƒˆ๋กœ์šด ๋กœ์ผ€์ผ์— ๋Œ€ํ•œ ๋ฒˆ์—ญ์„ ํ‘œ์‹œํ•ฉ๋‹ˆ๋‹ค.

      ์ž์„ธํ•œ ๋‚ด์šฉ์€ useLocale ๋ฌธ์„œ๋ฅผ ์ฐธ์กฐํ•˜์„ธ์š”.

    TypeScript ๊ตฌ์„ฑํ•˜๊ธฐ (TypeScript๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ)

    Intlayer๋Š” ์ž๋™ ์™„์„ฑ ๊ธฐ๋Šฅ์„ ํ–ฅ์ƒ์‹œํ‚ค๊ณ  ๋ฒˆ์—ญ ์˜ค๋ฅ˜๋ฅผ ์žก๊ธฐ ์œ„ํ•ด ์ˆจ๊ฒจ์ง„ ํด๋”(๊ธฐ๋ณธ๊ฐ’์€ .intlayer)์— ํƒ€์ž… ์ •์˜๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค:

    json5
    // tsconfig.json
    {
      // ... ๊ธฐ์กด TS ์„ค์ •
      "include": [
        "src", // ์†Œ์Šค ์ฝ”๋“œ
        ".intlayer/types/**/*.ts", // <-- ์ž๋™ ์ƒ์„ฑ๋œ ํƒ€์ž… ํฌํ•จ ๋ณด์žฅ
        // ... ๊ธฐ์กด์— ํฌํ•จ๋œ ๋‹ค๋ฅธ ํ•ญ๋ชฉ๋“ค
      ],
    }
    

    ์ด ์„ค์ •์€ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ธฐ๋Šฅ์„ ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•ฉ๋‹ˆ๋‹ค:

    • ์‚ฌ์ „ ํ‚ค์— ๋Œ€ํ•œ ์ž๋™ ์™„์„ฑ.
    • ์กด์žฌํ•˜์ง€ ์•Š๋Š” ํ‚ค์— ์ ‘๊ทผํ•˜๊ฑฐ๋‚˜ ํƒ€์ž…์ด ์ผ์น˜ํ•˜์ง€ ์•Š์„ ๋•Œ ๊ฒฝ๊ณ ํ•˜๋Š” ํƒ€์ž… ๊ฒ€์‚ฌ.

    Git ์„ค์ •

    Intlayer๊ฐ€ ์ž๋™ ์ƒ์„ฑํ•œ ํŒŒ์ผ์„ ์ปค๋ฐ‹ํ•˜์ง€ ์•Š๋„๋ก ํ•˜๋ ค๋ฉด, .gitignore์— ๋‹ค์Œ์„ ์ถ”๊ฐ€ํ•˜์„ธ์š”:

    bash
    # Intlayer๊ฐ€ ์ƒ์„ฑํ•œ ํŒŒ์ผ ๋ฌด์‹œ
    .intlayer
    

    VS Code ํ™•์žฅ

    Intlayer์™€ ํ•จ๊ป˜ ๊ฐœ๋ฐœ ๊ฒฝํ—˜์„ ํ–ฅ์ƒ์‹œํ‚ค๊ธฐ ์œ„ํ•ด ๊ณต์‹ Intlayer VS Code ํ™•์žฅ์„ ์„ค์น˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

    ์ด ํ™•์žฅ ๊ธฐ๋Šฅ์€ ๋‹ค์Œ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค:

    • ๋ฒˆ์—ญ ํ‚ค์— ๋Œ€ํ•œ ์ž๋™ ์™„์„ฑ.
    • ๋ˆ„๋ฝ๋œ ๋ฒˆ์—ญ์— ๋Œ€ํ•œ ์‹ค์‹œ๊ฐ„ ์˜ค๋ฅ˜ ๊ฐ์ง€.
    • ๋ฒˆ์—ญ๋œ ์ฝ˜ํ…์ธ ์˜ ์ธ๋ผ์ธ ๋ฏธ๋ฆฌ๋ณด๊ธฐ.
    • ๋ฒˆ์—ญ์„ ์‰ฝ๊ฒŒ ์ƒ์„ฑํ•˜๊ณ  ์—…๋ฐ์ดํŠธํ•  ์ˆ˜ ์žˆ๋Š” ๋น ๋ฅธ ์ž‘์—….

    ํ™•์žฅ ๊ธฐ๋Šฅ ์‚ฌ์šฉ ๋ฐฉ๋ฒ•์— ๋Œ€ํ•œ ์ž์„ธํ•œ ๋‚ด์šฉ์€ Intlayer VS Code ํ™•์žฅ ๋ฌธ์„œ๋ฅผ ์ฐธ์กฐํ•˜์„ธ์š”.

    ๋” ๋‚˜์•„๊ฐ€๊ธฐ

    Intlayer๋ฅผ ํ†ตํ•ด ์™„๋ฒฝํ•˜๊ฒŒ ์ง€์›๋˜๋Š” i18n์œผ๋กœ React Native ์•ฑ์„ ์ฆ๊ฒ๊ฒŒ ๊ฐœ๋ฐœํ•˜์„ธ์š”!

    Debug

    Intlayer๋Š” ์ฃผ๋กœ Web Intl API๋ฅผ ๋Œ€์ƒ์œผ๋กœ ํ•˜๋ฉฐ, React Native์—์„œ๋Š” ์ ์ ˆํ•œ ํด๋ฆฌํ•„์„ ํฌํ•จํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

    Intlayer๋Š” ์ฃผ๋กœ Web Intl API๋ฅผ ๋Œ€์ƒ์œผ๋กœ ํ•ฉ๋‹ˆ๋‹ค. React Native์—์„œ๋Š” ์ ์ ˆํ•œ polyfills์„ ํฌํ•จํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

    ์ฒดํฌ๋ฆฌ์ŠคํŠธ:

    • intlayer์™€ react-native-intlayer์˜ ์ตœ์‹  ๋ฒ„์ „์„ ์‚ฌ์šฉํ•˜์„ธ์š”.
    • Intlayer ํด๋ฆฌํ•„์„ ํ™œ์„ฑํ™”ํ•˜์„ธ์š”.
    • getLocaleName ๋˜๋Š” ๋‹ค๋ฅธ Intl-API ๊ธฐ๋ฐ˜ ์œ ํ‹ธ๋ฆฌํ‹ฐ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ, ์ด๋Ÿฌํ•œ ํด๋ฆฌํ•„์„ ๋จผ์ € importํ•˜์„ธ์š” (์˜ˆ: index.js ๋˜๋Š” App.tsx):
    ts
    import "intl";
    import "@formatjs/intl-getcanonicallocales/polyfill";
    import "@formatjs/intl-locale/polyfill";
    import "@formatjs/intl-pluralrules/polyfill";
    import "@formatjs/intl-displaynames/polyfill";
    import "@formatjs/intl-listformat/polyfill";
    import "@formatjs/intl-numberformat/polyfill";
    import "@formatjs/intl-relativetimeformat/polyfill";
    import "@formatjs/intl-datetimeformat/polyfill";
    
    • ๋ชจ๋“ˆ์„ ํ™•์ธํ•  ์ˆ˜ ์—†์œผ๋ฉด Metro ๊ตฌ์„ฑ(resolver aliases, asset plugins, tsconfig paths)์„ ํ™•์ธํ•˜์„ธ์š”.

    ์ž์ฃผ ๋ฌป๋Š” ์งˆ๋ฌธ

    • i18n-js (expo-localization๊ณผ ํ•จ๊ป˜ ์‚ฌ์šฉ): ๊ฐ€์žฅ ์ „ํ†ต์ ์ธ ์กฐํ•ฉ์œผ๋กœ, ํƒ€์ž… ์•ˆ์ „์„ฑ์ด ์—†๋Š” ์ผ๋ฐ˜ ๋ฉ”์‹œ์ง€ ๊ฐ์ฒด์ž…๋‹ˆ๋‹ค.
    • react-i18next: React ์ƒํƒœ๊ณ„์˜ ํ‘œ์ค€์œผ๋กœ, ๋Ÿฐํƒ€์ž„์— JSON ๋„ค์ž„์ŠคํŽ˜์ด์Šค๋ฅผ ๋กœ๋“œํ•ฉ๋‹ˆ๋‹ค.
    • Intlayer: ๊ฐ€์žฅ ์ง„๋ณด๋œ ์†”๋ฃจ์…˜์ž…๋‹ˆ๋‹ค. ์ฝ”๋“œ๋ฒ ์ด์Šค ์–ด๋””์—๋‚˜ ์ฝ˜ํ…์ธ ๋ฅผ ์„ ์–ธํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ(๊ฐ ์ปดํฌ๋„ŒํŠธ ์˜† ๋˜๋Š” ์ค‘์•™ ์ง‘์ค‘์‹), Metro ํ”Œ๋Ÿฌ๊ทธ์ธ์— ์˜ํ•ด ๋นŒ๋“œ ํƒ€์ž„์— ์ปดํŒŒ์ผ๋˜๊ณ , ์™„์ „ํ•œ ํƒ€์ž… ์•ˆ์ „์„ฑ์„ ์ œ๊ณตํ•˜๋ฉฐ AI ๋ฒˆ์—ญ, ๋น„์ฃผ์–ผ ์—๋””ํ„ฐ ๋ฐ CMS๋ฅผ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค.

    ๋ชจ๋ฐ”์ผ์—์„œ๋Š” ํŽ˜์ด์ง€๋ณ„๋กœ ๊ฐ€์ ธ์˜ค๋Š” ์›น๊ณผ ๋‹ฌ๋ฆฌ ๋ชจ๋“  ๊ฒƒ์ด ์•ฑ ๋ฒˆ๋“ค์— ํฌํ•จ๋˜๊ธฐ ๋•Œ๋ฌธ์— ๋ฒˆ๋“ค ํฌ๊ธฐ ์ ˆ๊ฐ ํšจ๊ณผ๊ฐ€ ํ›จ์”ฌ ๊ฐ•๋ ฅํ•ฉ๋‹ˆ๋‹ค. ์ปดํฌ๋„ŒํŠธ๋ณ„๋กœ ์ฝ˜ํ…์ธ ๋ฅผ ์ปดํŒŒ์ผํ•˜๋ฉด ์‚ฌ์šฉ๋˜์ง€ ์•Š๋Š” ์–ธ์–ด์™€ ํ‚ค๊ฐ€ ๋ฒˆ๋“ค์—์„œ ์™„์ „ํžˆ ์ œ์™ธ๋ฉ๋‹ˆ๋‹ค. ์™œ Intlayer์ธ๊ฐ€๋ฅผ ์ฐธ์กฐํ•˜์„ธ์š”.

    ๋Ÿฐํƒ€์ž„ ์นดํƒˆ๋กœ๊ทธ๋ณด๋‹ค ํ›จ์”ฌ ์ ์Šต๋‹ˆ๋‹ค. ๋ชจ๋ฐ”์ผ์—์„œ๋Š” ํŽ˜์ด์ง€๋ณ„๋กœ ๊ฐ€์ ธ์˜ค๋Š” ์›น๊ณผ ๋‹ฌ๋ฆฌ ๋ชจ๋“  ๋ฆฌ์†Œ์Šค๊ฐ€ ์•ฑ ๋‚ด์— ๋ฒˆ๋“ค๋ง๋˜๋ฏ€๋กœ ์ด๊ฒƒ์ด ๋”์šฑ ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค. Metro ํ”Œ๋Ÿฌ๊ทธ์ธ์€ useIntlayer ํ˜ธ์ถœ์„ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์‚ฌ์šฉํ•˜๋Š” ์ •ํ™•ํ•œ ํ•ญ๋ชฉ์œผ๋กœ ํ™•์ธํ•˜๋ฏ€๋กœ ์‚ฌ์šฉ๋˜์ง€ ์•Š๋Š” ํ‚ค์™€ ์–ธ์–ด๋Š” ๋ฐ”์ด๋„ˆ๋ฆฌ์— ์ ˆ๋Œ€ ํฌํ•จ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ผ๋ฐ˜์ ์ธ ๋Œ€์•ˆ๋“ค๊ณผ ๋น„๊ตํ–ˆ์„ ๋•Œ Intlayer๋Š” ๋ฒˆ๋“ค ํฌ๊ธฐ๋ฅผ ์ตœ๋Œ€ 50%๊นŒ์ง€ ์ค„์—ฌ์ค๋‹ˆ๋‹ค. ๋ฒˆ๋“ค ์ตœ์ ํ™”๋ฅผ ์ฐธ์กฐํ•˜์„ธ์š”.

    ๋„ค, ๋‘ ๊ฐ€์ง€ ๋ฐฉ๋ฒ•์ด ์žˆ์Šต๋‹ˆ๋‹ค. i18n-js ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ๊ฐ€์ด๋“œ ๋˜๋Š” react-i18next ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ๊ฐ€์ด๋“œ๋ฅผ ๋”ฐ๋ผ ์ ์ง„์ ์œผ๋กœ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋˜๋Š” ํ˜„์žฌ API๋ฅผ ์™„์ „ํžˆ ์œ ์ง€ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ํ˜ธํ™˜ ์–ด๋Œ‘ํ„ฐ(compat adapters)๋Š” react-i18next ๋ฐ react-intl๊ณผ ์™„์ „ํžˆ ๋™์ผํ•œ API๋ฅผ ๋…ธ์ถœํ•˜๋ฉด์„œ Intlayer ์‚ฌ์ „์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ์ œ๊ณตํ•˜๋ฏ€๋กœ, import ๊ตฌ๋ฌธ๋งŒ ๋ณ€๊ฒฝํ•˜๊ณ  ์ปดํฌ๋„ŒํŠธ ์ฝ”๋“œ๋Š” ๊ทธ๋Œ€๋กœ ์œ ์ง€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

    ๋„ค. sync JSON ํ”Œ๋Ÿฌ๊ทธ์ธ์€ /messages/{locale}/{namespace}.json ํŒŒ์ผ์„ ๋‹จ์ผ ์ง„์‹ค ๊ณต๊ธ‰์›(source of truth)์œผ๋กœ ์œ ์ง€ํ•˜๋ฉด์„œ ์–‘๋ฐฉํ–ฅ์œผ๋กœ Intlayer ์‚ฌ์ „์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. sync PO ํ”Œ๋Ÿฌ๊ทธ์ธ์€ gettext ์นดํƒˆ๋กœ๊ทธ์— ๋Œ€ํ•ด ๋™์ผํ•œ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋ฉฐ, ๋กœ์ผ€์ผ๋ณ„ ํŒŒ์ผ์„ ํ†ตํ•ด ๋กœ์ผ€์ผ์„ ํ•œ ํŒŒ์ผ์— ๋ชจ์œผ๋Š” ๋Œ€์‹  ์–ธ์–ด๋ณ„๋กœ ์ฝ˜ํ…์ธ ๋ฅผ ๋ถ„ํ• ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

    ์•„๋‹™๋‹ˆ๋‹ค. npx intlayer extract๋ฅผ ์‹คํ–‰ํ•˜๋ฉด Intlayer๊ฐ€ ์†Œ์Šค ํŒŒ์ผ์„ ์ฝ๊ณ  ์‚ฌ์šฉ์ž ๋Œ€๋ฉด ๋ฌธ์ž์—ด์„ ์ถ”์ถœํ•˜์—ฌ ๊ฐ ์ปดํฌ๋„ŒํŠธ ์˜†์— .content ํŒŒ์ผ์„ ์ƒ์„ฑํ•˜๋ฏ€๋กœ ์นดํƒˆ๋กœ๊ทธ์— ์ผ์ผ์ด ๋ณต์‚ฌํ•  ํ•„์š” ์—†์ด diff๋งŒ ๊ฒ€ํ† ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค. extract ๋ช…๋ น์„ ์ฐธ์กฐํ•˜์„ธ์š”.

    ์™„์ „ ์ž๋™ํ™”๋œ ํŒŒ์ดํ”„๋ผ์ธ์„ ์œ„ํ•ด Intlayer ์ปดํŒŒ์ผ๋Ÿฌ๋Š” ๋นŒ๋“œ ํƒ€์ž„์— JSX, TSX, Vue ๋ฐ Svelte ์†Œ์Šค์—์„œ ๋™์ผํ•œ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜์—ฌ ๋ณ€๊ฒฝ๋  ๋•Œ๋งˆ๋‹ค ์‚ฌ์ „์„ ์ƒ์„ฑํ•˜๊ณ  HMR์„ ํ†ตํ•ด ๋™๊ธฐํ™”ํ•˜๋ฏ€๋กœ ์ˆ˜๋™์œผ๋กœ ํ‚ค๋ฅผ ๊ด€๋ฆฌํ•  ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ์ •์  ๋ถ„์„์œผ๋กœ ์ž‘๋™ํ•˜๋ฏ€๋กœ ๋Ÿฐํƒ€์ž„์—๋งŒ ์กด์žฌํ•˜๋Š” ๋ฌธ์ž์—ด์€ ์ œ์™ธ๋˜๋ฉฐ, ์‚ฌ์šฉ์ž ํ…์ŠคํŠธ์™€ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋กœ์ง์„ ๊ตฌ๋ถ„ํ•˜๊ธฐ ์œ„ํ•ด ๋ช‡ ๊ฐ€์ง€ ์ฃผ์„์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

    5๊ฐ€์ง€ ๋„๊ตฌ๊ฐ€ ๋ชจ๋‘ ์„ ํƒ ์‚ฌํ•ญ์œผ๋กœ ์ œ๊ณต๋ฉ๋‹ˆ๋‹ค:

    • VS Code ํ™•์žฅ ํ”„๋กœ๊ทธ๋žจ: useIntlayer ํ‚ค์—์„œ ์ด๋ฅผ ์„ ์–ธํ•œ ์ฝ˜ํ…์ธ  ํŒŒ์ผ๋กœ ๋ฐ”๋กœ ์ด๋™ํ•˜๊ณ , ์ปดํฌ๋„ŒํŠธ์—์„œ ์ฝ˜ํ…์ธ ๋ฅผ ์ถ”์ถœํ•˜๋ฉฐ, ๋ช…๋ น ํŒ”๋ ˆํŠธ๋‚˜ ์ „์šฉ Intlayer ํƒญ์—์„œ build, fill, test, push, pull์„ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
    • LSP ์„œ๋ฒ„: LSP๋ฅผ ์ง€์›ํ•˜๋Š” ๋ชจ๋“  ์—๋””ํ„ฐ์—์„œ ์ •์˜๋กœ ์ด๋™, ๋ชจ๋“  ์ฐธ์กฐ ์ฐพ๊ธฐ, ๋ฒˆ์—ญ ๊ฐ’ ๋งˆ์šฐ์Šค ์˜ค๋ฒ„ ๋ฏธ๋ฆฌ๋ณด๊ธฐ, ํ‚ค ๋ฐ ํ•„๋“œ ์ž๋™ ์™„์„ฑ, ์„ ์–ธ๋˜์ง€ ์•Š์€ ํ‚ค์— ๋Œ€ํ•œ ๊ฒฝ๊ณ  ๋“ฑ ๋™์ผํ•œ ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ๋˜ํ•œ i18next, react-i18next, next-intl, use-intl ํ˜ธ์ถœ๋„ ํ•ด์„ํ•˜๋ฏ€๋กœ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ์‹œ ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค.
    • MCP ์„œ๋ฒ„: Cursor, VS Code, Claude Desktop, Claude Code, ChatGPT์— Intlayer ๋ฌธ์„œ์™€ CLI๋ฅผ ๋…ธ์ถœํ•˜์—ฌ AI ์–ด์‹œ์Šคํ„ดํŠธ๊ฐ€ ์ตœ์‹  ๋ฌธ์„œ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ์ •ํ™•ํžˆ ๋‹ต๋ณ€ํ•˜๊ณ  intlayer fill ๋“ฑ์˜ ๋ช…๋ น์„ ์ง์ ‘ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ฉ๋‹ˆ๋‹ค.
    • Agent Skills: intlayer-config, intlayer-cli, intlayer-content ๋ฐ ๊ฐ ํ”„๋ ˆ์ž„์›Œํฌ ์ „์šฉ ์Šคํ‚ฌ์„ ํ†ตํ•ด AI ์—์ด์ „ํŠธ์—๊ฒŒ ๋ผ์šฐํŒ… ์„ค์ •๊ณผ ์ฝ˜ํ…์ธ  ๋…ธ๋“œ ํƒ€์ž…์„ ํ•™์Šต์‹œํ‚ต๋‹ˆ๋‹ค.
    • ESLint ํ”Œ๋Ÿฌ๊ทธ์ธ: no-raw-text ๊ทœ์น™์œผ๋กœ ํ•˜๋“œ์ฝ”๋”ฉ๋œ ๋ฌธ์ž์—ด์„ ํ‘œ์‹œํ•˜๊ณ , ์ •์  ์‚ฌ์ „ ํ‚ค ๋ฐ ์‚ฌ์šฉ๋˜์ง€ ์•Š๋Š” ์ฝ˜ํ…์ธ ์— ๋Œ€ํ•œ ์ถ”๊ฐ€ ๊ทœ์น™์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.