@intlayer/docs 8.12.2 → 8.12.4-canary.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/blog.cjs.map +1 -1
- package/dist/cjs/common.cjs.map +1 -1
- package/dist/cjs/doc.cjs.map +1 -1
- package/dist/cjs/frequentQuestions.cjs.map +1 -1
- package/dist/cjs/generated/blog.entry.cjs +1 -0
- package/dist/cjs/generated/blog.entry.cjs.map +1 -1
- package/dist/cjs/generated/docs.entry.cjs +1 -0
- package/dist/cjs/generated/docs.entry.cjs.map +1 -1
- package/dist/cjs/generated/frequentQuestions.entry.cjs +1 -0
- package/dist/cjs/generated/frequentQuestions.entry.cjs.map +1 -1
- package/dist/cjs/generated/legal.entry.cjs +1 -0
- package/dist/cjs/generated/legal.entry.cjs.map +1 -1
- package/dist/cjs/legal.cjs.map +1 -1
- package/dist/esm/blog.mjs.map +1 -1
- package/dist/esm/common.mjs.map +1 -1
- package/dist/esm/doc.mjs.map +1 -1
- package/dist/esm/frequentQuestions.mjs.map +1 -1
- package/dist/esm/generated/blog.entry.mjs.map +1 -1
- package/dist/esm/generated/docs.entry.mjs.map +1 -1
- package/dist/esm/generated/frequentQuestions.entry.mjs.map +1 -1
- package/dist/esm/generated/legal.entry.mjs.map +1 -1
- package/dist/esm/legal.mjs.map +1 -1
- package/dist/types/blog.d.ts.map +1 -1
- package/dist/types/common.d.ts.map +1 -1
- package/dist/types/doc.d.ts.map +1 -1
- package/dist/types/frequentQuestions.d.ts.map +1 -1
- package/dist/types/legal.d.ts.map +1 -1
- package/docs/ar/bundle_optimization.md +250 -102
- package/docs/ar/configuration.md +10 -10
- package/docs/bn/bundle_optimization.md +252 -104
- package/docs/bn/configuration.md +10 -10
- package/docs/cs/bundle_optimization.md +253 -105
- package/docs/cs/configuration.md +10 -10
- package/docs/de/bundle_optimization.md +245 -97
- package/docs/de/configuration.md +10 -10
- package/docs/en/bundle_optimization.md +172 -49
- package/docs/en/configuration.md +10 -10
- package/docs/en-GB/bundle_optimization.md +230 -82
- package/docs/en-GB/configuration.md +10 -10
- package/docs/es/bundle_optimization.md +250 -102
- package/docs/es/configuration.md +10 -10
- package/docs/fr/bundle_optimization.md +223 -75
- package/docs/fr/configuration.md +10 -10
- package/docs/hi/bundle_optimization.md +253 -105
- package/docs/hi/configuration.md +10 -10
- package/docs/id/bundle_optimization.md +258 -110
- package/docs/id/configuration.md +10 -10
- package/docs/it/bundle_optimization.md +249 -103
- package/docs/it/configuration.md +10 -10
- package/docs/ja/bundle_optimization.md +245 -97
- package/docs/ja/configuration.md +10 -10
- package/docs/ko/bundle_optimization.md +253 -105
- package/docs/ko/configuration.md +10 -10
- package/docs/nl/bundle_optimization.md +249 -101
- package/docs/nl/configuration.md +10 -10
- package/docs/pl/bundle_optimization.md +258 -111
- package/docs/pl/configuration.md +10 -10
- package/docs/pt/bundle_optimization.md +256 -115
- package/docs/pt/configuration.md +10 -10
- package/docs/ru/bundle_optimization.md +253 -105
- package/docs/ru/configuration.md +10 -10
- package/docs/tr/bundle_optimization.md +255 -107
- package/docs/tr/configuration.md +10 -10
- package/docs/uk/bundle_optimization.md +250 -102
- package/docs/uk/configuration.md +10 -10
- package/docs/ur/bundle_optimization.md +257 -109
- package/docs/ur/configuration.md +10 -10
- package/docs/vi/bundle_optimization.md +259 -111
- package/docs/vi/configuration.md +10 -10
- package/docs/zh/bundle_optimization.md +260 -112
- package/docs/zh/configuration.md +10 -10
- package/docs/zh-TW/bundle_optimization.md +602 -0
- package/package.json +8 -8
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
---
|
|
2
2
|
createdAt: 2025-11-25
|
|
3
|
-
updatedAt: 2026-
|
|
4
|
-
title: i18n 번들 크기
|
|
5
|
-
description: 국제화(i18n) 콘텐츠를 최적화하여 애플리케이션 번들 크기를 줄이세요. Intlayer를 통해
|
|
3
|
+
updatedAt: 2026-06-07
|
|
4
|
+
title: i18n 번들 크기 및 성능 최적화
|
|
5
|
+
description: 국제화(i18n) 콘텐츠를 최적화하여 애플리케이션 번들 크기를 줄이세요. Intlayer를 통해 사전(dictionary)의 트리 쉐이킹(tree shaking)과 지연 로딩(lazy loading)을 활용하는 방법을 알아봅니다.
|
|
6
6
|
keywords:
|
|
7
7
|
- 번들 최적화
|
|
8
8
|
- 콘텐츠 자동화
|
|
@@ -16,33 +16,36 @@ slugs:
|
|
|
16
16
|
- concept
|
|
17
17
|
- bundle-optimization
|
|
18
18
|
history:
|
|
19
|
+
- version: 8.12.0
|
|
20
|
+
date: 2026-06-07
|
|
21
|
+
changes: "Babel/Webpack용 `intlayerPurgeBabelPlugin` 및 `intlayerMinifyBabelPlugin` 추가, 플러그인 파이프라인 명확화"
|
|
19
22
|
- version: 8.7.0
|
|
20
23
|
date: 2026-04-08
|
|
21
24
|
changes: "빌드 구성에 `minify` 및 `purge` 옵션 추가"
|
|
22
25
|
---
|
|
23
26
|
|
|
24
|
-
# i18n 번들 크기
|
|
27
|
+
# i18n 번들 크기 및 성능 최적화
|
|
25
28
|
|
|
26
|
-
JSON 파일에 의존하는
|
|
29
|
+
JSON 파일에 의존하는 전통적인 i18n 솔루션에서 가장 일반적인 문제 중 하나는 콘텐츠 크기를 관리하는 것입니다. 개발자가 콘텐츠를 네임스페이스로 수동으로 분리하지 않으면 사용자는 단일 페이지를 보기 위해 모든 페이지와 잠재적으로 모든 언어에 대한 번역을 다운로드해야 하는 경우가 많습니다.
|
|
27
30
|
|
|
28
|
-
예를
|
|
31
|
+
예를 들어 10개 언어로 번역된 10개의 페이지가 있는 애플리케이션의 경우, 사용자가 **단 하나**(현재 언어로 된 현재 페이지)만 필요함에도 불구하고 100페이지 분량의 콘텐츠를 다운로드하게 될 수 있습니다. 이는 대역폭 낭비와 로드 시간 증가를 초래합니다.
|
|
29
32
|
|
|
30
|
-
**Intlayer는 빌드
|
|
33
|
+
**Intlayer는 빌드 시간 최적화를 통해 이 문제를 해결합니다.** 코드를 분석하여 구성 요소(component)당 실제로 사용되는 사전이 무엇인지 감지하고, 필요한 콘텐츠만 번들에 다시 삽입합니다.
|
|
31
34
|
|
|
32
35
|
## 목차
|
|
33
36
|
|
|
34
37
|
<TOC />
|
|
35
38
|
|
|
36
|
-
## 번들
|
|
39
|
+
## 번들 분석하기
|
|
37
40
|
|
|
38
|
-
번들을 분석하는 것은 "무거운" JSON 파일과 코드 분할 기회를
|
|
41
|
+
번들을 분석하는 것은 "무거운" JSON 파일과 코드 분할(code-splitting) 기회를 파악하는 첫 번째 단계입니다. 이러한 도구는 애플리케이션의 컴파일된 코드의 시각적 트리맵을 생성하여 어떤 라이브러리가 가장 많은 공간을 차지하고 있는지 정확히 확인할 수 있게 해줍니다.
|
|
39
42
|
|
|
40
43
|
<Tabs>
|
|
41
44
|
<Tab value="vite">
|
|
42
45
|
|
|
43
46
|
### Vite / Rollup
|
|
44
47
|
|
|
45
|
-
Vite는 내부적으로 Rollup을 사용합니다. `rollup-plugin-visualizer` 플러그인은
|
|
48
|
+
Vite는 내부적으로 Rollup을 사용합니다. `rollup-plugin-visualizer` 플러그인은 그래프 내 모든 모듈의 크기를 보여주는 대화형 HTML 파일을 생성합니다.
|
|
46
49
|
|
|
47
50
|
```bash
|
|
48
51
|
npm install -D rollup-plugin-visualizer
|
|
@@ -55,7 +58,7 @@ import { visualizer } from "rollup-plugin-visualizer";
|
|
|
55
58
|
export default defineConfig({
|
|
56
59
|
plugins: [
|
|
57
60
|
visualizer({
|
|
58
|
-
open: true, // 브라우저에서
|
|
61
|
+
open: true, // 브라우저에서 리포트를 자동으로 엽니다
|
|
59
62
|
filename: "stats.html",
|
|
60
63
|
gzipSize: true,
|
|
61
64
|
brotliSize: true,
|
|
@@ -69,7 +72,7 @@ export default defineConfig({
|
|
|
69
72
|
|
|
70
73
|
### Next.js (Turbopack)
|
|
71
74
|
|
|
72
|
-
App Router
|
|
75
|
+
App Router와 Turbopack을 사용하는 프로젝트의 경우, Next.js는 추가 의존성 없이 사용할 수 있는 내장 실험용 분석기를 제공합니다.
|
|
73
76
|
|
|
74
77
|
```bash packageManager='npm'
|
|
75
78
|
npx next experimental-analyze
|
|
@@ -92,7 +95,7 @@ bun next experimental-analyze
|
|
|
92
95
|
|
|
93
96
|
### Next.js (Webpack)
|
|
94
97
|
|
|
95
|
-
Next.js에서 기본 Webpack 번들러를 사용하는 경우 공식 번들 분석기를
|
|
98
|
+
Next.js에서 기본 Webpack 번들러를 사용하는 경우 공식 번들 분석기를 사용하십시오. 빌드 중에 환경 변수를 설정하여 트리거할 수 있습니다.
|
|
96
99
|
|
|
97
100
|
```bash packageManager='npm'
|
|
98
101
|
npm install -D @next/bundle-analyzer
|
|
@@ -116,11 +119,11 @@ const withBundleAnalyzer = require("@next/bundle-analyzer")({
|
|
|
116
119
|
});
|
|
117
120
|
|
|
118
121
|
module.exports = withBundleAnalyzer({
|
|
119
|
-
// Next.js
|
|
122
|
+
// Next.js 설정
|
|
120
123
|
});
|
|
121
124
|
```
|
|
122
125
|
|
|
123
|
-
|
|
126
|
+
**사용 방법:**
|
|
124
127
|
|
|
125
128
|
```bash
|
|
126
129
|
ANALYZE=true npm run build
|
|
@@ -131,7 +134,7 @@ ANALYZE=true npm run build
|
|
|
131
134
|
|
|
132
135
|
### 표준 Webpack
|
|
133
136
|
|
|
134
|
-
Create React App (ejected), Angular 또는
|
|
137
|
+
Create React App (ejected), Angular, 또는 맞춤형 Webpack 설정의 경우 업계 표준인 `webpack-bundle-analyzer`를 사용합니다.
|
|
135
138
|
|
|
136
139
|
```bash packageManager='npm'
|
|
137
140
|
npm install -D webpack-bundle-analyzer
|
|
@@ -149,7 +152,7 @@ pnpm add -D webpack-bundle-analyzer
|
|
|
149
152
|
bun add -d webpack-bundle-analyzer
|
|
150
153
|
```
|
|
151
154
|
|
|
152
|
-
```typescript fileName="webpack.config.ts
|
|
155
|
+
```typescript fileName="webpack.config.ts"
|
|
153
156
|
import { BundleAnalyzerPlugin } from "webpack-bundle-analyzer";
|
|
154
157
|
|
|
155
158
|
export default {
|
|
@@ -168,16 +171,53 @@ export default {
|
|
|
168
171
|
|
|
169
172
|
## 작동 방식
|
|
170
173
|
|
|
171
|
-
Intlayer는 **컴포넌트별 접근
|
|
174
|
+
Intlayer는 **컴포넌트별 접근 방식(per-component approach)**을 사용합니다. 전역 JSON 파일과 달리 콘텐츠는 컴포넌트 내부나 컴포넌트 옆에 정의됩니다. 빌드 과정에서 Intlayer는 다음과 같은 작업을 수행합니다:
|
|
172
175
|
|
|
173
|
-
1.
|
|
174
|
-
2.
|
|
175
|
-
3.
|
|
176
|
+
1. **분석**: 코드를 분석하여 `useIntlayer` 호출을 찾습니다.
|
|
177
|
+
2. **구축**: 해당하는 사전 콘텐츠를 구축합니다.
|
|
178
|
+
3. **대체**: 설정에 따라 최적화된 코드로 `useIntlayer` 호출을 대체합니다.
|
|
176
179
|
|
|
177
|
-
이를 통해
|
|
180
|
+
이를 통해 다음과 같은 효과를 보장합니다:
|
|
178
181
|
|
|
179
|
-
- 컴포넌트가
|
|
180
|
-
- 컴포넌트가 지연
|
|
182
|
+
- 컴포넌트가 가져오기(import) 되지 않은 경우, 해당 콘텐츠는 번들에 포함되지 않습니다 (Dead Code Elimination).
|
|
183
|
+
- 컴포넌트가 지연 로드(lazy load) 되는 경우, 해당 콘텐츠도 지연 로드됩니다.
|
|
184
|
+
|
|
185
|
+
## 플러그인 레퍼런스
|
|
186
|
+
|
|
187
|
+
Intlayer의 빌드 최적화는 각각 단일 책임을 갖는 여러 개별 플러그인으로 나뉘어 있습니다. 각 플러그인이 어떤 역할을 하는지 이해하면 설정 시의 혼란을 방지할 수 있습니다.
|
|
188
|
+
|
|
189
|
+
### Babel 플러그인 (`@intlayer/babel`)
|
|
190
|
+
|
|
191
|
+
이들은 Webpack 기반 설정(Babel을 사용하는 Next.js, CRA, 커스텀 Webpack 등)의 `babel.config.js`에서 직접 사용됩니다.
|
|
192
|
+
|
|
193
|
+
| 플러그인 | 기능 |
|
|
194
|
+
| :---------------------------- | :----------------------------------------------------------------------------------------------------------------- |
|
|
195
|
+
| `intlayerExtractBabelPlugin` | `.content.ts` 파일을 스캔하여 컴파일된 사전을 `.intlayer/`에 작성합니다. |
|
|
196
|
+
| `intlayerOptimizeBabelPlugin` | `useIntlayer('key')`를 `useDictionary(hash)`로 재작성하고 일치하는 사전의 `import`를 주입합니다. |
|
|
197
|
+
| `intlayerPurgeBabelPlugin` | 모든 소스 파일을 스캔하여 컴파일된 `.intlayer/**/*.json` 사전 파일에서 **사용되지 않는 콘텐츠 필드**를 제거합니다. |
|
|
198
|
+
| `intlayerMinifyBabelPlugin` | JSON 파일과 소스 코드 모두에서 **콘텐츠 필드 키를 짧은 알파벳 별칭**(`title` → `a`)으로 **이름을 변경**합니다. |
|
|
199
|
+
|
|
200
|
+
> **플러그인 순서가 중요합니다.** `babel.config.js`에서 purge 및 minify 플러그인은 optimize 플러그인 **앞에** 나타나야 합니다. optimize 패스는 `useIntlayer('key')`를 불투명한 `useDictionary(hash)` 호출로 대체하여 purge 및 minify 패스가 어떤 필드가 사용되는지 식별하는 데 필요한 사전 키 정보를 지웁니다.
|
|
201
|
+
|
|
202
|
+
각 Babel 플러그인에는 구성을 로드할 때 한 번 `intlayer.config.ts`를 읽고 미리 해석된 값을 반환하는 옵션 헬퍼(options helper)가 있습니다:
|
|
203
|
+
|
|
204
|
+
| 옵션 헬퍼 | 사용하는 플러그인 |
|
|
205
|
+
| :--------------------------- | :---------------------------- |
|
|
206
|
+
| `getExtractPluginOptions()` | `intlayerExtractBabelPlugin` |
|
|
207
|
+
| `getOptimizePluginOptions()` | `intlayerOptimizeBabelPlugin` |
|
|
208
|
+
| `getPurgePluginOptions()` | `intlayerPurgeBabelPlugin` |
|
|
209
|
+
| `getMinifyPluginOptions()` | `intlayerMinifyBabelPlugin` |
|
|
210
|
+
|
|
211
|
+
### Vite 플러그인 (`vite-intlayer`)
|
|
212
|
+
|
|
213
|
+
Vite 사용자는 **이를 직접 구성하지 않습니다**. `vite.config.ts`에서 `withIntlayer()`를 호출하면 자동으로 설정됩니다. `intlayer.config.ts`의 `build.purge` 및 `build.minify` 플래그는 추가 플러그인 등록 없이 해당하는 동작을 토글합니다.
|
|
214
|
+
|
|
215
|
+
| 내부 Vite 플러그인 | 해당하는 동작 |
|
|
216
|
+
| :----------------- | :--------------------------------------------------------------------------------------- |
|
|
217
|
+
| Usage analyzer | `intlayerPurgeBabelPlugin`의 분석 패스와 동일 |
|
|
218
|
+
| Dictionary prune | `intlayerPurgeBabelPlugin`의 JSON 작성 패스와 동일 |
|
|
219
|
+
| Dictionary minify | `intlayerMinifyBabelPlugin`의 JSON 작성 패스와 동일 |
|
|
220
|
+
| Babel transform | `intlayerMinifyBabelPlugin`의 소스 코드 이름 변경 + `intlayerOptimizeBabelPlugin`과 동일 |
|
|
181
221
|
|
|
182
222
|
## 플랫폼별 설정
|
|
183
223
|
|
|
@@ -186,9 +226,9 @@ Intlayer는 **컴포넌트별 접근 방식**을 사용합니다. 전역 JSON
|
|
|
186
226
|
|
|
187
227
|
### Next.js
|
|
188
228
|
|
|
189
|
-
Next.js는
|
|
229
|
+
Next.js는 빌드 시 SWC를 사용하므로 optimize(가져오기 재작성) 패스를 위해 `@intlayer/swc` 플러그인이 필요합니다.
|
|
190
230
|
|
|
191
|
-
>
|
|
231
|
+
> Next.js에서 SWC 플러그인이 아직 실험 단계이므로 이 플러그인은 기본적으로 설치되지 않습니다. 향후 변경될 수 있습니다.
|
|
192
232
|
|
|
193
233
|
```bash packageManager="npm"
|
|
194
234
|
npm install -D @intlayer/swc
|
|
@@ -206,21 +246,63 @@ pnpm add -D @intlayer/swc
|
|
|
206
246
|
bun add -d @intlayer/swc
|
|
207
247
|
```
|
|
208
248
|
|
|
209
|
-
설치되면 Intlayer가 자동으로
|
|
249
|
+
설치되면 Intlayer가 플러그인을 자동으로 감지하여 사용합니다.
|
|
250
|
+
|
|
251
|
+
**purge 및 minify** 패스(필드 제거 및 필드 이름 변경)의 경우 `@intlayer/babel`을 함께 설치하고 Babel 플러그인을 추가합니다. Next.js는 변환을 위해 SWC를 사용하지만 플러그인 구성을 위해 `babel.config.js`를 계속 평가하므로 Babel 플러그인은 SWC 이전의 사전 패스(pre-pass)로 실행됩니다.
|
|
252
|
+
|
|
253
|
+
```bash packageManager="npm"
|
|
254
|
+
npm install -D @intlayer/babel
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
```javascript fileName="babel.config.js"
|
|
258
|
+
const {
|
|
259
|
+
intlayerPurgeBabelPlugin,
|
|
260
|
+
intlayerMinifyBabelPlugin,
|
|
261
|
+
getPurgePluginOptions,
|
|
262
|
+
getMinifyPluginOptions,
|
|
263
|
+
} = require("@intlayer/babel");
|
|
264
|
+
|
|
265
|
+
module.exports = {
|
|
266
|
+
presets: ["next/babel"],
|
|
267
|
+
plugins: [
|
|
268
|
+
// Purge: .intlayer/**/*.json에서 사용되지 않는 콘텐츠 필드 제거
|
|
269
|
+
[intlayerPurgeBabelPlugin, getPurgePluginOptions()],
|
|
270
|
+
// Minify: JSON + 소스 코드에서 콘텐츠 필드 키의 이름 변경
|
|
271
|
+
[intlayerMinifyBabelPlugin, getMinifyPluginOptions()],
|
|
272
|
+
// 주의: @intlayer/swc가 useIntlayer → useDictionary 재작성을 처리하므로
|
|
273
|
+
// intlayerOptimizeBabelPlugin은 여기서 필요하지 않습니다.
|
|
274
|
+
],
|
|
275
|
+
};
|
|
276
|
+
```
|
|
210
277
|
|
|
211
278
|
</Tab>
|
|
212
279
|
<Tab value="vite">
|
|
213
280
|
|
|
214
281
|
### Vite
|
|
215
282
|
|
|
216
|
-
Vite는 `vite-intlayer`의
|
|
283
|
+
Vite는 `vite-intlayer`의 종속성으로 포함된 `@intlayer/babel` 플러그인을 사용합니다. 가져오기 재작성, purge 및 minify를 포함한 전체 최적화 파이프라인은 기본적으로 활성화되어 있으며 추가 플러그인 등록이 필요하지 않습니다.
|
|
284
|
+
|
|
285
|
+
`intlayer.config.ts`에서 해당하는 플래그를 설정하여 purge와 minify를 활성화합니다:
|
|
286
|
+
|
|
287
|
+
```typescript fileName="intlayer.config.ts"
|
|
288
|
+
import type { IntlayerConfig } from "intlayer";
|
|
289
|
+
|
|
290
|
+
const config: IntlayerConfig = {
|
|
291
|
+
build: {
|
|
292
|
+
purge: true, // 번들된 JSON에서 사용되지 않는 콘텐츠 필드 제거
|
|
293
|
+
minify: true, // 콘텐츠 필드 키를 짧은 별칭으로 이름 변경
|
|
294
|
+
},
|
|
295
|
+
};
|
|
296
|
+
|
|
297
|
+
export default config;
|
|
298
|
+
```
|
|
217
299
|
|
|
218
300
|
</Tab>
|
|
219
301
|
<Tab value="webpack">
|
|
220
302
|
|
|
221
|
-
### Webpack
|
|
303
|
+
### Webpack (및 Babel이 포함된 Next.js)
|
|
222
304
|
|
|
223
|
-
|
|
305
|
+
`@intlayer/babel` 설치:
|
|
224
306
|
|
|
225
307
|
```bash packageManager="npm"
|
|
226
308
|
npm install -D @intlayer/babel
|
|
@@ -238,21 +320,44 @@ pnpm add -D @intlayer/babel
|
|
|
238
320
|
bun add -d @intlayer/babel
|
|
239
321
|
```
|
|
240
322
|
|
|
241
|
-
|
|
323
|
+
네 가지 플러그인을 `babel.config.js`에 올바른 순서로 모두 추가합니다:
|
|
324
|
+
|
|
325
|
+
```javascript fileName="babel.config.js"
|
|
242
326
|
const {
|
|
243
|
-
|
|
327
|
+
intlayerExtractBabelPlugin,
|
|
328
|
+
intlayerPurgeBabelPlugin,
|
|
329
|
+
intlayerMinifyBabelPlugin,
|
|
244
330
|
intlayerOptimizeBabelPlugin,
|
|
331
|
+
getExtractPluginOptions,
|
|
332
|
+
getPurgePluginOptions,
|
|
333
|
+
getMinifyPluginOptions,
|
|
334
|
+
getOptimizePluginOptions,
|
|
245
335
|
} = require("@intlayer/babel");
|
|
246
336
|
|
|
247
337
|
module.exports = {
|
|
248
|
-
plugins: [
|
|
338
|
+
plugins: [
|
|
339
|
+
// Extract: .content.ts 파일 컴파일 → .intlayer/**/*.json
|
|
340
|
+
[intlayerExtractBabelPlugin, getExtractPluginOptions()],
|
|
341
|
+
|
|
342
|
+
// Purge: .intlayer/**/*.json에서 사용되지 않는 필드 제거
|
|
343
|
+
// (intlayer.config.ts의 build.purge 플래그를 읽습니다)
|
|
344
|
+
[intlayerPurgeBabelPlugin, getPurgePluginOptions()],
|
|
345
|
+
|
|
346
|
+
// Minify: JSON + 소스 코드의 필드 키 이름 변경
|
|
347
|
+
// (intlayer.config.ts의 build.minify 플래그를 읽습니다)
|
|
348
|
+
[intlayerMinifyBabelPlugin, getMinifyPluginOptions()],
|
|
349
|
+
|
|
350
|
+
// Optimize: useIntlayer('key') → useDictionary(hash) 재작성
|
|
351
|
+
// 사전 키를 지우기 때문에 마지막에 위치해야 합니다.
|
|
352
|
+
[intlayerOptimizeBabelPlugin, getOptimizePluginOptions()],
|
|
353
|
+
],
|
|
249
354
|
};
|
|
250
355
|
```
|
|
251
356
|
|
|
252
357
|
</Tab>
|
|
253
358
|
</Tabs>
|
|
254
359
|
|
|
255
|
-
##
|
|
360
|
+
## 설정
|
|
256
361
|
|
|
257
362
|
`intlayer.config.ts`의 `build` 속성을 통해 Intlayer가 번들을 최적화하는 방법을 제어할 수 있습니다.
|
|
258
363
|
|
|
@@ -261,50 +366,55 @@ import { Locales, type IntlayerConfig } from "intlayer";
|
|
|
261
366
|
|
|
262
367
|
const config: IntlayerConfig = {
|
|
263
368
|
internationalization: {
|
|
264
|
-
locales: [Locales.ENGLISH, Locales.
|
|
369
|
+
locales: [Locales.ENGLISH, Locales.KOREAN],
|
|
265
370
|
defaultLocale: Locales.ENGLISH,
|
|
266
371
|
},
|
|
267
372
|
dictionary: {
|
|
268
373
|
importMode: "dynamic",
|
|
269
374
|
},
|
|
270
375
|
build: {
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
* 빌드 시 TypeScript 유형을 확인해야 하는지 여부
|
|
283
|
-
*/
|
|
284
|
-
checkTypes: false;
|
|
376
|
+
// 빌드 시 useIntlayer() 호출을 직접적인 사전(dictionary) 가져오기(import)로 대체합니다.
|
|
377
|
+
// undefined = 자동 (프로덕션에서 활성화), true = 항상, false = 비활성화.
|
|
378
|
+
optimize: undefined,
|
|
379
|
+
|
|
380
|
+
// 컴파일된 사전에서 콘텐츠 필드 키의 이름을 짧은 알파벳 별칭으로
|
|
381
|
+
// 바꿉니다(예: title → a). JSON 크기를 줄입니다; optimize가 필요합니다.
|
|
382
|
+
minify: true,
|
|
383
|
+
|
|
384
|
+
// 소스 코드에서 접근되지 않는 콘텐츠 필드를 제거합니다.
|
|
385
|
+
// optimize가 필요합니다.
|
|
386
|
+
purge: true,
|
|
285
387
|
},
|
|
286
388
|
};
|
|
287
389
|
|
|
288
390
|
export default config;
|
|
289
391
|
```
|
|
290
392
|
|
|
291
|
-
> 대부분의 경우 `optimize`
|
|
393
|
+
> 대부분의 경우 `optimize`는 기본값(`undefined`)을 유지하는 것이 좋습니다.
|
|
292
394
|
|
|
293
|
-
>
|
|
395
|
+
> 모든 옵션에 대해서는 설정 레퍼런스를 참조하세요: [Configuration](https://github.com/aymericzip/intlayer/blob/main/docs/docs/ko/configuration.md)
|
|
294
396
|
|
|
295
397
|
### 빌드 옵션
|
|
296
398
|
|
|
297
|
-
|
|
399
|
+
| 속성 | 타입 | 기본값 | 설명 |
|
|
400
|
+
| :------------- | :--------------------- | :---------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
401
|
+
| **`optimize`** | `boolean \| undefined` | `undefined` | 가져오기(import) 재작성 패스를 활성화합니다. `undefined` = 프로덕션 빌드에서만 활성화됩니다. `false`는 purge 및 minify도 비활성화합니다. |
|
|
402
|
+
| **`minify`** | `boolean` | `false` | 컴파일된 JSON 파일에서 콘텐츠 필드 키의 이름을 짧은 알파벳 별칭으로 바꿉니다. 소스 코드에서 일치하는 속성 접근도 재작성합니다. `optimize`가 `false`이면 아무 효과가 없습니다. |
|
|
403
|
+
| **`purge`** | `boolean` | `false` | 컴파일된 JSON 파일에서 소스 코드를 통해 정적으로 접근되지 않는 콘텐츠 필드를 제거합니다. `optimize`가 `false`이면 아무 효과가 없습니다. |
|
|
298
404
|
|
|
299
|
-
|
|
300
|
-
| :------------- | :-------- | :---------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
301
|
-
| **`optimize`** | `boolean` | `undefined` | 빌드 최적화 활성화 여부를 제어합니다. `true`인 경우 Intlayer는 사전 호출을 최적화된 주입으로 교체합니다. `false`인 경우 최적화가 비활성화됩니다. 프로덕션 환경에서는 `true`로 설정하는 것이 좋습니다. |
|
|
302
|
-
| **`minify`** | `boolean` | `false` | 번들 크기를 줄이기 위해 사전을 압축할지 여부입니다. |
|
|
303
|
-
| **`purge`** | `boolean` | `false` | 사전에서 사용되지 않는 키를 제거할지 여부입니다. |
|
|
405
|
+
### 최소화 (필드 키 이름 변경)
|
|
304
406
|
|
|
305
|
-
|
|
407
|
+
`build.minify`는 JavaScript 번들을 최소화**하지 않습니다**. (이 작업은 번들러가 수행합니다.) 대신 사용자 정의 콘텐츠 필드 키를 짧은 알파벳 별칭으로 대체하여 컴파일된 사전 JSON 파일을 축소합니다:
|
|
306
408
|
|
|
307
|
-
|
|
409
|
+
```
|
|
410
|
+
// 최소화 이전
|
|
411
|
+
{ "title": "안녕", "subtitle": "세계" }
|
|
412
|
+
|
|
413
|
+
// 최소화 이후
|
|
414
|
+
{ "a": "안녕", "b": "세계" }
|
|
415
|
+
```
|
|
416
|
+
|
|
417
|
+
소스 코드의 모든 속성 접근에도 동일한 이름 변경이 적용되므로, 컴파일된 출력에서는 `content.title`이 `content.a`가 됩니다. 런타임 동작은 동일합니다.
|
|
308
418
|
|
|
309
419
|
```typescript fileName="intlayer.config.ts"
|
|
310
420
|
import type { IntlayerConfig } from "intlayer";
|
|
@@ -318,11 +428,13 @@ const config: IntlayerConfig = {
|
|
|
318
428
|
export default config;
|
|
319
429
|
```
|
|
320
430
|
|
|
321
|
-
>
|
|
431
|
+
> `optimize`가 `false`이거나 `editor.enabled`가 `true`일 때(비주얼 에디터에서는 편집을 위해 원본 필드 이름이 필요함) 최소화는 건너뜁니다.
|
|
432
|
+
|
|
433
|
+
> `importMode: 'fetch'`를 통해 로드된 사전에서도 최소화는 건너뜁니다. JSON이 원본 필드 이름을 사용하여 원격 API에서 제공되기 때문입니다(클라이언트 측 키의 이름을 변경하면 서버/클라이언트 규약이 깨짐).
|
|
322
434
|
|
|
323
|
-
###
|
|
435
|
+
### 파지 (사용하지 않는 필드 제거)
|
|
324
436
|
|
|
325
|
-
|
|
437
|
+
`build.purge`는 소스 코드에서 실제로 접근하는 콘텐츠 필드를 분석하고 다른 모든 필드를 컴파일된 JSON 파일에서 제거합니다.
|
|
326
438
|
|
|
327
439
|
```typescript fileName="intlayer.config.ts"
|
|
328
440
|
import type { IntlayerConfig } from "intlayer";
|
|
@@ -336,34 +448,50 @@ const config: IntlayerConfig = {
|
|
|
336
448
|
export default config;
|
|
337
449
|
```
|
|
338
450
|
|
|
339
|
-
|
|
451
|
+
**예시:** 5개의 필드가 있지만 2개만 사용되는 사전:
|
|
452
|
+
|
|
453
|
+
```
|
|
454
|
+
// 파지 이전
|
|
455
|
+
{ "title": "…", "subtitle": "…", "cta": "…", "footer": "…", "badge": "…" }
|
|
456
|
+
|
|
457
|
+
// 파지 이후 (소스에서 title + subtitle만 접근됨)
|
|
458
|
+
{ "title": "…", "subtitle": "…" }
|
|
459
|
+
```
|
|
460
|
+
|
|
461
|
+
> `optimize`가 `false`이거나 `editor.enabled`가 `true`일 때 파지(purge)는 건너뜁니다.
|
|
462
|
+
|
|
463
|
+
> 소스 파일을 구문 분석할 수 없거나 `useIntlayer`의 결과가 변수에 할당되고 정적 분석기가 추적할 수 없는 방식으로 전달될 때(예: 객체에 스프레드, 구조 분해 없이 prop으로 전달) 파지도 보수적으로 건너뜁니다. 이런 경우에는 전체 사전이 유지됩니다.
|
|
464
|
+
|
|
465
|
+
### 가져오기 모드 (Import Mode)
|
|
340
466
|
|
|
341
|
-
|
|
467
|
+
여러 페이지와 로케일을 포함하는 대규모 애플리케이션의 경우 JSON이 번들 크기의 상당 부분을 차지할 수 있습니다. Intlayer에서는 `importMode` 옵션을 사용하여 사전 로드 방식을 제어할 수 있습니다.
|
|
342
468
|
|
|
343
|
-
|
|
469
|
+
### 전역 정의
|
|
344
470
|
|
|
345
|
-
|
|
471
|
+
가져오기 모드는 `intlayer.config.ts` 파일에서 전역으로 정의할 수 있습니다.
|
|
346
472
|
|
|
347
473
|
```typescript fileName="intlayer.config.ts"
|
|
348
474
|
import type { IntlayerConfig } from "intlayer";
|
|
349
475
|
|
|
350
476
|
const config: IntlayerConfig = {
|
|
351
|
-
|
|
352
|
-
|
|
477
|
+
dictionary: {
|
|
478
|
+
importMode: "dynamic", // 기본값은 'static'
|
|
353
479
|
},
|
|
354
480
|
};
|
|
355
481
|
|
|
356
482
|
export default config;
|
|
357
483
|
```
|
|
358
484
|
|
|
359
|
-
|
|
485
|
+
### 사전별 정의
|
|
486
|
+
|
|
487
|
+
각각의 `.content.{{ts|tsx|js|jsx|mjs|cjs|json|jsonc|json5|md|mdx|yaml|yml}}` 파일에서 개별 사전의 가져오기 모드를 재정의(override)할 수 있습니다.
|
|
360
488
|
|
|
361
489
|
```ts
|
|
362
490
|
import { type Dictionary, t } from "intlayer";
|
|
363
491
|
|
|
364
492
|
const appContent: Dictionary = {
|
|
365
493
|
key: "app",
|
|
366
|
-
importMode: "dynamic", // 기본
|
|
494
|
+
importMode: "dynamic", // 기본 가져오기 모드를 재정의
|
|
367
495
|
content: {
|
|
368
496
|
// ...
|
|
369
497
|
},
|
|
@@ -372,83 +500,103 @@ const appContent: Dictionary = {
|
|
|
372
500
|
export default appContent;
|
|
373
501
|
```
|
|
374
502
|
|
|
375
|
-
| 속성 |
|
|
376
|
-
| :--------------- | :--------------------------------- | :--------- |
|
|
377
|
-
| **`importMode`** | `'static'`, `'dynamic'`, `'fetch'` | `'static'` |
|
|
503
|
+
| 속성 | 타입 | 기본값 | 설명 |
|
|
504
|
+
| :--------------- | :--------------------------------- | :--------- | :---------------------------------------------------------------------------------------------------------------------- |
|
|
505
|
+
| **`importMode`** | `'static'`, `'dynamic'`, `'fetch'` | `'static'` | **사용되지 않음(Deprecated)**: 대신 `dictionary.importMode`를 사용하세요. 사전을 로드하는 방법을 결정합니다(아래 참조). |
|
|
378
506
|
|
|
379
|
-
`importMode` 설정은
|
|
380
|
-
`intlayer.config.ts` 파일의 `dictionary` 개체 아래에서 전역적으로 정의하거나, 특정 사전의 `.content.ts` 파일에서 재정의할 수 있습니다.
|
|
507
|
+
`importMode` 설정은 사전의 콘텐츠가 컴포넌트에 주입되는 방식을 결정합니다. `intlayer.config.ts`의 `dictionary` 객체에서 전역으로 정의하거나, 사전의 `.content.ts` 파일에서 개별적으로 재정의할 수 있습니다.
|
|
381
508
|
|
|
382
|
-
### 1.
|
|
509
|
+
### 1. Static 모드 (`default`)
|
|
383
510
|
|
|
384
|
-
정적 모드에서 Intlayer는 `useIntlayer`를 `useDictionary`로
|
|
511
|
+
Static(정적) 모드에서 Intlayer는 `useIntlayer`를 `useDictionary`로 대체하고 사전을 JavaScript 번들에 직접 주입합니다.
|
|
385
512
|
|
|
386
|
-
- **장점:**
|
|
387
|
-
- **단점:**
|
|
388
|
-
-
|
|
513
|
+
- **장점:** 즉각적인 렌더링(동기식), 하이드레이션(hydration) 중에 추가 네트워크 요청 없음.
|
|
514
|
+
- **단점:** 해당 컴포넌트에서 사용할 수 있는 **모든** 언어의 번역이 번들에 포함됨.
|
|
515
|
+
- **적합한 사례:** 단일 페이지 애플리케이션(SPA).
|
|
389
516
|
|
|
390
517
|
**변환된 코드 예시:**
|
|
391
518
|
|
|
392
519
|
```tsx
|
|
393
|
-
//
|
|
520
|
+
// 작성한 코드
|
|
394
521
|
const content = useIntlayer("my-key");
|
|
395
522
|
|
|
396
|
-
// 최적화된 코드 (
|
|
523
|
+
// 변환 후 최적화된 코드 예시 (Static)
|
|
524
|
+
// (설명을 위한 예시이며 최적화를 위해 실제 코드는 다를 수 있습니다)
|
|
397
525
|
const content = useDictionary({
|
|
398
526
|
key: "my-key",
|
|
399
527
|
content: {
|
|
400
528
|
nodeType: "translation",
|
|
401
529
|
translation: {
|
|
402
530
|
en: "My title",
|
|
403
|
-
|
|
531
|
+
ko: "나의 제목",
|
|
404
532
|
},
|
|
405
533
|
},
|
|
406
534
|
});
|
|
407
535
|
```
|
|
408
536
|
|
|
409
|
-
### 2.
|
|
537
|
+
### 2. Dynamic 모드
|
|
410
538
|
|
|
411
|
-
동적 모드에서 Intlayer는 `useIntlayer`를 `useDictionaryAsync`로
|
|
539
|
+
Dynamic(동적) 모드에서 Intlayer는 `useIntlayer`를 `useDictionaryAsync`로 대체합니다. 현재 로케일의 JSON만 특별히 지연 로드하기 위해 `import()`(Suspense와 유사한 메커니즘)를 사용합니다.
|
|
412
540
|
|
|
413
|
-
- **장점:** **로케일 수준의 트리 쉐이킹.** 영어 버전을 보는 사용자는 영어
|
|
414
|
-
- **단점:** 하이드레이션
|
|
415
|
-
-
|
|
541
|
+
- **장점:** **로케일 수준의 트리 쉐이킹.** 영어 버전을 보는 사용자는 영어 사전**만** 다운로드합니다. 한국어 사전은 로드되지 않습니다.
|
|
542
|
+
- **단점:** 하이드레이션 중에 컴포넌트별로 네트워크 요청(에셋 가져오기)을 트리거합니다.
|
|
543
|
+
- **적합한 사례:** 번들 크기가 중요한 대용량 텍스트 블록, 기사, 또는 여러 언어를 지원하는 애플리케이션.
|
|
416
544
|
|
|
417
545
|
**변환된 코드 예시:**
|
|
418
546
|
|
|
419
547
|
```tsx
|
|
420
|
-
//
|
|
548
|
+
// 작성한 코드
|
|
421
549
|
const content = useIntlayer("my-key");
|
|
422
550
|
|
|
423
|
-
// 최적화된 코드 (
|
|
551
|
+
// 변환 후 최적화된 코드 예시 (Dynamic)
|
|
552
|
+
// (설명을 위한 예시이며 최적화를 위해 실제 코드는 다를 수 있습니다)
|
|
424
553
|
const content = useDictionaryAsync({
|
|
425
554
|
en: () =>
|
|
426
555
|
import(".intlayer/dynamic_dictionary/my-key/en.json").then(
|
|
427
556
|
(mod) => mod.default
|
|
428
557
|
),
|
|
429
|
-
|
|
430
|
-
import(".intlayer/dynamic_dictionary/my-key/
|
|
558
|
+
ko: () =>
|
|
559
|
+
import(".intlayer/dynamic_dictionary/my-key/ko.json").then(
|
|
431
560
|
(mod) => mod.default
|
|
432
561
|
),
|
|
433
562
|
});
|
|
434
563
|
```
|
|
435
564
|
|
|
436
|
-
> `importMode: 'dynamic'`을 사용할 때 단일 페이지에서 `useIntlayer`를 사용하는 컴포넌트가 100개인
|
|
565
|
+
> `importMode: 'dynamic'`을 사용할 때 단일 페이지에서 `useIntlayer`를 사용하는 컴포넌트가 100개인 경우, 브라우저는 100번의 개별 가져오기(fetch)를 시도합니다. 이러한 요청의 "폭포수(waterfall)" 현상을 피하려면 콘텐츠를 아톰(atom) 컴포넌트별로 나누는 대신, 더 적은 수의 `.content` 파일(예: 페이지 섹션당 하나의 사전)로 그룹화하세요. 동일한 키를 사용하는 여러 개의 `.content` 파일을 사용할 수도 있습니다. Intlayer는 이들을 단일 사전으로 병합합니다.
|
|
566
|
+
|
|
567
|
+
### 3. Fetch 모드
|
|
437
568
|
|
|
438
|
-
|
|
569
|
+
Dynamic 모드와 유사하게 작동하지만 먼저 Intlayer Live Sync API에서 사전을 가져오려고 시도합니다. API 호출이 실패하거나 콘텐츠가 실시간 업데이트용으로 표시되지 않은 경우 동적(dynamic) 가져오기로 폴백(fallback)합니다.
|
|
570
|
+
|
|
571
|
+
**변환된 코드 예시:**
|
|
439
572
|
|
|
440
|
-
|
|
573
|
+
```tsx
|
|
574
|
+
// 작성한 코드
|
|
575
|
+
const content = useIntlayer("my-key");
|
|
576
|
+
|
|
577
|
+
// 최적화된 코드 예시 (Fetch)
|
|
578
|
+
const content = useDictionaryAsync({
|
|
579
|
+
en: () =>
|
|
580
|
+
fetch("https://intlayer.my-domain.com/dictionary/my-key/en").then((res) =>
|
|
581
|
+
res.json()
|
|
582
|
+
),
|
|
583
|
+
ko: () =>
|
|
584
|
+
fetch("https://intlayer.my-domain.com/dictionary/my-key/ko").then((res) =>
|
|
585
|
+
res.json()
|
|
586
|
+
),
|
|
587
|
+
});
|
|
588
|
+
```
|
|
441
589
|
|
|
442
|
-
> 자세한 내용은 CMS
|
|
590
|
+
> 자세한 내용은 CMS 설명서를 참조하세요: [CMS](https://github.com/aymericzip/intlayer/blob/main/docs/docs/ko/intlayer_CMS.md)
|
|
443
591
|
|
|
444
|
-
>
|
|
592
|
+
> fetch 모드에서는 JSON이 원본 필드 이름을 사용하여 원격 API에서 제공되므로 purge(파지) 및 minify(최소화)가 적용되지 않습니다.
|
|
445
593
|
|
|
446
|
-
## 요약:
|
|
594
|
+
## 요약: Static vs Dynamic
|
|
447
595
|
|
|
448
|
-
| 특징
|
|
449
|
-
|
|
|
450
|
-
| **JS 번들 크기**
|
|
451
|
-
| **초기 로드**
|
|
452
|
-
| **네트워크 요청**
|
|
453
|
-
| **트리 쉐이킹**
|
|
454
|
-
|
|
|
596
|
+
| 특징 | Static 모드 | Dynamic 모드 |
|
|
597
|
+
| :------------------- | :---------------------------------- | :----------------------------------- |
|
|
598
|
+
| **JS 번들 크기** | 큼 (해당 컴포넌트의 모든 언어 포함) | 최소 크기 (코드만 포함, 콘텐츠 없음) |
|
|
599
|
+
| **초기 로드** | 즉각적 (콘텐츠가 번들에 포함됨) | 약간의 지연 (JSON을 가져옴) |
|
|
600
|
+
| **네트워크 요청** | 추가 요청 0번 | 사전 키당 1번의 요청 |
|
|
601
|
+
| **트리 쉐이킹** | 컴포넌트 수준 | 컴포넌트 수준 + 로케일 수준 |
|
|
602
|
+
| **적합한 사용 사례** | UI 컴포넌트, 소규모 앱 | 텍스트가 많은 페이지, 다국어 지원 앱 |
|
package/docs/ko/configuration.md
CHANGED
|
@@ -679,16 +679,16 @@ routing: {
|
|
|
679
679
|
|
|
680
680
|
쿠키 저장소를 사용하는 경우 추가 쿠키 속성을 구성할 수 있습니다:
|
|
681
681
|
|
|
682
|
-
| 필드 | 설명
|
|
683
|
-
| ---------- |
|
|
684
|
-
| `name` | 쿠키 이름. 기본값: `'INTLAYER_LOCALE'`
|
|
685
|
-
| `domain` | 쿠키 도메인. 기본값: `undefined`
|
|
686
|
-
| `path` | 쿠키 경로. 기본값: `undefined`
|
|
687
|
-
| `secure` | HTTPS 필요 여부. 기본값: `undefined`
|
|
688
|
-
| `httpOnly` | HTTP-only 플래그. 기본값: `undefined`
|
|
689
|
-
| `sameSite` | SameSite 정책.
|
|
690
|
-
| `expires` |
|
|
691
|
-
| `maxAge` | 생성 후 초 단위의 수명. `expires`보다 우선합니다. 기본값: `undefined`
|
|
682
|
+
| 필드 | 설명 | 타입 |
|
|
683
|
+
| ---------- | ------------------------------------------------------------------------------------------------------ | ----------------------------------------------------- |
|
|
684
|
+
| `name` | 쿠키 이름. 기본값: `'INTLAYER_LOCALE'` | `string` |
|
|
685
|
+
| `domain` | 쿠키 도메인. 기본값: `undefined` | `string` |
|
|
686
|
+
| `path` | 쿠키 경로. 기본값: `undefined` | `string` |
|
|
687
|
+
| `secure` | HTTPS 필요 여부. 기본값: `undefined` | `boolean` |
|
|
688
|
+
| `httpOnly` | HTTP-only 플래그. 기본값: `undefined` | `boolean` |
|
|
689
|
+
| `sameSite` | SameSite 정책. | `'strict'` | <br/> `'lax'` | <br/> `'none'` |
|
|
690
|
+
| `expires` | 숫자는 생성 후 일수를 나타내고, 날짜(또는 ISO 날짜 문자열)는 절대 만료 날짜입니다. 기본값: `undefined` | `Date` | <br/> `number` | <br/> `string` |
|
|
691
|
+
| `maxAge` | 생성 후 초 단위의 수명. `expires`보다 우선합니다. 기본값: `undefined` | `number` |
|
|
692
692
|
|
|
693
693
|
#### 저장소 속성 (Storage Attributes)
|
|
694
694
|
|