이 페이지와 원하는 AI 어시스턴트를 사용하여 문서를 요약합니다
버전 기록
- "GitHub 스타 비교 추가"v8.9.82026. 5. 18.
- "벤치마크 초기화"v8.7.122026. 1. 6.
이 페이지의 콘텐츠는 AI를 사용하여 번역되었습니다.
영어 원본 내용의 최신 버전을 보기이 문서를 개선할 아이디어가 있으시면 GitHub에 풀 리퀘스트를 제출하여 자유롭게 기여해 주세요.
문서에 대한 GitHub 링크문서의 Markdown을 클립보드에 복사
Vue i18n 라이브러리 - 2026 벤치마크 리포트
이 페이지는 Vue i18n 솔루션에 대한 벤치마크 리포트입니다.
목차
인터랙티브 벤치마크
결과 참조:
전체 벤치마크 데이터 보기
전체 벤치마크 저장소는 여기에서 확인할 수 있습니다.
서론
국제화 솔루션은 Vue 앱에서 가장 무거운 의존성 중 하나입니다. 주요 위험은 불필요한 콘텐츠, 즉 단일 경로의 번들에 다른 페이지와 다른 로케일의 번역을 포함하는 것입니다.
앱이 성장함에 따라 이 문제는 클라이언트에 전송되는 JavaScript를 빠르게 팽창시키고 내비게이션을 느리게 만들 수 있습니다.
실제로 최적화가 가장 덜 된 구현의 경우, 국제화된 페이지가 i18n이 없는 버전보다 몇 배나 무거워질 수 있습니다.
또 다른 영향은 개발자 경험(DX)입니다: 콘텐츠 선언 방식, 타입, 네임스페이스 구성, 동적 로딩, 로케일 변경 시의 반응성 등이 포함됩니다.
TL;DR
- Intlayer: 내장된 스코핑(scoping)과 동적 로딩을 제공하는 가장 가벼운 솔루션(v8.7.12).
- vue-i18n: 풍부한 에코시스템을 가진 업계 표준이지만, 대규모 애플리케이션에서 코드 분할 최적화가 어렵고 상당히 무거워질 수 있습니다.
- fluent-vue: 혁신적인 메시지 구성을 제공하지만 타입 안전성이 부족하고 극도로 무거운 솔루션입니다.
앱 테스트하기
i18n 누수 문제를 빠르게 파악하기 위해 여기에서 시도해 볼 수 있는 무료 스캐너를 구축했습니다.
문제점
다국어 앱의 비용을 제한하려면 두 가지 레버가 필수적입니다:
- 페이지 / 네임스페이스별로 콘텐츠를 분리하여 필요하지 않을 때 전체 사전을 로드하지 않도록 합니다.
- 필요할 때만 올바른 로케일을 동적으로 로드합니다.
이러한 접근 방식의 기술적 한계 이해:
동적 로딩
동적 로딩이 없으면 대부분의 솔루션은 첫 번째 렌더링부터 메시지를 메모리에 유지하므로 경로와 로케일이 많은 앱의 경우 상당한 오버헤드가 발생합니다.
동적 로딩을 사용하면 초기 JS는 줄어들지만 언어 전환 시 추가 요청이 발생할 수 있는 장단점을 수용하게 됩니다.
콘텐츠 분리
const { t } = useI18n() + t('a.b.c')를 중심으로 구축된 구문은 매우 편리하지만 런타임에 큰 JSON 객체를 유지하도록 조장하는 경우가 많습니다. 이 모델은 라이브러리가 실제 페이지별 분리 전략을 제공하지 않는 한 트리 쉐이킹(tree-shaking)을 어렵게 만듭니다.
연구 방법론
이 벤치마크에서는 다음과 같은 라이브러리를 비교했습니다:
Base App(i18n 라이브러리 없음)vue-intlayer(v8.7.12)vue-i18n(v11.4.0)fluent-vue(v3.8.2)
프레임워크는 Vue이며 10개의 페이지와 10개의 언어를 가진 다국어 앱을 사용했습니다.
네 가지 로딩 전략을 비교했습니다:
테이블을 모달로 열어 모든 데이터를 명확하게 확인
| 전략 | 네임스페이스 없음 (글로벌) | 네임스페이스 포함 (스코프) |
|---|---|---|
| 정적 로딩 | Static: 시작 시 모든 것을 메모리에 로드. | Scoped static: 네임스페이스별 분리; 시작 시 모든 것을 로드. |
| 동적 로딩 | Dynamic: 로케일별 온디맨드 로딩. | Scoped dynamic: 네임스페이스 및 로케일별 세분화된 로딩. |
전략 요약
- Static: 간단함. 초기 로드 후 네트워크 지연 없음. 단점: 큰 번들 크기.
- Dynamic: 초기 무게 감소(지연 로딩). 로케일이 많을 때 적합함.
- Scoped static: 복잡한 추가 네트워크 요청 없이 코드 구조를 유지(논리적 분리).
- Scoped dynamic: 코드 분할 및 성능을 위한 최선의 접근 방식. 현재 뷰와 활성 로케일에 필요한 것만 로드하여 메모리 사용을 최소화함.
측정 항목:
각 스택에 대해 실제 브라우저에서 동일한 다국어 앱을 실행한 다음, 실제로 네트워크에 전송된 데이터와 소요 시간을 기록했습니다. 크기는 일반적인 웹 압축 후를 기준으로 보고되는데, 이는 원시 소스 코드 크기보다 실제 다운로드 크기에 더 가깝기 때문입니다.
국제화 라이브러리 크기: 번들링, 트리 쉐이킹 및 미니피케이션 후의 i18n 라이브러리 크기는 빈 컴포넌트에서의 프로바이더 + 컴포저블(composables) 코드 크기입니다. 여기에는 번역 파일 로딩은 포함되지 않습니다. 이는 콘텐츠가 들어가기 전에 라이브러리 자체가 얼마나 "무거운지"를 나타냅니다.
페이지당 JavaScript: 각 벤치마크 경로에 대해 브라우저가 해당 방문을 위해 가져오는 스크립트의 양으로, 테스트 세트의 페이지 전체(및 로케일 전체)에 대한 평균입니다. 무거운 페이지는 느린 페이지입니다.
다른 로케일에서의 누수 (Leakage): 감사 대상 페이지에서 실수로 로드되는 다른 언어의 동일 페이지 콘텐츠입니다. 이 콘텐츠는 불필요하며 피해야 합니다. (예:
/en/about페이지 번들에 포함된/fr/about페이지 콘텐츠)다른 경로에서의 누수: 앱의 다른 화면에 대해서도 동일한 개념입니다. 한 페이지만 열었을 때 다른 화면의 텍스트가 함께 포함되는지 여부입니다. (예:
/en/contact페이지 번들에 포함된/en/about페이지 콘텐츠). 점수가 높으면 분리가 약하거나 번들이 너무 광범위함을 암시합니다.평균 컴포넌트 번들 크기: 공통 UI 요소들을 하나씩 측정하여 국제화가 일상적인 컴포넌트들을 조용히 팽창시키는지 확인합니다. 예를 들어, 컴포넌트가 재렌더링될 때 메모리에서 해당 데이터를 모두 로드하게 됩니다. 컴포넌트에 거대한 JSON을 첨부하는 것은 사용하지 않는 데이터의 거대한 저장소를 연결하는 것과 같으며, 이는 컴포넌트의 성능을 저하시킵니다.
언어 전환 반응성: 앱 자체 컨트롤을 사용하여 언어를 전환하고, 방문자가 인지할 수 있을 정도로 페이지가 명확하게 전환될 때까지의 시간을 측정합니다.
언어 변경 후 렌더링 작업: 전환이 진행되는 동안 인터페이스가 새로운 언어를 위해 다시 그리는 데 소요된 노력입니다. "체감" 시간과 프레임워크 비용이 다를 때 유용합니다.
초기 페이지 로드 시간: 내비게이션부터 브라우저가 테스트 시나리오에 대해 페이지가 완전히 로드되었다고 판단할 때까지의 시간입니다. 콜드 스타트(cold starts)를 비교하는 데 좋습니다.
하이드레이션 시간 (Hydration): 클라이언트가 서버 HTML을 실제 클릭 가능한 상태로 변환하는 데 걸리는 시간입니다. 표의 대시(-)는 해당 구현이 이 벤치마크에서 신뢰할 수 있는 하이드레이션 수치를 제공하지 않았음을 의미합니다.
GitHub 스타
GitHub 스타는 프로젝트의 인기, 커뮤니티 신뢰 및 장기적인 관련성을 나타내는 강력한 지표입니다. 기술적 품질을 직접적으로 측정하는 것은 아니지만, 얼마나 많은 개발자가 프로젝트가 유용하다고 생각하고 진행 상황을 팔로우하며 채택할 가능성이 있는지를 반영합니다. 프로젝트의 가치를 평가할 때 스타는 대안 간의 견인력을 비교하는 데 도움이 되며 생태계 성장에 대한 통찰력을 제공합니다.
결과 상세
1 - 피해야 할 솔루션
Vue 에코시스템에서 분명하게 피해야 할 솔루션은 없습니다.
2 - 수용 가능한 솔루션
(vue-i18n) ([email protected]):
- vue-i18n은 논쟁의 여지 없이 Vue에서 가장 많이 사용되는 i18n 라이브러리이며, 많은 기능과 거대한 에코시스템을 가지고 있습니다. 하지만 내부적으로 이 솔루션은 상당히 무겁습니다. vue-i18n이 메시지 지연 로딩을 통합하더라도 스코핑(scoping) 기능이 부족합니다. 클래식 Vue SPA 앱의 경우 문제가 없으나, @nuxt/i18n을 사용하는 Nuxt 앱의 경우 모든 페이지의 메시지가 단일 페이지에 포함되는 결과를 초래합니다. 10페이지 이상의 대규모 Nuxt 앱의 경우 이는 정말 문제가 될 수 있습니다.
패키지가 매우 무겁습니다 (~24.3kb, vue-intlayer의 약 9배).
(fluent-vue) ([email protected]):
- fluent-vue는 .ftl 형식을 통해 혁신을 시도합니다. 메시지 구성이 훌륭하고 시작하기 쉽습니다. 하지만 실제로는 타입 안전성의 부재로 오류 위험이 높고 디버깅에 많은 시간이 소요될 수 있습니다. 또한, 이 솔루션은 Vite 플러그인을 사용하여 메시지를 로드하는데, 이는 모든 언어의 모든 콘텐츠를 각 페이지에 강제로 로드하게 만듭니다. 게다가 이는 극도로 무거운 솔루션입니다 (~92.7kb,
vue-intlayer의 약 34배).
3 - 추천 사항
(Intlayer) ([email protected]):
객관성을 위해 나의 솔루션인 vue-intlayer에 대해서는 직접 판단하지 않겠습니다.