이 페이지와 원하는 AI 어시스턴트를 사용하여 문서를 요약합니다
이 페이지의 콘텐츠는 AI를 사용하여 번역되었습니다.
영어 원본 내용의 최신 버전을 보기이 문서를 개선할 아이디어가 있으시면 GitHub에 풀 리퀘스트를 제출하여 자유롭게 기여해 주세요.
문서에 대한 GitHub 링크문서의 Markdown을 클립보드에 복사
next-intl VS Intlayer: React & Next.js 국제화(i18n) 벤치마크

next-intl은 Next.js에서 가장 널리 사용되는 i18n 라이브러리입니다. Intlayer는 컴파일러 기반의 컴포넌트 스코프 대안입니다. 두 라이브러리 모두 App Router 애플리케이션을 현지화합니다. 질문은 앱이 빌드된 후 각각의 비용이 얼마인가 하는 것입니다.
이 기사는 튜토리얼이 아닙니다. 각 라이브러리로 동일한 애플리케이션을 빌드하고 브라우저가 실제로 다운로드하고 실행하는 것을 측정하는 오픈 소스 벤치마크 스위트인 Benchmark Bloom의 수치로 뒷받침된 비교입니다.
요약 (tl;dr):next-intl은 런타임 비용만으로도 페이지당 최소 +12.6 KB gzip을 추가하며, 표준 설정(static및dynamic)에서 다른 페이지 문자열의 약 90%를 누출합니다. 이 누출을 제거하려면 카탈로그를 네임스페이스로 분할하고 페이지별로 수동 선택해야 하는 번거로운 작업이 필요합니다. 반면Intlayer컴파일러는 추가 설정 없이도 누출 0%, 3배 더 작은 컴포넌트 크기, 기본 앱 대비 단 +0.3 KB 증가만을 보장합니다.
한눈에 보기
- next-intl - Next.js 커뮤니티의 표준. 언어별 중앙 집중식 JSON 사전, 완전한 ICU MessageFormat 지원, Next.js 요청 처리 및 라우팅과의 긴밀한 통합.
- Intlayer - 컴포넌트 중심 콘텐츠 모델.
.content.ts파일이 담당 컴포넌트 바로 옆에 위치하며, 빌드 타임 컴파일러가 컴포넌트 및 로케일별로 트리 셰이킹과 지연 로딩을 수행하고 엄격한 TypeScript 타입을 자동으로 생성합니다.
테이블을 모달로 열어 모든 데이터를 명확하게 확인
배지는 자동으로 업데이트됩니다.
기능별 직접 비교
테이블을 모달로 열어 모든 데이터를 명확하게 확인
| 기능 | Intlayer (react-intlayer / next-intlayer) | next-intl (next-intl / use-intl) |
|---|---|---|
| 컴포넌트 인근 번역 파일 배치 | ✅ 예, 각 컴포넌트와 함께 .content.ts 위치 | ❌ messages/ 폴더 내 중앙 집중식 JSON 사전 |
| TypeScript 통합 | ✅ 콘텐츠로부터 자동 생성되는 엄격한 타입 | ⚠️ 메시지 경로에 대한 수동 global.d.ts 설정을 통해 지원 |
| 누락된 번역 감지 | ✅ TypeScript 오류 + 빌드 타임 오류/경고 | ⚠️ 런타임에서 누락된 키를 반환하거나 설정에 따라 오류 발생 |
| 풍부한 콘텐츠 (JSX / Markdown / 컴포넌트) | ✅ 직접 지원 | ⚠️ 컴포넌트 매핑을 포함한 t.rich()를 통해 지원 |
| ICU MessageFormat 지원 | ⚠️ 개발 중 | ✅ 예, 완전한 ICU 지원 |
| 동기식 서버 컴포넌트 지원 | ✅ next-intlayer/server의 useIntlayer가 자식 서버 컴포넌트에서 즉시 작동 | ❌ 비동기 서버 부모로부터 props를 통해 번역을 전달해야 함 |
| 트리 셰이킹 (Tree-shaking) | ✅ 컴포넌트 및 로케일별로 컴파일러가 자동 수행 | ⚠️ 네임스페이스를 수동 분할하고 pick()을 사용해야 함 |
| 지연 로딩 (Lazy loading) | ✅ 단 한 줄의 설정 (importMode: 'dynamic') | ⚠️ getRequestConfig에서 수동 동적 import 필요 |
| 비주얼 에디터 / CMS | ✅ 무료 비주얼 에디터 + 선택적 CMS | ❌ 없음 |
| AI 기반 자동 번역 | ✅ 내장 기능, 자체 API 키 사용 | ❌ 없음 |
| MCP 서버 및 에이전트 스킬 | ✅ 지원 | ❌ 없음 |
벤치마크
측정 항목
Benchmark Bloom 테스트 스위트는 각 라이브러리로 동일한 애플리케이션을 빌드합니다. 10개 페이지(home, about, blog, careers, contact, FAQ, pricing, products, settings, team), 10개 언어(en, fr, es, de, it, pt, zh, ja, ko, ru), 동일한 컴포넌트 및 동일한 콘텐츠로 구성됩니다. 페이지는 en과 fr로 측정됩니다. 각 라이브러리는 최대 4가지 로딩 전략으로 구현되었습니다.
테이블을 모달로 열어 모든 데이터를 명확하게 확인
| 전략 | 설명 | 대상 사용자 |
|---|---|---|
| static | 모든 로케일과 모든 페이지를 시작 시 함께 번들링하여 로드 | 빠른 프로토타입, AI 생성 코드 |
| dynamic | 활성 로케일만 로드하지만, 모든 페이지를 한 번에 가져옴 | 대부분의 프로젝트 |
| scoped-static | 라우트별 네임스페이스 분할, 지연 로딩 없음 | 드문 경우 |
| scoped-dynamic | 라우트별 네임스페이스 + 지연 로딩. 현재 로케일의 현재 페이지만 전송 | 엄격한 성능 예산이 필요한 앱 |
Intlayer에는 "scoped" 변형이 없습니다. 컴파일러가 콘텐츠 범위를 컴포넌트별로 자동 제한하므로 static 및 dynamic 행이 이미 스코프화되어 있습니다.
각 빌드에 대해 스위트는 다음을 기록합니다:
- 라이브러리 크기 (Lib size): i18n 라이브러리만 가져오는 빈 컴포넌트의 gzip 크기.
- 페이지 JS (Page JS): 페이지당 다운로드된 gzip JavaScript 크기.
- 로케일 누출률 (Locale leak %): 사용자가 보지 않는 로케일에 속한 문자열의 비율.
- 페이지 누출률 (Page leak %): 사용자가 머물고 있지 않은 페이지에 속한 문자열의 비율.
- 컴포넌트 평균 크기 (Component avg): 격리되어 컴파일된 각 컴포넌트의 평균 gzip 크기.
- E2E 반응성: 새 언어 선택부터 DOM의
html[lang]업데이트까지의 시간. - 하이드레이션 (Hydration): React 하이드레이션 단계의 소요 시간.
아래 수치는next-intl4.14.2 및intlayer9.5.1을 사용한 2026-09-12 실행 결과입니다.
Next.js (App Router) 결과
관심 있는 메트릭과 라이브러리를 선택하세요:
측정항목
동적 JSON 로드
런타임에 번역을 지연 로드합니다
범위가 지정된 JSON (네임스페이싱)
페이지별 번역 네임스페이스
이 측정항목은 무엇인가요?
국제화 라이브러리 번들의 총 gzip 압축 크기입니다. 여기에는 트리 쉐이킹 및 미니피케이션 후의 프로바이더 및 콘텐츠 검색 로직만 포함됩니다.
왜 중요한가요?
라이브러리 크기가 작으면 초기 JavaScript 페이로드가 줄어들어 클라이언트에서 다운로드 및 실행 시간이 빨라집니다.
보기 형식
테이블을 모달로 열어 모든 데이터를 명확하게 확인
| 라이브러리 | 전략 | 라이브러리 크기 (gz) | 평균 페이지 JS (gz) | 로케일 누출 | 페이지 누출 | 평균 컴포넌트 (gz) | E2E 반응성 | 하이드레이션 |
|---|---|---|---|---|---|---|---|---|
| 기본 앱 (i18n 없음) | - | 0.0 KB | 141.0 KB | 0.0% | 0.0% | 0.9 KB | 13.4 ms | 11.8 ms |
next-intl | static | 14.7 KB | 153.6 KB | 4.2% | 89.8% | 21.8 KB | 16.0 ms | 14.7 ms |
next-intl | dynamic | 14.7 KB | 153.6 KB | 9.7% | 89.9% | 21.8 KB | 15.6 ms | 14.8 ms |
next-intl | scoped-static | 14.7 KB | 153.6 KB | 0.0% | 0.0% | 80.1 KB | 17.9 ms | 17.4 ms |
next-intl | scoped-dynamic | 14.7 KB | 153.6 KB | 0.0% | 0.0% | 22.9 KB | 17.8 ms | 16.8 ms |
next-intlayer | static | 5.5 KB | 141.3 KB | 0.0% | 0.0% | 8.5 KB | 15.5 ms | 16.9 ms |
next-intlayer | dynamic | 5.5 KB | 141.3 KB | 0.0% | 0.0% | 6.9 KB | 15.3 ms | 15.9 ms |
@intlayer/next-intl (호환) | static | 8.0 KB | 147.5 KB | 0.0% | 0.0% | 8.1 KB | 14.5 ms | 12.8 ms |
@intlayer/next-intl (호환) | dynamic | 8.0 KB | 148.7 KB | 0.0% | 0.0% | 8.1 KB | 11.7 ms | 12.8 ms |
결과 해석
- 런타임 비용. 기본 앱은 페이지당 141.0 KB입니다.
next-intl은 이를 153.6 KB(모든 페이지에서 +12.6 KB gzip)로 늘리지만, Intlayer는 141.3 KB(+0.3 KB)로 거의 차이가 없습니다. - 콘텐츠 누출. 가장 흔히 사용되는 설정(
static및dynamic)에서next-intl은 전체en.json이 클라이언트 공급자에 들어가기 때문에 페이지마다 다른 페이지 문자열의 약 90%를 전송합니다. 이를 0%로 만들려면 복잡한 수동 네임스페이스 분할이 필요하지만, Intlayer는 기본적으로 0%입니다. - 컴포넌트 크기.
useTranslations()를 호출하는 컴포넌트는 평균 21.8 KB로 컴파일되지만,useIntlayer()를 사용하는 동일한 컴포넌트는 단 6.9 KB입니다.
모든 라이브러리와 전략이 포함된 전체 표는 Next.js 벤치마크 보고서에서 확인하세요.
TanStack Start (use-intl) 결과
use-intl은 next-intl의 프레임워크 독립적인 핵심 코어입니다. 동일한 API, 동일한 메시지 형식을 사용합니다. TanStack Start에서 이를 intlayer와 비교하면 방정식에서 Next.js 관련 요소를 배제할 수 있습니다.
테이블을 모달로 열어 모든 데이터를 명확하게 확인
| 라이브러리 | 전략 | 라이브러리 크기 (gz) | 평균 페이지 JS (gz) | 로케일 누출 | 페이지 누출 | 평균 컴포넌트 (gz) | E2E 반응성 |
|---|---|---|---|---|---|---|---|
| 기본 앱 (i18n 없음) | - | 0.0 KB | 111.0 KB | 0.0% | 0.0% | 0.7 KB | 8.1 ms |
use-intl | static | 14.1 KB | 179.8 KB | 50.0% | 89.8% | 76.0 KB | 6.7 ms |
use-intl | dynamic | 14.1 KB | 119.4 KB | 0.0% | 89.8% | 75.9 KB | 7.0 ms |
use-intl | scoped-static | 14.1 KB | 128.7 KB | 0.0% | 0.0% | 87.1 KB | 20.9 ms |
use-intl | scoped-dynamic | 14.1 KB | 128.7 KB | 0.0% | 0.0% | 87.1 KB | 13.3 ms |
intlayer | static | 5.0 KB | 125.8 KB | 50.0% | 0.0% | 8.1 KB | 3.2 ms |
intlayer | dynamic | 5.0 KB | 118.6 KB | 0.0% | 0.0% | 6.3 KB | 3.6 ms |
@intlayer/use-intl (호환) | dynamic | 7.3 KB | 129.7 KB | 0.0% | 0.0% | 9.3 KB | 8.7 ms |
결과 해석
- 단순한
use-intl설정은 기본 앱보다 페이지당 68.8 KB 더 많은 JS를 전송합니다. dynamic모드에서도use-intl은 119.4 KB에 달하며 여전히 89.8%의 페이지 누출을 유지합니다.- 아키텍처의 차이는 컴포넌트 크기에서 명확히 드러납니다.
use-intl의 76-87 KB 대비 Intlayer는 6-8 KB에 불과합니다. - 로케일 전환 속도는 Intlayer가 2~4배 더 빠릅니다(3 ms vs 7-21 ms).
전체 표는 TanStack Start 벤치마크 보고서에서 확인하세요.
왜 이런 차이가 발생하는가? 중앙 집중식 카탈로그 vs 컴파일된 사전

