μ΄ νμ΄μ§μ μνλ AI μ΄μμ€ν΄νΈλ₯Ό μ¬μ©νμ¬ λ¬Έμλ₯Ό μμ½ν©λλ€
λ²μ κΈ°λ‘
- "μ΄κΈ° νμ€ν 리"v9.3.12026. 8. 12.
μ΄ νμ΄μ§μ μ½ν μΈ λ AIλ₯Ό μ¬μ©νμ¬ λ²μλμμ΅λλ€.
μμ΄ μλ³Έ λ΄μ©μ μ΅μ λ²μ μ λ³΄κΈ°μ΄ λ¬Έμλ₯Ό κ°μ ν μμ΄λμ΄κ° μμΌμλ©΄ GitHubμ ν 리νμ€νΈλ₯Ό μ μΆνμ¬ μμ λ‘κ² κΈ°μ¬ν΄ μ£ΌμΈμ.
λ¬Έμμ λν GitHub λ§ν¬λ¬Έμμ Markdownμ ν΄λ¦½λ³΄λμ 볡μ¬
ESLint x OXLint νλ¬κ·ΈμΈ
eslint-plugin-intlayerλ TypeScriptκ° κ°μ§νμ§ λͺ»νλ i18n μ€μλ₯Ό μ‘μλ
λλ€:
- μ¬μ μ λ±λ‘λμ§ μμ νλμ½λ©λ ν μ€νΈ.
- νμ κ²μ¬λ₯Ό ν΅κ³Όνκ³ μ€νλμ§λ§ Intlayer μ»΄νμΌλ¬κ° μ΅μ νν μ μλ λμ νΈμΆ.
- λ―Έμ¬μ© μ½ν μΈ (Dead content): νλ‘μ νΈ λ΄μμ μ무 κ³³μμλ μ½μ§ μλ μ¬μ λ° νλ(μ ν μ¬ν).
μ μ μλ μ¬μ ν€, μ μ μλ νλ κ²½λ‘ λ° λλ½λ λ‘μΌμΌμ μ΄λ―Έ μ»΄νμΌ μλ¬λ‘ μ²λ¦¬λλ―λ‘ νλ¬κ·ΈμΈμ μ΄λ₯Ό μ€λ³΅ λ³΄κ³ νμ§ μμ΅λλ€.
μ€μΉ
μ½λλ₯Ό ν΄λ¦½λ³΄λμ 볡μ¬
ESLint 9 μ΄μ(Flat config)μ΄ νμν©λλ€. ESLint 10μ μ§μν©λλ€.
μ¬μ©λ²
μ΄ νλ¬κ·ΈμΈμ ESLintμ oxlint λͺ¨λμμ λμΌν κ·μΉκ³Ό μ΅μ μΌλ‘ μ€νλ©λλ€.
μ½λλ₯Ό ν΄λ¦½λ³΄λμ 볡μ¬
λλ μ€μ μ νΌμΉ λ€ μ¬κ°λλ₯Ό μ§μ μ§μ ν μ μμ΅λλ€:
μ½λλ₯Ό ν΄λ¦½λ³΄λμ 볡μ¬
μ½λλ₯Ό ν΄λ¦½λ³΄λμ 볡μ¬
λ κ°μ§ μ£Όμ μ¬ν: oxlintμ JS νλ¬κ·ΈμΈ μ§μμ μμ§ μν λ¨κ³μ΄λ©°, 컀μ€ν
νμλ₯Ό μ§μνμ§ μμΌλ―λ‘ .vue, .svelte, .astro λ° Angular ν
νλ¦Ώμ oxlintμμ λ¦°νΈλμ§ μμ΅λλ€. JS/TS/JSX νμΌμλ oxlintλ₯Ό μ¬μ©νκ³ λλ¨Έμ§λ ESLintλ₯Ό κ³μ μ¬μ©νμΈμ.
no-unused-contentλ μμμ μλμ μΌλ‘ μ μΈλμμ΅λλ€. μ΄ κ·μΉμ κ·μΉ 컨ν
μ€νΈμμ μμ
λλ ν°λ¦¬μ λ¦°νΈ λμ νμΌ κ²½λ‘λ₯Ό νμλ‘ νμ§λ§, μν λ¨κ³μ JS νλ¬κ·ΈμΈ λΈλ¦¬μ§μμλ μ΄λ₯Ό 보μ₯νμ§ λͺ»ν©λλ€. μ΄ κ·μΉμ ESLintμμ μ€ννμΈμ.
μ€μ (Configs)
ν μ΄λΈμ λͺ¨λ¬λ‘ μ΄μ΄ λͺ¨λ λ°μ΄ν°λ₯Ό λͺ ννκ² νμΈ
| μ€μ | no-raw-text | static-dictionary-key | no-dynamic-field-access | enforce-adapter-import | no-unused-content |
|---|---|---|---|---|---|
recommended | warn | error | error | off | off |
strict | error (+ λΉ JSX 리ν°λ΄) | error | error | error | off |
contract-only | off | error | error | off | off |
recommendedλ μλμ μΌλ‘ no-raw-textλ₯Ό warnμΌλ‘ μ μ§ν©λλ€. κΈ°μ‘΄ μ½λλ² μ΄μ€μ μ μ©νμ λ λ²μλμ§ μμ λͺ¨λ λ¬Έμμ΄μ΄ ν λ²μ λ³΄κ³ λμ΄ μ²«λ λΆν° λΉλκ° μ€λ¨λλ κ²μ λ°©μ§νκΈ° μν¨μ
λλ€.
enforce-adapter-importλ κΈ°λ³Έμ μΌλ‘ κΊΌμ Έ μμ΅λλ€. νμν κ²½μ° λͺ
μμ μΌλ‘ νμ±ννμΈμ.
no-unused-contentλ strictλ₯Ό ν¬ν¨ν λͺ¨λ μ¬μ μ€μ μμ κΊΌμ Έ μμ΅λλ€. μ΄ κ·μΉμ Intlayer μ€μ μ μ½κ³ λμ€ν¬μ μμ€ νμΌμ μ§μ μννλ―λ‘, μ¬μ μ€μ μ μν΄ μλμΌλ‘ μΌμ§κΈ°λ³΄λ€λ μ μ€ν μ νμ λ°λΌ νμ±νν΄μΌ ν©λλ€.
κ·μΉ
no-raw-text
μ¬μ μ μ μΈλμ§ μμ μ¬μ©μ λλ©΄ ν
μ€νΈλ₯Ό λ³΄κ³ ν©λλ€. intlayer extractμ λμΌν κ°μ§ λ°©μμ μ¬μ©νλ―λ‘ λΈλλ μ΄λ¦, CSS ν΄λμ€ λ° κΈ°μ μ μλ³μλ 무μλ©λλ€.
μ½λλ₯Ό ν΄λ¦½λ³΄λμ 볡μ¬
μ½ν
μΈ μ μΈ νμΌ(*.content.ts, β¦)μ μ μΈλ©λλ€.
νμΌ μ 체λ₯Ό ν λ²μ μμ νλ €λ©΄ npx intlayer extractλ₯Ό μ€ννμ¬ μ»΄νμΌλ¬κ° λ¬Έμμ΄μ μ¬μ μΌλ‘ μ΄λνλλ‘ νμΈμ.
μ΅μ
μ½λλ₯Ό ν΄λ¦½λ³΄λμ 볡μ¬
static-dictionary-key
μ¬μ ν€κ° λ°λμ λ¬Έμμ΄ λ¦¬ν°λ΄μ΄μ΄μΌ ν©λλ€.
μ»΄νμΌλ¬λ νΈμΆ μμΉμμ ν€λ₯Ό μ§μ μ½μ μ μμ λλ§ μ¬μ μ μ¬μ λ‘λ(pre-load)ν μ μμ΅λλ€. κ³μ°λ ν€λ₯Ό μ¬μ©νλ©΄ μ΅μ νλ₯Ό μλμΌλ‘ 건λλ°κ³ λͺ¨λ μ¬μ μ λ²λ€μ ν¬ν¨ν©λλ€.
μ½λλ₯Ό ν΄λ¦½λ³΄λμ 볡μ¬
μ΄λ useIntlayer, getIntlayer λ° λͺ¨λ νΈν μ΄λν°(useTranslation, useTranslations, formatMessage, <FormattedMessage id>, <Trans i18nKey>, β¦)μ μ μ©λ©λλ€.
no-dynamic-field-access
μ¬μ μμ μ½λ νλκ° μ μ μΌλ‘ μλ €μ Έ μμ΄μΌ ν©λλ€.
μ»΄νμΌλ¬λ μ¬μ©λμ§ μλ κ²μΌλ‘ νλ¨λλ νλλ₯Ό μ κ±°ν©λλ€. λμ μ κ·Όμ μ»΄νμΌλ¬κ° κ°μ§ν μ μμΌλ―λ‘ λ°νμμ μ½κΈ° μμ
μ΄ undefinedλ₯Ό λ°νν μ μμ΅λλ€.
μ½λλ₯Ό ν΄λ¦½λ³΄λμ 볡μ¬
enforce-adapter-import
μλ³Έ ν¨ν€μ§ λμ @intlayer/* νΈν μ΄λν°μ μ¬μ©μ κΆμ₯ν©λλ€. μλ³Έ ν¨ν€μ§λ λ²λ€λ¬ λ³μΉμ΄ μ€μ λ κ²½μ°μλ§ Intlayerλ‘ νμΈλμ§λ§, μ΄λν°λ νμ νμΈλ©λλ€. --fixλ‘ μλ μμ ν μ μμ΅λλ€.
μ½λλ₯Ό ν΄λ¦½λ³΄λμ 볡μ¬
no-unused-content
κΈ°λ³Έμ μΌλ‘ κΊΌμ Έ μμ΅λλ€. νλ‘μ νΈ λ΄μμ μ무 κ³³μμλ μ½μ§ μλ μ½ν μΈ μ μ¬λ¬ μμΉμμ μ μΈλ μ¬μ ν€λ₯Ό λ³΄κ³ ν©λλ€.
μ½λλ₯Ό ν΄λ¦½λ³΄λμ 볡μ¬
λ€λ₯Έ κ·μΉκ³Ό λ¬λ¦¬ μ΄ κ·μΉμ νμ¬ νμΌ νλλ§μΌλ‘ νλ¨ν μ μμ΅λλ€. νλ μ¬μ© μ¬λΆλ μ 체 νλ‘μ νΈμμ κ΄κ³μμλ§ νμ
ν μ μκΈ° λλ¬Έμ
λλ€. λ¦°νΈ μ€ν μ 첫 λ²μ§Έ μ½ν
μΈ μ μΈμ λ§λ¬μ λ Intlayer μ€μ μ λ‘λνκ³ , ν΄λΉ μ€μ μ μ μΈλ μμ€ νμΌ(build.traversePattern, compiler.transformPattern)μ μμ§ν ν @intlayer/lsp λ° VS Code νμ₯μ "λ―Έμ¬μ©" μ·¨μμ μ μ§μνλ λμΌν μ¬μ©λ λΆμκΈ°λ₯Ό μ€νν©λλ€. κ²°κ³Όλ cacheTtl λ°λ¦¬μ΄ λμ μΊμλλ―λ‘ νμΌλ§λ€ κ²μ¬νμ§ μκ³ 1ν μ€νλΉ ν λ²λ§ κ²μ¬λ₯Ό μνν©λλ€.
μ΅μ
μ½λλ₯Ό ν΄λ¦½λ³΄λμ 볡μ¬
μ€λ«λμ μ€νλλ μλν° μλ²μμ λ¦°νΈλ₯Ό μννλ©° λ³κ²½ μ¬νμ λ 빨리 λ°μνκ³ μΆμ λλ cacheTtlμ μ€μ΄μΈμ. λͺ¨λ
Έλ ν¬μμ λ¨μΌ λ¦°νΈ μ€νμ΄ μ¬λ¬ Intlayer νλ‘μ νΈμ κ±Έμ³ μμ λλ baseDirμ μ€μ νμΈμ.
침묡μ μ°μ ν©λλ€. μ¬κΈ°μ κ±°μ§ μμ±(false positive)μ΄ λ°μνλ©΄ νμν λ²μμ΄ μμ λ μ μμΌλ―λ‘, λΆμκΈ°κ° μΆμ ν μ μλ λ°©μμΌλ‘ μ¬μ μ μλΉν λλ μ무κ²λ λ³΄κ³ νμ§ μμ΅λλ€: μ½ν μΈ κ°μ²΄ μ 체λ₯Ό κ·Έλλ‘ μ λ¬, κ°μ²΄μμ λ°μΈλ©λ λ²μ ν¨μ(const t = useTranslations("home")), μ§μ κ°μ Έμ€κΈ°λ₯Ό ν΅ν μ μΈ μ κ·Ό(useDictionary(myDictionary)), λ€λ₯Έ μ¬μ μμμnest(), λλ μ€νλ λ μ°μ°μλ‘ λΆμμ ν΄μ§ νλ λͺ©λ‘ λ±μ λλ€. λ¨μΌ νμΌ μ»΄ν¬λνΈ(.vue,.svelte,.astro)λ μ€ν¬λ¦½νΈ λΈλ‘μ΄ μ¬κΈ°μ νμ±λμ§ μμΌλ―λ‘ μΈκΈλ μ¬μ μ λͺ¨λ νλλ₯Ό μ¬μ©νλ κ²μΌλ‘ κ°μ£Όλ©λλ€.
reportDuplicateKeysλ λΉλ μ .intlayer/μ κΈ°λ‘λλ λ³ν©λμ§ μμ μ¬μ μ μ½μΌλ―λ‘ νλ‘μ νΈκ° μ΅μ ν λ² λΉλλ λκΉμ§λ λμνμ§ μμ΅λλ€. ν€λ₯Ό 곡μ νλ λ μ μΈμ λ³ν©λλ©° μ΄λ μ¬λ°λ₯Έ ν¨ν΄μ
λλ€. λ€λ§ μμͺ½μ μ μλ νλκ° μ‘°μ©ν λ μ€ νλμ κ°λ§ μ μ§νκΈ° λλ¬Έμ μ΄ λ³΄κ³ κΈ°λ₯μ΄ μ 곡λ©λλ€.
λΆμκΈ°λ ESMμΌλ‘ μ 곡λλ @intlayer/lspμμ λ‘λλ©λλ€. λ°λΌμ μ΄ κ·μΉμ ES λͺ¨λμ require()ν μ μλ Node λ²μ (Node 20.19+ λλ 22.12+)μ΄ νμν©λλ€. μ΄μ λ²μ μμλ λ¦°νΈ μ€νμ μ€ν¨μν€λ λμ μ무κ²λ λ³΄κ³ νμ§ μμ΅λλ€.
νλ μμν¬
λͺ¨λ κ·μΉμ Vue, Svelte λ° Angular ν νλ¦Ώ λ΄λΆλ₯Ό ν¬ν¨νμ¬ λͺ¨λ Intlayer ν΅ν© νκ²½μμ μλν©λλ€. ESLintμ κ° νμΌ νμμ μ½μ νμλ§ μ§μ ν΄ μ£Όλ©΄ λ©λλ€.
ν μ΄λΈμ λͺ¨λ¬λ‘ μ΄μ΄ λͺ¨λ λ°μ΄ν°λ₯Ό λͺ ννκ² νμΈ
| νλ μμν¬ | νμΌ | νμ |
|---|---|---|
| React, Preact, Solid, Lit | .jsx .tsx | typescript-eslint |
| Next.js | .jsx .tsx | typescript-eslint |
| Vue, Nuxt | .vue | vue-eslint-parser |
| Svelte, SvelteKit | .svelte | svelte-eslint-parser |
| Angular | .ts | typescript-eslint |
| Angular ν νλ¦Ώ | .component.html | @angular-eslint/template-parser |
| Astro | .astro | astro-eslint-parser |
μ½λλ₯Ό ν΄λ¦½λ³΄λμ 볡μ¬
νλ‘μ νΈμ νμν νμλ§ μ€μΉνμΈμ.
μλ €μ§ μ ν μ¬ν. Vue λ° Angular ν νλ¦Ώμμ{{ content[key] }}μ κ°μ ννμμno-dynamic-field-accessμ μν΄ κ²μ¬λμ§ μμ΅λλ€. μ€ν¬λ¦½νΈ λΈλ‘μ μμ±λ λμ μ½κΈ°λ μ μμ μΌλ‘ κ°μ§λ©λλ€.
