Svelte 5: 컴파일러 기반 접근 방식과 정신 모델
빌드 시 완전히 사라지는 JavaScript 프레임워크를 상상해 보세요. 다운로드할 라이브러리가 없습니다. 가상 DOM은 런타임에 조정되며 브라우저 검사기에는 프레임워크 오버헤드가 표시되지 않습니다. 이 그리고 Svelte: 전통적인 의미의 프레임워크가 아니라 .svelte 구성 요소를 변환하는 컴파일러 순수하고 최적화된 JavaScript로. 2024년 10월에 출시된 Svelte 5는 이 모델을 세계에 혁명을 일으킨 범용 신호 기반 반응 시스템인 Runes로 레벨을 올리세요. 애플리케이션의 상태를 관리하는 곳입니다.
React, Vue 또는 Angular에서 온 경우 Svelte의 정신 모델에는 관점의 변화가 필요합니다. 그것에 관한 것이 아닙니다 새로운 API를 배우지만 프레임워크 자체가 런타임에 존재하지 않는다는 것을 이해합니다. 이 가이드는 당신을 도와줍니다 정신 모델을 구축하고 Svelte 컴파일러가 내부적으로 작동하는 방식과 Runes가 필요한 이유를 탐구합니다. 이 접근 방식의 자연스러운 발전을 나타냅니다.
무엇을 배울 것인가
- Svelte 컴파일러가 구성 요소를 순수 JavaScript로 변환하는 방법
- Svelte에는 가상 DOM이 필요하지 않기 때문에
- Svelte 5 작업을 위한 올바른 정신 모델
- 룬 및 신호 기반 반응성 소개
- React 및 Vue와의 성능 비교(2025~2026년 데이터)
- Runes를 사용하여 첫 번째 Svelte 5 구성 요소를 만드는 방법
가상 DOM의 문제
Svelte가 존재하는 이유를 이해하려면 먼저 Svelte가 무엇을 해결하는지 이해해야 합니다. React, Vue, Angular는 모두 가상 DOM: 프레임워크가 계산에 사용하는 실제 DOM의 메모리 내 표현입니다. 차이점을 비교하고(diffing) 필요한 변경 사항만 적용합니다. 이 접근 방식은 직관적으로 이해됩니다. DOM을 직접 조작하는 것보다 메모리 내 표현을 업데이트하는 것이 더 효율적이지만 비용이 많이 듭니다. 숨겨진: 아무것도 변경되지 않은 경우에도 가상 DOM 조정이 항상 발생합니다.
Svelte의 창시자인 Rich Harris는 "가상 DOM은 순수한 오버헤드입니다."에 커뮤니티에서 활발한 논쟁을 촉발한 2019년 기사입니다. 요점은 가상 DOM이 아니라는 것입니다. 전체적으로 느리지만 컴파일러가 제거할 수 있는 불필요한 작업이 발생합니다.
카운터를 표시하는 React 구성 요소를 고려해보세요.
// React: il virtual DOM riconcilia ad ogni render
function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<p>Contatore: {count}</p>
<button onClick={() => setCount(count + 1)}>
Incrementa
</button>
</div>
);
}
상태가 변경될 때마다 React는 다음을 수행해야 합니다. 구성 요소에 대한 새 가상 DOM을 생성하고 이를 다음과 비교합니다. 이전 것(diffing), 무엇이 변경되었는지 확인하고 마지막으로 실제 DOM을 업데이트합니다. 컴파일러 Svelte는 빌드 시 무엇이 변경될 수 있는지(단락의 텍스트만) 이미 알고 있으며 이를 직접 생성합니다. 중간 단계 없이 업데이트하는 코드입니다.
Svelte 컴파일러의 작동 방식
Svelte 구성요소와 .svelte 여기에는 스크립트, 템플릿 및 세 가지 선택 섹션이 포함되어 있습니다.
스타일. 빌드하는 동안 컴파일러는 이 파일을 구문 분석하고
세부적이고 외과적인 업데이트가 포함된 DOM.
<!-- Counter.svelte - Il componente sorgente -->
<script>
let count = $state(0);
</script>
<p>Contatore: {count}</p>
<button onclick={() => count++}>
Incrementa
</button>
컴파일러는 템플릿을 분석하고 다음을 이해합니다. {count} 그리고 유일하게 변하는 부분.
생성된 JavaScript에는 다음이 직접 포함됩니다. 노드 생성 <p>, 텍스트 노드를 삽입하고,
다음 경우에만 해당 텍스트 노드를 업데이트하는 효과를 등록합니다. count 변화. 가상 DOM이 없습니다.
의견 차이도 없고 화해도 없습니다.
단순화된 컴파일된 코드는 다음과 같습니다.
// Output del compilatore Svelte (semplificato)
import { mount, text, element } from 'svelte/internal';
export function Counter(target) {
let count = 0;
const p = element('p');
const countText = text(`Contatore: ${count}`);
const button = element('button');
button.addEventListener('click', () => {
count++;
// Aggiorna SOLO il text node specifico
set_data(countText, `Contatore: ${count}`);
});
append(p, countText);
append(target, p);
append(target, button);
}
이것이 컴파일러 기반 접근 방식의 핵심입니다. 컴파일러는 무엇을 변경하고 생성할 수 있는지 정확히 알고 있습니다. 런타임에 이 작업을 일반 비교 알고리즘에 위임하는 대신 이를 처리하기 위한 최적의 코드입니다.
번들 크기 비교(2025)
동등한 TodoList 구성 요소는 주요 프레임워크에서 매우 다양한 크기의 JavaScript 번들을 생성합니다.
- 리액트 19 + ReactDOM: ~42KB gzip 압축(런타임 포함)
- 뷰 3.5: ~22KB gzip 압축(런타임 포함)
- Angular 19(독립형): ~35KB gzip 압축(런타임 포함)
- 빠른 5: ~2-5KB gzipped(런타임 없음, 구성요소만)
구성 요소가 많은 대규모 애플리케이션의 경우 각 Svelte 구성 요소에는 다음이 포함되므로 이점이 줄어듭니다. 업데이트 코드입니다. 그러나 중간 규모 애플리케이션의 경우 Svelte가 여전히 전체 승자입니다. 브라우저에 대한 페이로드 측면에서.
Svelte 5의 패러다임 전환: 룬
Svelte 4는 할당을 기반으로 하는 마법의 반응성 시스템을 사용했습니다. 블록의 모든 변수
<script> 자동으로 반응적이었고 컴파일러는 전체에서 종속성을 추적했습니다.
빌드. 이는 간단한 경우에는 잘 작동했지만 중요한 제한 사항이 있었습니다.
.svelte 구성 요소 내에서만 가능하며 마법 같은 동작으로 인해 코드를 추론하기가 어려워졌습니다.
Svelte 5는 i를 소개합니다 Runes: 접두사가 붙은 특수 함수 $ 의사소통하는 사람
컴파일러와 직접적으로. 룬은 정상적인 기능이 아닙니다 — $state() 그것은 기능이 아니다
가져오고 호출하지만 컴파일러가 인식하는 특수 구문은 다음과 유사합니다. useState()
React에서는 린트 및 유형 검사를 위해 트랜스파일러에서 인식하지만 실제로는 일반적인 함수입니다.
주요 차이점: 룬이 작동합니다. 어디에나, .svelte 파일뿐만 아니라:
// counter.svelte.ts - Un modulo TypeScript puro con reattivita Svelte 5
export function createCounter(initial: number = 0) {
let count = $state(initial);
// $derived calcola automaticamente quando count cambia
const doubled = $derived(count * 2);
const isEven = $derived(count % 2 === 0);
function increment() { count++; }
function decrement() { count--; }
function reset() { count = initial; }
return {
get count() { return count; },
get doubled() { return doubled; },
get isEven() { return isEven; },
increment,
decrement,
reset
};
}
// Usabile in qualsiasi componente .svelte
// o in altri file TypeScript che importano questo modulo
이는 Svelte 4에 비해 급격한 변화입니다. 반응성을 갖춘 비즈니스 로직이 살아 있을 수 있습니다. 별도의 TypeScript 모듈에서 구성요소 간에 공유 가능하며 일반 단위 테스트와 별도로 테스트 가능합니다. 렌더링 환경에 의존하지 않습니다.
네 가지 기본 룬
Svelte 5에는 대부분의 사용 사례를 포괄하는 네 가지 주요 룬이 도입되었습니다.
<script lang="ts">
// $state: stato reattivo (sostituisce let reattivo di Svelte 4)
let name = $state('Federico');
let items = $state<string[]>([]);
// $derived: valori computati (sostituisce $: di Svelte 4)
const greeting = $derived(`Ciao, ${name}!`);
const itemCount = $derived(items.length);
// $effect: side effects (sostituisce $: con side effects di Svelte 4)
$effect(() => {
console.log('name cambiato:', name);
// Cleanup automatico quando l'effetto si ri-esegue
return () => console.log('cleanup prima del prossimo run');
});
// $props: props del componente (sostituisce export let di Svelte 4)
const { title, onClose = () => {} } = $props<{
title: string;
onClose?: () => void;
}>();
</script>
Svelte 4와 Svelte 5: 주요 차이점
Svelte 4를 사용해 본 경험이 있는 경우 Runes는 구문을 크게 변경합니다.
- 빠른 4:
let count = 0;(암시적 마법) → 빠른 5:let count = $state(0);(명백한) - 빠른 4:
$: doubled = count * 2;→ 빠른 5:const doubled = $derived(count * 2); - 빠른 4:
export let prop;→ 빠른 5:const { prop } = $props(); - 빠른 4:
on:click={handler}→ 빠른 5:onclick={handler}
Svelte 5는 "레거시 모드"에서 Svelte 4와의 이전 버전과의 호환성을 유지하므로 마이그레이션이 점진적으로 이루어질 수 있습니다.
Svelte 5 대 React: 실제 비교
접근 방식의 차이점을 구체적으로 이해하기 위해 React와 Svelte 5에 구현된 동일한 구성 요소를 살펴보겠습니다.
// React 19: SearchBox con debounce
import { useState, useEffect, useCallback } from 'react';
function SearchBox({ onSearch }: { onSearch: (q: string) => void }) {
const [query, setQuery] = useState('');
const [debouncedQuery, setDebouncedQuery] = useState('');
useEffect(() => {
const timer = setTimeout(() => {
setDebouncedQuery(query);
}, 300);
return () => clearTimeout(timer);
}, [query]);
useEffect(() => {
if (debouncedQuery) onSearch(debouncedQuery);
}, [debouncedQuery, onSearch]);
return (
<input
value={query}
onChange={e => setQuery(e.target.value)}
placeholder="Cerca..."
/>
);
}
<!-- Svelte 5: SearchBox con debounce -->
<script lang="ts">
const { onSearch }: { onSearch: (q: string) => void } = $props();
let query = $state('');
$effect(() => {
const timer = setTimeout(() => {
if (query) onSearch(query);
}, 300);
return () => clearTimeout(timer);
});
</script>
<input bind:value={query} placeholder="Cerca..." />
Svelte 5 버전은 "마법"이기 때문이 아니라 컴파일러가 동기화를 관리하기 때문에 더 간결합니다.
사이에 query 그리고 다음을 통해 입력 bind:value, 그리고 $effect 자동으로 추적
의존 query 종속성 배열에서 명시적으로 선언하지 않고도 가능합니다.
실제 성능: 데이터 및 벤치마크
합성 벤치마크는 오해의 소지가 있는 경우가 많지만, JS 프레임워크 벤치마크 2025 (집약적인 DOM 작업을 사용하여 실제 하드웨어에서 실행) Svelte 5가 지속적으로 상위 1/4위를 차지했습니다. 테스트된 거의 모든 작업에 대해:
- 10,000개의 행 생성: Svelte 5 ~1.2x 오버헤드 대 바닐라 JS, React ~2.1x
- 10번째 행마다 업데이트합니다. 스벨트 5 ~1.1x, 리액트 ~1.8x
- 행 강조 표시 선택: 스벨트 5 ~1.05x, 리액트 ~1.4x
- 생성 후 메모리: Svelte 5는 React보다 ~40% 적은 메모리를 사용합니다.
JavaScript를 구문 분석하고 실행하는 저사양 모바일 장치에서 이점이 가장 두드러집니다. 비용이 더 많이 듭니다. 최신 데스크탑에서는 일반적인 애플리케이션의 실질적인 차이가 눈에 띄지 않는 경우가 많습니다. 최종 사용자에게.
첫 번째 빠른 프로젝트 만들기 5
Svelte 5를 시작하는 가장 빠른 방법은 Svelte 기반의 공식 전체 스택 프레임워크인 SvelteKit을 사용하는 것입니다.
# Crea un nuovo progetto SvelteKit con Svelte 5
npm create svelte@latest my-svelte-app
cd my-svelte-app
# Seleziona: Skeleton project, TypeScript, ESLint, Prettier
npm install
# Avvia il dev server
npm run dev
다음을 확인하여 프로젝트에서 Svelte 5를 사용하는지 확인하세요. package.json:
{
"dependencies": {
"@sveltejs/kit": "^2.5.0",
"svelte": "^5.0.0"
},
"devDependencies": {
"@sveltejs/adapter-auto": "^3.0.0",
"vite": "^5.0.0"
}
}
Runes를 사용하여 첫 번째 구성 요소를 만듭니다. src/lib/components/Hello.svelte:
<script lang="ts">
// $props: tipo sicuro per le props del componente
const { name = 'Mondo' }: { name?: string } = $props();
// $state: stato locale reattivo
let clickCount = $state(0);
// $derived: valore computato da state e props
const message = $derived(
clickCount === 0
? `Ciao, ${name}!`
: `Ciao, ${name}! Hai cliccato ${clickCount} volt${clickCount === 1 ? 'a' : 'e'}`
);
</script>
<div class="hello">
<p>{message}</p>
<button onclick={() => clickCount++}>
Clicca qui
</button>
</div>
<style>
.hello {
padding: 1rem;
border: 1px solid #ccc;
border-radius: 8px;
}
button {
margin-top: 0.5rem;
padding: 0.5rem 1rem;
}
</style>
SvelteKit: 풀스택 프레임워크
혼자 빠르고 UI 레이어만 가능합니다. SvelteKit Svelte를 기반으로 구축된 애플리케이션 프레임워크 라우팅, SSR(서버 측 렌더링), SSG(정적 사이트 생성), 양식 작업 및 로드를 추가합니다. 데이터 가져오기 기능. React의 경우 Next.js, Vue의 경우 Nuxt와 동일합니다.
SvelteKit 프로젝트의 구조는 파일 기반 규칙을 따릅니다.
src/
├── routes/
│ ├── +layout.svelte # Layout globale
│ ├── +page.svelte # Homepage (/)
│ ├── about/
│ │ └── +page.svelte # Pagina /about
│ └── blog/
│ ├── +page.svelte # Lista articoli (/blog)
│ ├── +page.server.ts # Data fetching server-side
│ └── [slug]/
│ ├── +page.svelte # Articolo singolo (/blog/nome)
│ └── +page.server.ts
├── lib/
│ ├── components/ # Componenti condivisibili
│ └── utils/ # Utilita
└── app.html # Template HTML base
Svelte 5를 선택해야 하는 경우
Svelte 5는 다음과 같은 경우에 최적의 선택입니다.
- 업로드 성능이 중요함(모바일, 느린 연결)
- 번들 크기는 최소여야 합니다.
- 팀은 React와 다른 정신 모델을 기꺼이 배우고 싶어합니다.
- 상용구가 적은 우수한 DX(개발자 경험)를 원합니다.
- SvelteKit을 사용하여 SSR/SSG의 이점을 활용하는 콘텐츠 중심 사이트를 구축합니다.
다음과 같은 경우에는 Svelte 5가 올바른 선택이 아닐 수 있습니다.
- 팀은 강력한 React 경험을 갖고 있으며 마이그레이션 비용이 너무 많이 듭니다.
- 많은 UI 구성 요소 라이브러리를 찾고 있습니다(React 생태계가 더 광범위함).
- React(헤드리스 UI, Radix 등)를 사용하는 라이브러리와 통합되어야 합니다.
멘탈 모델: 명심해야 할 사항
Svelte 5를 사용하려면 프레임워크와 비교하여 몇 가지 근본적인 차이점을 내부화해야 합니다. 가상 DOM 기반:
- 컴파일러는 런타임이 아닌 도구입니다. 뭔가가 작동하지 않을 때 렌더링 루프가 아니라 컴파일러가 코드를 어떻게 해석할지 생각해 보세요.
-
룬은 컴파일러와 통신합니다.
$state(),$derived()나머지는 단순한 함수가 아닙니다. 반응성을 처리하는 방법에 대한 컴파일러에 대한 지침입니다. -
응답성은 설계상 세분화되어 있습니다. 실제로 존재하는 것만 빠르게 업데이트합니다.
변경되었습니다. 수동으로 최적화할 수 있는 메커니즘이 없습니다.
useMemoouseCallback. -
.svelte.ts 파일은 보편적인 응답성을 가능하게 합니다. 룬은 어떤 용도로든 사용할 수 있습니다.
확장자를 가진 파일
.svelte.tso.svelte.js, 구성 요소뿐만 아니라.
결론 및 다음 단계
Svelte 5는 프레임워크 생성 이후 프레임워크의 가장 중요한 발전을 나타냅니다. 접근 방식 컴파일러 기반은 새로운 것이 아니지만 Runes는 구성 요소의 범위를 벗어난 신호 기반 응답성을 사용합니다. 보다 유연하고 테스트 가능한 아키텍처 패턴을 가능하게 합니다. 그 결과는 다음을 결합한 프레임워크입니다. 뛰어난 성능, 최소한의 번들, 쓸모없는 상용구가 없는 개발자 경험.
시리즈의 다음 기사에서는 심층적으로 탐구합니다. $state 및 $derived: 어떻게 작동하는가
Proxy ES6를 통한 깊은 응답성 $derived 메모이제이션 구현 방법
구성 요소 간에 공유되는 TypeScript 파일에서 룬을 사용합니다.
시리즈: Svelte 5 및 프런트엔드 컴파일러 기반
- 제1조(본): 컴파일러 기반 접근 방식 및 정신 모델
- 기사 2: $state 및 $derived — 룬과의 보편적인 반응성
- 3조: $효과 및 수명 주기 — 사용 시기(사용하지 않을 경우)
- 기사 4: SvelteKit SSR, 스트리밍 및 로드 기능
- 기사 5: Svelte 5의 전환 및 애니메이션
- 기사 6: Svelte의 접근성: 컴파일러 경고 및 모범 사례
- 7장: 전역 상태 관리: 컨텍스트, 룬 및 저장소
- 기사 8: Svelte 4에서 Svelte 5로 마이그레이션 — 실용 가이드
- 조항 9: Svelte 5: Vitest, 테스트 라이브러리 및 극작가에서의 테스트