next-intl은 전통적인 방식을 따릅니다. 로케일당 하나의 JSON 파일이 getRequestConfig에서 로드되고, NextIntlClientProvider에 전달되며, t("namespace.key")로 읽힙니다.
코드를 클립보드에 복사
런타임은 페이지에서 어떤 키가 사용될지 미리 알 수 없으므로 전체 카탈로그를 전송하는 것이 유일하게 안전한 기본값입니다.
최적화에 도달하지 못할 때 발생하는 비용은 페이지와 언어라는 두 축에서 동시에 증가합니다:

Intlayer는 이 구조를 완전히 뒤집습니다. 콘텐츠는 컴포넌트 바로 옆에 선언됩니다.
코드를 클립보드에 복사
빌드 시 컴파일러는 어떤 컴포넌트가 어떤 사전을 가져오는지 감지하여 활성 로케일에 필요한 사전만 번들링합니다.
dynamic행의 수치를 얻으려면intlayer.config.ts에서dictionary.importMode: 'dynamic'을 설정하세요. 번들 최적화 문서를 참조하세요.
개발자 경험
클라이언트 컴포넌트
코드를 클립보드에 복사
코드를 클립보드에 복사
이 컴포넌트를 렌더링하는 모든 페이지에서NextIntlClientProvider에 전달되는 메시지에counter네임스페이스를 포함해야 합니다.
코드를 클립보드에 복사
코드를 클립보드에 복사
페이지에 등록할 것이 전혀 없습니다: 컴포넌트가 자체 콘텐츠를 직접 가져옵니다.
동기식 서버 컴포넌트
디자인 시스템 요소(내비게이션 바, 바닥글, 카드 등)는 클라이언트 컴포넌트의 자식으로 렌더링되는 서버 컴포넌트인 경우가 많으므로 비동기(async)일 수 없습니다.
코드를 클립보드에 복사
페이지에서 await getTranslations("counter") 및 await getFormatter()를 실행한 다음 결과를 props로 전달해야 합니다. 컴포넌트는 더 이상 독립적이지 않습니다.
코드를 클립보드에 복사
메타데이터
코드를 클립보드에 복사
코드를 클립보드에 복사
next-intl API 유지 및 Intlayer 출력 획득
위의 벤치마크 결과를 얻기 위해 기존 컴포넌트를 모두 다시 작성할 필요는 없습니다. @intlayer/next-intl은 드롭인 어댑터입니다. useTranslations, getTranslations, useFormatter, t.rich(), ICU 복수형을 그대로 유지하면서 Intlayer 컴파일러로 컴파일된 Intlayer 사전에서 콘텐츠를 제공합니다.
코드를 클립보드에 복사
벤치마크에서 동일한 앱의 호환 빌드는 애플리케이션 코드를 전혀 수정하지 않고도 페이지당 153.6 KB에서 147.5 KB로, 컴포넌트당 21.8 KB에서 8.1 KB로 줄었으며, 페이지 누출은 약 90%에서 0%로 개선되었습니다. 기존 messages/{locale}.json 파일은 JSON 동기화 플러그인을 통해 계속 단일 소스로 유지할 수 있습니다.
자세한 단계는 next-intl 마이그레이션 가이드를 참조하세요.
언제 무엇을 선택해야 할까요?
Next.js의 생태계 표준을 원하고, ICU MessageFormat에 의존하며, 앱이 중소 규모이거나 중앙 집중식 JSON을 요구하는 번역 플랫폼(Crowdin, Phrase, Lokalise...)과 연동하는 경우. 성능이 중요하다면 카탈로그를 네임스페이스로 나누고 페이지별로 pick()을 통해 메시지를 선별하는 시간을 고려해야 합니다.
이미 next-intl을 사용 중이며 코드 재작성 없이 번들 크기를 줄이고자 하는 경우. 호환 어댑터는 기존 import 구문과 messages/{locale}.json 파일을 단일 진실 공급원으로 유지합니다. next-intl vs @intlayer/next-intl에서 나란히 측정되었습니다.
자주 묻는 질문 (FAQ)
렌더링 시점에는 그렇지 않습니다. 차이점은 클라이언트에 전달되는 번들 크기에 있습니다. next-intl은 각 페이지마다 +12.6 KB gzip의 런타임 비용이 발생하며, 일반적인 설정에서는 다른 페이지의 문자열 중 약 90%를 함께 전송합니다. 언어 전환 및 하이드레이션 시간은 Next.js에서 유사합니다(15-18 ms). TanStack Start에서는 use-intl이 7-21 ms 걸리는 반면 Intlayer는 3-4 ms에 불과합니다.
네, scoped-dynamic 설정을 통해 가능합니다. messages/{locale}.json을 라우트당 하나의 네임스페이스로 분할한 다음 각 페이지에서 pick(messages, [...])을 사용하고 컴포넌트 변경 시 이 매핑을 정확하게 유지해야 합니다. 벤치마크의 scoped-* 행이 바로 이러한 작업의 결과입니다. Intlayer는 컴파일러가 컴포넌트별로 콘텐츠 범위를 지정하므로 별도 작업 없이 기본적으로 0%에 도달합니다. 번들 최적화를 참조하세요.
아닙니다. @intlayer/next-intl은 useTranslations, getTranslations, useFormatter, t.rich(), ICU 복수형 및 네비게이션 헬퍼를 유지하며, 컴파일된 딕셔너리에서 이를 제공합니다. next.config.ts에 플러그인 한 줄만 추가하면 됩니다. 단계별 안내는 next-intl 마이그레이션 가이드를 참조하세요.
네이티브 API에서 ICU 지원은 지속적으로 확장 중입니다. 호환 어댑터(@intlayer/next-intl, @intlayer/use-intl)는 이미 ICU를 지원합니다: 복수형, select, selectordinal, #, {ts, date, long}은 Intlayer의 ICU 리졸버를 통해 처리됩니다. 자세한 내용은 ICU 메시지 포맷 설명을 참조하세요.
네. JSON 동기화 플러그인이 해당 파일을 읽어 최상위 키를 딕셔너리로 분할하고, CLI나 CMS가 번역을 업데이트할 때 동일한 파일에 다시 기록합니다. 번역 팀의 워크플로는 변경되지 않습니다.
관련 비교
동일한 벤치마크, 다른 라이브러리:
next-intl 심층 분석:
참고 문서:
이러한 라이브러리가 어디에서 왔는지 이해하려면 JavaScript i18n의 역사를 읽어보세요.
GitHub STARS
GitHub 스타 수는 프로젝트의 인기, 커뮤니티의 신뢰 및 장기적인 지속 가능성을 보여주는 강력한 지표입니다.
커밋 활동
스타는 인기를, 커밋은 프로젝트에 투입된 작업량을 보여줍니다. 작성 시점 기준으로 Intlayer의 커밋 수는 약 7,500개로, 여기서 비교한 대부분의 라이브러리보다 많고 next-intl이나 next-i18next의 약 5배입니다.
- amannn/next-intl
- aymericzip/intlayer
기본 브랜치의 커밋 수, 출처: GitHub API.
Intlayer는 모노레포이므로 이 수치에는 모든 프레임워크 패키지, CLI, 문서가 포함됩니다. 커밋 수는 품질이 아닌 활동의 지표로 읽어 주세요.
npm 다운로드
- next-intl
- next-intlayer
출처: npm 레지스트리 다운로드 API.
다운로드 수는 가장 좋은 솔루션이 아니라 가장 오래된 솔루션에 보상을 줍니다. 수년 전에 출시된 라이브러리는 당시 이를 선택한 모든 프로젝트, 모든 CI 실행, 이에 의존하는 모든 패키지에 의해 여전히 설치됩니다. 이 수치는 새로운 선택보다 관성을 측정합니다.
AI 어시스턴트는 이 효과를 더 키웁니다. next-intl, i18next, vue-i18n은 AI가 학습한 코드 곳곳에 있으므로, AI는 대안을 비교하지 않고 이들을 기본으로 추천합니다. 추천이 다운로드를 늘리고, 그 다운로드가 다음 추천을 부추깁니다. 다운로드 수가 아니라 벤치마크로 비교하세요.
결론
next-intl은 탄탄하고 잘 유지 관리되는 라이브러리이며, 벤치마크에서도 Next.js 환경에서 결코 나쁜 선택이 아님을 확인할 수 있습니다. 하지만 중앙 집중식 카탈로그 모델은 최적화의 모든 부담을 개발자에게 전가합니다. 단순한 설정에서는 다른 페이지 콘텐츠가 약 90% 누출되며, 런타임 자체만으로도 모든 페이지에서 +12.6 KB gzip의 비용이 발생합니다.
Intlayer는 이 모든 작업을 컴파일러로 이전합니다. 컴포넌트별 사전, 로케일별 지연 로딩, 미사용 콘텐츠 정리는 규칙이 아닌 자동 빌드 결과물입니다. 동일한 앱에서 얻은 결과는 페이지당 +0.3 KB, 누출 0%, 3배 더 작은 컴포넌트, TanStack Start에서 2~4배 더 빠른 로케일 전환이었습니다.
모든 원시 데이터, 테스트 앱 및 스크립트는 Benchmark Bloom 저장소에 공개되어 있습니다. 직접 실행해 보세요.
자세한 내용은 'Why Intlayer?' 문서를 참조하세요.
댓글
아직 댓글이 없습니다. 첫 번째로 의견을 나눠보세요.
