작가:
    생성:2026-04-20마지막 업데이트:2026-05-18

    Svelte i18n 라이브러리 - 2026 벤치마크 리포트

    이 페이지는 Svelte i18n 솔루션에 대한 벤치마크 리포트입니다.

    목차

    인터랙티브 벤치마크

    결과 참조:

    intlayer.org
    전체 벤치마크 데이터 보기

    전체 벤치마크 저장소는 여기에서 확인할 수 있습니다.

    서론

    국제화 솔루션은 Svelte 앱에서 가장 무거운 의존성 중 하나입니다. 주요 위험은 불필요한 콘텐츠, 즉 단일 경로의 번들에 다른 페이지와 다른 로케일의 번역을 포함하는 것입니다.

    앱이 성장함에 따라 이 문제는 클라이언트에 전송되는 JavaScript를 빠르게 팽창시키고 내비게이션을 느리게 만들 수 있습니다.

    실제로 최적화가 가장 덜 된 구현의 경우, 국제화된 페이지가 i18n이 없는 버전보다 몇 배나 무거워질 수 있습니다.

    또 다른 영향은 개발자 경험(DX)입니다: 콘텐츠 선언 방식, 타입, 네임스페이스 구성, 동적 로딩, 로케일 변경 시의 반응성 등이 포함됩니다.

    TL;DR

    • Intlayer: 가장 성능 효율적인 선택(v8.7.12)으로, 발자국(footprint)이 가장 작습니다.
    • Paraglide: 트리 쉐이킹(tree-shaking)을 위한 강력한 후보이지만, 개발자 경험이 더 복잡하고 반응성 오버헤드가 있습니다.
    • svelte-i18n: Svelte를 위한 표준적이고 기능이 완비된 솔루션이지만, 번들 무게가 훨씬 더 큽니다(Intlayer의 약 7배).

    앱 테스트하기

    i18n 누수 문제를 빠르게 파악하기 위해 여기에서 시도해 볼 수 있는 무료 스캐너를 구축했습니다.

    intlayer.org

    문제점

    다국어 앱의 비용을 제한하려면 두 가지 레버가 필수적입니다:

    • 페이지 / 네임스페이스별로 콘텐츠를 분리하여 필요하지 않을 때 전체 사전을 로드하지 않도록 합니다.
    • 필요할 때만 올바른 로케일을 동적으로 로드합니다.

    이러한 접근 방식의 기술적 한계 이해:

    동적 로딩

    동적 로딩이 없으면 대부분의 솔루션은 첫 번째 렌더링부터 메시지를 메모리에 유지하므로 경로와 로케일이 많은 앱의 경우 상당한 오버헤드가 발생합니다.

    동적 로딩을 사용하면 초기 JS는 줄어들지만 언어 전환 시 추가 요청이 발생할 수 있는 장단점을 수용하게 됩니다.

    콘텐츠 분리

    t('a.b.c')를 중심으로 구축된 구문은 매우 편리하지만 런타임에 큰 JSON 객체를 유지하도록 조장하는 경우가 많습니다. 이 모델은 라이브러리가 실제 페이지별 분리 전략을 제공하지 않는 한 트리 쉐이킹을 어렵게 만듭니다.

    연구 방법론

    이 벤치마크에서는 다음과 같은 라이브러리를 비교했습니다:

    • Base App (i18n 라이브러리 없음)
    • svelte-intlayer (v8.7.12)
    • svelte-i18n (v4.0.1)
    • @inlang/paraglide-js (v2.17.0)

    프레임워크는 Svelte이며 10개의 페이지10개의 언어를 가진 다국어 앱을 사용했습니다.

    네 가지 로딩 전략을 비교했습니다:

    전략 네임스페이스 없음 (글로벌) 네임스페이스 포함 (스코프)
    정적 로딩 Static: 시작 시 모든 것을 메모리에 로드. Scoped static: 네임스페이스별 분리; 시작 시 모든 것을 로드.
    동적 로딩 Dynamic: 로케일별 온디맨드 로딩. Scoped dynamic: 네임스페이스 및 로케일별 세분화된 로딩.

    전략 요약

    • Static: 간단함. 초기 로드 후 네트워크 지연 없음. 단점: 큰 번들 크기.
    • Dynamic: 초기 무게 감소(지연 로딩). 로케일이 많을 때 적합함.
    • Scoped static: 복잡한 추가 네트워크 요청 없이 코드 구조를 유지(논리적 분리).
    • Scoped dynamic: 코드 분할 및 성능을 위한 최선의 접근 방식. 현재 뷰와 활성 로케일에 필요한 것만 로드하여 메모리 사용을 최소화함.

    측정한 항목:

    동일한 다국어 앱을 모든 스택에서 실제 브라우저로 실행하고, 실제로 전송된 내용과 소요 시간을 기록했습니다. 크기는 일반적인 웹 압축 후 보고되며, 이는 원본 소스 크기보다 사용자가 실제로 다운로드하는 내용에 더 가깝습니다.

    • 국제화 라이브러리 크기: 번들링, 트리 쉐이킹 및 최소화 후, i18n 라이브러리의 크기는 빈 컴포넌트의 providers + stores 코드 크기입니다. 번역 파일 로딩은 포함되지 않습니다. 콘텐츠가 포함되기 전 라이브러리의 비용이 어느 정도인지 나타냅니다.

    • 페이지당 JavaScript: 각 벤치마크 경로에 대해 해당 방문에서 브라우저가 가져오는 스크립트의 양입니다. 이는 스위트의 페이지들과 리포트가 롤업하는 로케일들 전체에서 평균화됩니다. 무거운 페이지는 느린 페이지입니다.

    • 다른 로케일에서의 누수: 감사된 페이지에서 실수로 로드될 수 있는 다른 언어의 동일한 페이지 콘텐츠입니다. 이 콘텐츠는 불필요하며 피해야 합니다. (예: /en/about 페이지 번들에서 /fr/about 페이지 콘텐츠)

    • 다른 경로에서의 누수: 다른 화면의 경우도 마찬가지입니다. 한 페이지만 열었을 때 해당 복사본이 함께 로드되는지 여부입니다. (예: /en/contact 페이지 번들에서 /en/about 페이지 콘텐츠). 높은 점수는 약한 분할 또는 과도하게 광범위한 번들을 시사합니다.

    • 평균 컴포넌트 번들 크기: 하나의 거대한 앱 번호 내에 숨겨지지 않고 한 번에 하나씩 측정된 일반적인 UI 조각들입니다. 국제화가 일상적인 컴포넌트를 어느 정도 증가시키는지 보여줍니다. 예를 들어, 컴포넌트가 다시 렌더링되면 메모리에서 모든 데이터를 로드합니다. 거대한 JSON을 컴포넌트에 연결하는 것은 컴포넌트의 성능을 느리게 할 거대한 미사용 데이터 저장소를 연결하는 것과 같습니다.

    • 언어 전환 반응성: 앱의 자체 컨트롤을 사용하여 언어를 전환하고 페이지가 명확하게 전환될 때까지의 시간을 측정합니다. 이는 방문자가 눈으로 보게 되는 시간이지, 랩 마이크로 스텝이 아닙니다.

    • 언어 변경 후 렌더링 작업: 더 좁은 후속 조치입니다. 전환이 진행 중인 상태에서 새 언어를 위해 인터페이스가 다시 칠하는 데 소요된 노력의 정도입니다. "느껴지는" 시간과 프레임워크 비용이 다를 때 유용합니다.

    • 초기 페이지 로드 시간: 테스트한 시나리오에 대해 브라우저가 페이지를 완전히 로드된 것으로 간주할 때까지의 시간입니다. 콜드 시작을 비교하는 데 유용합니다.

    • Hydration 시간: 앱이 노출할 때, 클라이언트가 서버 HTML을 실제로 클릭할 수 있는 것으로 변환하는 데 소요되는 시간입니다. 표의 대시는 해당 구현이 이 벤치마크에서 신뢰할 수 있는 hydration 수치를 제공하지 않음을 의미합니다.

    GitHub 스타

    GitHub 스타는 프로젝트의 인기, 커뮤니티 신뢰 및 장기적인 관련성을 나타내는 강력한 지표입니다. 기술적 품질을 직접적으로 측정하는 것은 아니지만, 얼마나 많은 개발자가 프로젝트가 유용하다고 생각하고 진행 상황을 팔로우하며 채택할 가능성이 있는지를 반영합니다. 프로젝트의 가치를 평가할 때 스타는 대안 간의 견인력을 비교하는 데 도움이 되며 생태계 성장에 대한 통찰력을 제공합니다.

    Star History Chart

    결과 상세

    1 - 피해야 할 솔루션

    Svelte 에코시스템에서 분명하게 피해야 할 솔루션은 없습니다.

    2 - 수용 가능한 솔루션

    (Paraglide) (@inlang/paraglide-js@2.17.0):

    Paraglide는 혁신적이고 잘 설계된 접근 방식을 제공합니다. Vite + Svelte 앱의 맥락에서 그들이 홍보하는 트리 쉐이킹은 기대대로 잘 작동합니다. 하지만 React + TanStack Start의 경우 트리 쉐이킹이 기대대로 작동하지 않았으며 Next.js도 마찬가지였습니다. 그럼에도 불구하고 Svelte 및 TanStack Start 프로젝트에서의 Paraglide 사용은 확인해 볼 가치가 있습니다. 워크플로우와 DX 또한 다른 옵션보다 복잡합니다. 개인적으로 푸시할 때마다 JS 파일을 다시 생성해야 하는 것을 선호하지 않으며, 이는 PR을 통한 개발자들 간의 지속적인 머지 충돌 위험을 만듭니다. 또한 이 도구는 Next.js보다 Vite에 더 집중하는 것으로 보입니다. 마지막으로 다른 솔루션과 비교하여 Paraglide는 콘텐츠를 렌더링하기 위한 현재 로케일을 가져오기 위해 스토어(예: Svelte store)를 사용하지 않습니다. 파싱되는 각 노드에 대해 localStorage / 쿠키 등에서 로케일을 요청합니다. 이는 컴포넌트 반응성에 영향을 미주는 불필요한 로직 실행을 초래합니다.

    paraglide에 관한 참고: 이 솔루션은 임포트를 위해 코드베이스에 코드를 주입하므로, 벤치마크 리포트의 'lib size' 메트릭은 거의 0에 가깝습니다. 코드 생성(Code generation)은 사용되는 함수에 필요한 로직(모든 접두사 vs 접두사 없음, 쿠키 vs 스토리지 등)만 포함되므로 좋은 방식입니다. 이에 비해 Intlayer는 빌드 시 환경 변수 주입을 통해 이 필터링을 수행하여 번들러가 로직에 따라 콘텐츠를 트리 쉐이킹하도록 강제합니다. 덕분에 paraglide와 intlayer는 i18next나 next-intl보다 6~10배 더 가벼운 솔루션이 됩니다.

    (svelte-i18n) (svelte-i18n@3.4.0):

    이 솔루션은 Svelte 프로젝트의 모든 i18n 요구 사항을 충족합니다. 하지만 i18next나 다른 주요 i18n 솔루션과 마찬가지로 조금 무겁습니다 (~15.9kb, svelte-intlayer의 약 7배).

    3 - 추천 사항

    (Intlayer) (svelte-intlayer@8.7.12):

    객관성을 위해 나의 솔루션인 svelte-intlayer에 대해서는 직접 판단하지 않겠습니다.

    개인적인 의견

    이 의견은 개인적인 것이며 벤치마크 결과에는 영향을 미치지 않습니다. 그럼에도 불구하고 i18n 세계에서는 번역된 콘텐츠를 위해 const t = useTranslation('xx') + <>{t('xx.xx')}</>와 같은 패턴에 대한 합의가 자주 보입니다.

    Svelte 앱에서 함수를 Slot으로 주입하는 것은 내 견해로는 안티 패턴입니다. 또한 피할 수 있는 복잡성과 JavaScript 실행 오버헤드(거의 눈에 띄지 않더라도)를 추가합니다.