์ž‘๊ฐ€:
    ์ƒ์„ฑ:2025-01-02๋งˆ์ง€๋ง‰ ์—…๋ฐ์ดํŠธ:2025-10-29

    Intlayer๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ react-intl JSON ๋ฒˆ์—ญ ์ž๋™ํ™”ํ•˜๋Š” ๋ฐฉ๋ฒ•

    www.youtube.com

    ๋ชฉ์ฐจ

    Intlayer๋ž€ ๋ฌด์—‡์ธ๊ฐ€์š”?

    Intlayer๋Š” ์ „ํ†ต์ ์ธ i18n ์†”๋ฃจ์…˜์˜ ํ•œ๊ณ„๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด ์„ค๊ณ„๋œ ํ˜์‹ ์ ์ด๊ณ  ์˜คํ”ˆ ์†Œ์Šค์ธ ๊ตญ์ œํ™” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ž…๋‹ˆ๋‹ค. React ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ์ฝ˜ํ…์ธ  ๊ด€๋ฆฌ๋ฅผ ์œ„ํ•œ ํ˜„๋Œ€์ ์ธ ์ ‘๊ทผ ๋ฐฉ์‹์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

    react-intl๊ณผ์˜ ๊ตฌ์ฒด์ ์ธ ๋น„๊ต๋Š” ์ €ํฌ ๋ธ”๋กœ๊ทธ ๊ฒŒ์‹œ๋ฌผ react-i18next vs. react-intl vs. Intlayer์—์„œ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

    ์™œ Intlayer๋ฅผ react-intl๊ณผ ํ•จ๊ป˜ ์‚ฌ์šฉํ•ด์•ผ ํ• ๊นŒ์š”?

    Intlayer๋Š” ํ›Œ๋ฅญํ•œ ๋…๋ฆฝํ˜• i18n ์†”๋ฃจ์…˜์„ ์ œ๊ณตํ•˜์ง€๋งŒ(์ž์„ธํ•œ ๋‚ด์šฉ์€ React ํ†ตํ•ฉ ๊ฐ€์ด๋“œ๋ฅผ ์ฐธ์กฐ), ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์—ฌ๋Ÿฌ ์ด์œ ๋กœ react-intl๊ณผ ๊ฒฐํ•ฉํ•˜์—ฌ ์‚ฌ์šฉํ•˜๊ณ ์ž ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:

    1. ๊ธฐ์กด ์ฝ”๋“œ๋ฒ ์ด์Šค: ์ด๋ฏธ ๊ตฌ์ถ•๋œ react-intl ๊ตฌํ˜„์ด ์žˆ์œผ๋ฉฐ Intlayer์˜ ํ–ฅ์ƒ๋œ ๊ฐœ๋ฐœ์ž ๊ฒฝํ—˜์œผ๋กœ ์ ์ง„์ ์œผ๋กœ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ํ•˜๊ณ ์ž ํ•ฉ๋‹ˆ๋‹ค.
    2. ๋ ˆ๊ฑฐ์‹œ ์š”๊ตฌ์‚ฌํ•ญ: ํ”„๋กœ์ ํŠธ๊ฐ€ ๊ธฐ์กด react-intl ํ”Œ๋Ÿฌ๊ทธ์ธ ๋˜๋Š” ์›Œํฌํ”Œ๋กœ์šฐ์™€์˜ ํ˜ธํ™˜์„ฑ์„ ํ•„์š”๋กœ ํ•ฉ๋‹ˆ๋‹ค.
    3. ํŒ€ ์นœ์ˆ™๋„: ํŒ€์ด react-intl์— ์ต์ˆ™ํ•˜์ง€๋งŒ ๋” ๋‚˜์€ ์ฝ˜ํ…์ธ  ๊ด€๋ฆฌ๋ฅผ ์›ํ•ฉ๋‹ˆ๋‹ค.
    4. Intlayer ๊ธฐ๋Šฅ ์‚ฌ์šฉ: ์ฝ˜ํ…์ธ  ์„ ์–ธ, ๋ฒˆ์—ญ ์ž๋™ํ™”, ๋ฒˆ์—ญ ํ…Œ์ŠคํŠธ ๋“ฑ Intlayer์˜ ๊ธฐ๋Šฅ์„ ํ™œ์šฉํ•˜๊ณ ์ž ํ•ฉ๋‹ˆ๋‹ค.

    ์ด๋ฅผ ์œ„ํ•ด Intlayer๋Š” react-intl์˜ ์–ด๋Œ‘ํ„ฐ๋กœ ๊ตฌํ˜„๋˜์–ด CLI ๋˜๋Š” CI/CD ํŒŒ์ดํ”„๋ผ์ธ์—์„œ JSON ๋ฒˆ์—ญ ์ž๋™ํ™”, ๋ฒˆ์—ญ ํ…Œ์ŠคํŠธ ๋“ฑ์„ ์ง€์›ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

    ์ด ๊ฐ€์ด๋“œ๋Š” react-intl๊ณผ์˜ ํ˜ธํ™˜์„ฑ์„ ์œ ์ง€ํ•˜๋ฉด์„œ Intlayer์˜ ์šฐ์ˆ˜ํ•œ ์ฝ˜ํ…์ธ  ์„ ์–ธ ์‹œ์Šคํ…œ์„ ํ™œ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค.

    react-intl๊ณผ ํ•จ๊ป˜ Intlayer๋ฅผ ์„ค์ •ํ•˜๋Š” ๋‹จ๊ณ„๋ณ„ ๊ฐ€์ด๋“œ

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

      ํ•„์š”ํ•œ ํŒจํ‚ค์ง€๋ฅผ ์„ค์น˜ํ•˜์„ธ์š”:

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

      ํŒจํ‚ค์ง€ ์„ค๋ช…:

      • intlayer: ๊ตญ์ œํ™” ๊ด€๋ฆฌ, ์ฝ˜ํ…์ธ  ์„ ์–ธ ๋ฐ ๋นŒ๋“œ๋ฅผ ์œ„ํ•œ ํ•ต์‹ฌ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ
      • @intlayer/sync-json-plugin: Intlayer ์ฝ˜ํ…์ธ  ์„ ์–ธ์„ react-intl ํ˜ธํ™˜ JSON ํ˜•์‹์œผ๋กœ ๋‚ด๋ณด๋‚ด๋Š” ํ”Œ๋Ÿฌ๊ทธ์ธ
    2. JSON์„ ๋ž˜ํ•‘ํ•˜๊ธฐ ์œ„ํ•œ Intlayer ํ”Œ๋Ÿฌ๊ทธ์ธ ๊ตฌํ˜„

      ์ง€์›ํ•˜๋Š” ๋กœ์ผ€์ผ์„ ์ •์˜ํ•˜๊ธฐ ์œ„ํ•ด Intlayer ๊ตฌ์„ฑ ํŒŒ์ผ์„ ๋งŒ๋“ญ๋‹ˆ๋‹ค:

      react-intl์šฉ JSON ์‚ฌ์ „๋„ ๋‚ด๋ณด๋‚ด๊ณ  ์‹ถ๋‹ค๋ฉด, syncJSON ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ์ถ”๊ฐ€ํ•˜์„ธ์š”:

      intlayer.config.ts
      import { Locales, type IntlayerConfig } from "intlayer";
      import { syncJSON } from "@intlayer/sync-json-plugin";
      
      const config: IntlayerConfig = {
        internationalization: {
          locales: [Locales.ENGLISH, Locales.FRENCH, Locales.SPANISH],
          defaultLocale: Locales.ENGLISH,
        },
        plugins: [
          syncJSON({
            format: 'i18next',
            source: ({ key, locale }) => `./intl/messages/${locale}/${key}.json`,
          }),
        ],
      };
      
      `export default config;
      

      syncJSON ํ”Œ๋Ÿฌ๊ทธ์ธ์€ JSON์„ ์ž๋™์œผ๋กœ ๋ž˜ํ•‘ํ•ฉ๋‹ˆ๋‹ค. ์ฝ˜ํ…์ธ  ๊ตฌ์กฐ๋ฅผ ๋ณ€๊ฒฝํ•˜์ง€ ์•Š๊ณ  JSON ํŒŒ์ผ์„ ์ฝ๊ณ  ์”๋‹ˆ๋‹ค.

      ๋งŒ์•ฝ JSON๊ณผ intlayer ์ฝ˜ํ…์ธ  ์„ ์–ธ ํŒŒ์ผ(.content ํŒŒ์ผ)์„ ๊ณต์กด์‹œํ‚ค๊ณ  ์‹ถ๋‹ค๋ฉด, Intlayer๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค:

      1. JSON๊ณผ ์ฝ˜ํ…์ธ  ์„ ์–ธ ํŒŒ์ผ์„ ๋ชจ๋‘ ๋ถˆ๋Ÿฌ์™€์„œ intlayer ์‚ฌ์ „(dictionary)์œผ๋กœ ๋ณ€ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
      2. JSON๊ณผ ์ฝ˜ํ…์ธ  ์„ ์–ธ ํŒŒ์ผ ๊ฐ„์— ์ถฉ๋Œ์ด ์žˆ์„ ๊ฒฝ์šฐ, Intlayer๋Š” ๋ชจ๋“  ์‚ฌ์ „์„ ๋ณ‘ํ•ฉํ•ฉ๋‹ˆ๋‹ค. ์ด๋•Œ ํ”Œ๋Ÿฌ๊ทธ์ธ์˜ ์šฐ์„ ์ˆœ์œ„์™€ ์ฝ˜ํ…์ธ  ์„ ์–ธ ํŒŒ์ผ์˜ ์šฐ์„ ์ˆœ์œ„์— ๋”ฐ๋ผ ์ฒ˜๋ฆฌ๋˜๋ฉฐ, ๋ชจ๋‘ ์„ค์ • ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

      CLI๋ฅผ ์‚ฌ์šฉํ•ด JSON์„ ๋ฒˆ์—ญํ•˜๊ฑฐ๋‚˜ CMS๋ฅผ ํ†ตํ•ด ๋ณ€๊ฒฝ์ด ์ด๋ฃจ์–ด์ง€๋ฉด, Intlayer๋Š” ์ƒˆ๋กœ์šด ๋ฒˆ์—ญ์œผ๋กœ JSON ํŒŒ์ผ์„ ์—…๋ฐ์ดํŠธํ•ฉ๋‹ˆ๋‹ค.

      syncJSON ํ”Œ๋Ÿฌ๊ทธ์ธ์— ๋Œ€ํ•œ ์ž์„ธํ•œ ๋‚ด์šฉ์„ ๋ณด๋ ค๋ฉด syncJSON ํ”Œ๋Ÿฌ๊ทธ์ธ ๋ฌธ์„œ๋ฅผ ์ฐธ์กฐํ•˜์„ธ์š”.

    3. ์ปดํฌ๋„ŒํŠธ๋ณ„ JSON ๋ฒˆ์—ญ ๊ตฌํ˜„

      ์„ ํƒ์‚ฌํ•ญ

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

      ์ด๋ฅผ ์œ„ํ•ด loadJSON ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

      intlayer.config.ts
      import { Locales, type IntlayerConfig } from "intlayer";
      import { loadJSON, syncJSON } from "@intlayer/sync-json-plugin";
      
      const config: IntlayerConfig = {
        internationalization: {
          locales: [Locales.ENGLISH, Locales.FRENCH, Locales.SPANISH],
          defaultLocale: Locales.ENGLISH,
        },
      
        // ํ˜„์žฌ JSON ํŒŒ์ผ์„ Intlayer ์‚ฌ์ „๊ณผ ๋™๊ธฐํ™” ์ƒํƒœ๋กœ ์œ ์ง€ํ•ฉ๋‹ˆ๋‹ค
        plugins: [
          /**
           * src ๋‚ด์—์„œ {key}.i18n.json ํŒจํ„ด๊ณผ ์ผ์น˜ํ•˜๋Š” ๋ชจ๋“  JSON ํŒŒ์ผ์„ ๋กœ๋“œํ•ฉ๋‹ˆ๋‹ค
           */
          loadJSON({
            source: ({ key }) => `./src/**/${key}.i18n.json`,
            locale: Locales.ENGLISH,
            priority: 1, // ์ด JSON ํŒŒ์ผ๋“ค์ด `./locales/en/${key}.json` ํŒŒ์ผ๋ณด๋‹ค ์šฐ์„ ํ•˜๋„๋ก ๋ณด์žฅํ•ฉ๋‹ˆ๋‹ค
          }),
          /**
           * locales ๋””๋ ‰ํ† ๋ฆฌ ๋‚ด JSON ํŒŒ์ผ์— ์ถœ๋ ฅ ๋ฐ ๋ฒˆ์—ญ์„ ๋‹ค์‹œ ๊ธฐ๋กํ•˜๋ฉฐ ๋กœ๋“œํ•ฉ๋‹ˆ๋‹ค
           */
          syncJSON({
            format: "icu",
            source: ({ key, locale }) => `./messages/${locale}/${key}.json`,
            priority: 0,
          }),
        ],
      };
      
      export default config;
      

      ์ด ์„ค์ •์€ src ๋””๋ ‰ํ† ๋ฆฌ ๋‚ด์—์„œ {key}.i18n.json ํŒจํ„ด๊ณผ ์ผ์น˜ํ•˜๋Š” ๋ชจ๋“  JSON ํŒŒ์ผ์„ ๋กœ๋“œํ•˜์—ฌ Intlayer ์‚ฌ์ „์œผ๋กœ ๋ถˆ๋Ÿฌ์˜ต๋‹ˆ๋‹ค.

    Git ์„ค์ •

    ์ž๋™ ์ƒ์„ฑ๋˜๋Š” Intlayer ํŒŒ์ผ์€ ๋ฌด์‹œํ•˜๋Š” ๊ฒƒ์ด ๊ถŒ์žฅ๋ฉ๋‹ˆ๋‹ค:

    .gitignore
    # Intlayer์—์„œ ์ƒ์„ฑ๋œ ํŒŒ์ผ ๋ฌด์‹œ
    .intlayer
    

    ์ด ํŒŒ์ผ๋“ค์€ ๋นŒ๋“œ ๊ณผ์ •์—์„œ ๋‹ค์‹œ ์ƒ์„ฑ๋  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ ๋ฒ„์ „ ๊ด€๋ฆฌ์— ์ปค๋ฐ‹ํ•  ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.

    VS Code ํ™•์žฅ ํ”„๋กœ๊ทธ๋žจ

    ๊ฐœ๋ฐœ์ž ๊ฒฝํ—˜ ํ–ฅ์ƒ์„ ์œ„ํ•ด ๊ณต์‹ Intlayer VS Code ํ™•์žฅ ํ”„๋กœ๊ทธ๋žจ์„ ์„ค์น˜ํ•˜์„ธ์š”:

    VS Code ๋งˆ์ผ“ํ”Œ๋ ˆ์ด์Šค์—์„œ ์„ค์น˜ํ•˜๊ธฐ

    ๋Œ“๊ธ€

    ์•„์ง ๋Œ“๊ธ€์ด ์—†์Šต๋‹ˆ๋‹ค. ์ฒซ ๋ฒˆ์งธ๋กœ ์˜๊ฒฌ์„ ๋‚˜๋ˆ ๋ณด์„ธ์š”.

    ๊ด€๋ จ ๊ฒŒ์‹œ๋ฌผ

    ์ตœ๊ทผ ๊ฒŒ์‹œ๋ฌผ