1. Svelte 소개
1.1 Svelte란 무엇인가?
Svelte = 컴파일러
Svelte는 2016년 Rich Harris가 만든 현대적인 프론트엔드 프레임워크입니다. 다른 프레임워크와 달리 Svelte는 컴파일러로 동작합니다.
핵심 특징
- 빌드 시점에 최적화된 바닐라 JavaScript로 변환
- 런타임 오버헤드 없음 - 프레임워크 코드가 번들에 포함되지 않음
- 가상 DOM 없음 - 직접 DOM 조작으로 최고의 성능
코드로 보는 Svelte
<script>
let count = $state(0);
function increment() {
count += 1;
}
</script>
<button onclick={increment}>
클릭 횟수: {count}
</button>
Svelte 컴파일러의 마법
위의 간단한 코드가 아래와 같은 최적화된 JavaScript로 변환됩니다:
// Svelte가 생성하는 실제 JavaScript (간소화 버전)
function create_fragment(ctx) {
let button;
let t0;
let t1;
return {
c() {
// create - 요소 생성
button = element('button');
t0 = text('클릭 횟수: ');
t1 = text(ctx.count);
},
m(target, anchor) {
// mount - DOM에 추가
insert(target, button, anchor);
append(button, t0);
append(button, t1);
button.addEventListener('click', ctx.increment);
},
p(ctx, dirty) {
// update - 변경된 부분만 정확히 업데이트
if (dirty & 1) set_data(t1, ctx.count);
},
d(detaching) {
// destroy - 정리
if (detaching) detach(button);
button.removeEventListener('click', ctx.increment);
},
};
}
주목할 점: p
(update) 함수에서 t1
텍스트 노드만 업데이트합니다. 가상 DOM 비교나 전체 컴포넌트 재렌더링이 없습니다.
실습해보기: Svelte REPL에서 이 코드를 직접 실행해보세요! 컴파일러로 동작합니다. 즉, 개발자가 작성한 컴포넌트를 빌드 시점에 효율적인 바닐라 JavaScript로 변환합니다.
핵심 개념을 코드로 살펴보겠습니다:
<!-- Svelte 5 방식 (Rune 사용) -->
<script>
let count = $state(0);
function increment() {
count += 1;
}
</script>
<button onclick={increment}>
클릭 횟수: {count}
</button>
이 간단한 코드가 빌드되면, Svelte는 정확히 어느 부분이 변경되는지 알고 있는 최적화된 JavaScript를 생성합니다:
// Svelte가 생성하는 실제 JavaScript (간소화 버전)
function create_fragment(ctx) {
let button;
let t0;
let t1;
return {
c() {
// create
button = element('button');
t0 = text('클릭 횟수: ');
t1 = text(ctx.count);
},
m(target, anchor) {
// mount
insert(target, button, anchor);
append(button, t0);
append(button, t1);
button.addEventListener('click', ctx.increment);
},
p(ctx, dirty) {
// update - 정확히 텍스트 노드만 업데이트
if (dirty & 1) set_data(t1, ctx.count);
},
d(detaching) {
// destroy
if (detaching) detach(button);
button.removeEventListener('click', ctx.increment);
},
};
}
보시다시피 런타임에 가상 DOM을 비교하거나 상태 변화를 추적하는 라이브러리가 필요하지 않습니다. Svelte는 컴파일 시점에 t1
텍스트 노드만 업데이트하면 된다는 것을 알고, 해당 부분만 직접 수정하는 코드를 생성합니다.
Svelte의 철학
Svelte는 "적은 코드로 더 많은 일을" 원칙을 따릅니다. 복잡한 개념을 숨기고, 웹 표준(HTML, CSS, JavaScript)에 가까운 문법을 사용합니다:
<script>
let name = $state('World');
// $derived로 계산된 값 생성
let uppercaseName = $derived(name.toUpperCase());
</script>
<input bind:value={name} placeholder="이름을 입력하세요">
<p>안녕하세요, {uppercaseName}!</p>
Svelte 5의 새로운 Rune 시스템
Svelte 5는 더 명확하고 강력한 반응성을 위해 Rune 시스템을 도입했습니다:
Rune | 용도 | 기존 방식 대체 |
---|---|---|
$state | 반응형 상태 선언 | let 변수 |
$derived | 계산된 값 | $: 반응형 구문 |
$effect | 부수 효과 처리 | $: 구문, onMount |
$props | 컴포넌트 속성 | export let |
1.2 다른 프레임워크와의 차이점
React, Vue와의 비교
주요 프레임워크들과 Svelte의 차이를 실제 코드로 비교해보겠습니다.
왜 Svelte를 선택해야 하는가?
프레임워크 비교 - 같은 기능, 다른 코드량
React (7줄):
import React, { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0);
return (
<button onClick={() => setCount(count + 1)}>
Count: {count}
</button>
);
}
Vue 3 (8줄):
<template>
<button @click="count++">Count: {{ count }}</button>
</template>
<script setup>
import { ref } from 'vue';
const count = ref(0);
</script>
Svelte (5줄):
<script>
let count = $state(0);
</script>
<button onclick={() => count++}>
Count: {count}
</button>
결과: Svelte가 가장 간결합니다. 특별한 API 없이 직관적인 코드 작성이 가능합니다.
가상 DOM vs 컴파일 타임 최적화
동작 방식의 근본적 차이
단계 | 가상 DOM (React, Vue) | Svelte 컴파일 방식 |
---|---|---|
빌드 시 | 컴포넌트 + 프레임워크 번들링 | 최적화된 바닐라 JS 생성 |
런타임 초기화 | 프레임워크 로드 필요 | 즉시 실행 가능 |
상태 변경 시 | 1. 새 가상 DOM 생성 2. 이전과 비교(Diffing) 3. 변경사항 계산 4. DOM 업데이트 | 변경될 부분만 직접 업데이트 |
메모리 사용 | 가상 DOM 트리 유지 | 최소한의 메모리 |
실제 코드 생성 비교
Svelte 소스:
<script>
let count = $state(0);
</script>
<button onclick={() => count++}>
Count: {count}
</button>
↓ 컴파일 후
// Svelte: 정확한 업데이트 위치를 아는 코드
function update(dirty) {
if (dirty & 1) {
set_data(text_node, ctx.count); // 딱 이 부분만 업데이트!
}
}
React/Vue의 경우:
// 전체 컴포넌트 재실행 → 가상 DOM 생성 → 비교 → 업데이트
// 매번 이 과정을 반복해야 함
번들 크기와 성능 비교
초기 로딩 성능 - 번들 크기 (gzip 압축 후)
프레임워크 | 최소 앱 | 일반 앱 | 특징 |
---|---|---|---|
Svelte | ~10KB | 30-50KB | 프레임워크 런타임 없음 |
Vue 3 | ~34KB | 80-120KB | 런타임 포함 |
React | ~42KB | 100-150KB | React + ReactDOM |
런타임 성능 - 실제 벤치마크 (js-framework-benchmark)
작업 | Svelte 5 | React 18 | Vue 3 |
---|---|---|---|
1,000개 행 생성 | 35.2ms | 45.8ms | 41.3ms |
10,000개 행 업데이트 | 152.4ms | 203.7ms | 182.5ms |
부분 업데이트 | 15.8ms | 23.4ms | 19.2ms |
행 선택 | 3.2ms | 5.1ms | 4.3ms |
메모리 사용량 | 2.4MB | 3.8MB | 3.2MB |
낮은 수치 = 더 나은 성능
1.3 Svelte의 장점과 단점
장점
1. 뛰어난 성능
Svelte는 컴파일 타임 최적화를 통해 가상 DOM 없이도 정확히 변경된 부분만 업데이트하여 뛰어난 성능을 제공합니다. 1000개 아이템 중 특정 아이템만 수정해도 해당 아이템만 DOM에서 업데이트되어 효율적입니다. 대량 데이터 처리나 실시간 업데이트가 필요한 애플리케이션에서 특히 우수한 성능을 발휘합니다.
<script>
// 대량 데이터 처리 예시
let items = Array.from({ length: 1000 }, (_, i) => ({
id: i,
name: `Item ${i}`,
}));
function updateItem(id) {
// Svelte는 정확히 해당 아이템만 업데이트
items = items.map(item =>
item.id === id
? { ...item, name: `Updated ${item.name}` }
: item
);
}
</script>
{#each items as item (item.id)}
<div onclick="{()" ="">
updateItem(item.id)}> {item.name}
</div>
{/each}
2. 작은 번들 크기
Svelte는 컴파일러가 사용하지 않는 CSS와 개발 모드 코드를 자동으로 제거하여 최소한의 번들 크기를 생성합니다. 프로덕션 빌드에서 불필요한 코드가 완전히 제거되어 네트워크 비용과 로딩 시간을 크게 단축시킵니다. 특히 모바일 환경이나 제한된 네트워크 환경에서 빠른 초기 로딩을 보장합니다.
// svelte.config.js
export default {
compilerOptions: {
// 사용하지 않는 CSS 자동 제거
css: 'external',
// 개발 모드 코드 제거
dev: false,
},
};
3. 간결한 문법
Svelte는 {#if}
, {#each}
같은 직관적인 템플릿 문법으로 조건부 렌더링과 리스트 처리를 간단하게 구현할 수 있습니다.
별도의 JSX나 복잡한 문법 없이도 HTML과 유사한 구조로 동적 UI를 작성할 수 있어 학습 곡선이 완만합니다.
$state
를 통한 반응형 상태 관리가 내장되어 있어 추가적인 라이브러리 없이도 상태 관리가 가능합니다.
<script>
let show = $state(false);
let items = $state(['사과', '바나나', '오렌지']);
</script>
<!-- 조건부 렌더링 -->
{#if show}
<p>보이는 내용</p>
{:else}
<p>숨겨진 내용</p>
{/if}
<!-- 리스트 렌더링 -->
<ul>
{#each items as item}
<li>{item}</li>
{/each}
</ul>
4. 풍부한 내장 기능
Svelte는 fade, slide 같은 트랜지션과 tweened를 통한 애니메이션 기능을 기본 제공합니다. 별도의 애니메이션 라이브러리 없이도 부드러운 UI 전환과 모션 효과를 쉽게 구현할 수 있습니다. 이러한 내장 기능들이 번들 크기 증가 없이 제공되어 개발 생산성과 성능을 동시에 향상시킵니다.
<script>
import { fade, slide } from 'svelte/transition';
import { tweened } from 'svelte/motion';
let visible = $state(true);
const progress = tweened(0);
function start() {
progress.set(100);
}
function reset() {
progress.set(0);
}
function show() {
visible = true;
}
function hide() {
visible = false;
}
</script>
<!-- 트랜지션 제어 버튼 -->
<button onclick="{show}">보이기</button>
<button onclick="{hide}">숨기기</button>
<!-- 트랜지션 -->
{#if visible}
<div transition:fade class="fade-box">
<p>페이드 효과 영역</p>
<!-- 애니메이션 -->
<progress value="{$progress}" max="100"></progress>
<button onclick="{start}">시작</button>
<button onclick="{reset}">리셋</button>
</div>
{/if}
<style>
.fade-box {
border: 2px solid #333;
border-radius: 8px;
padding: 20px;
margin: 10px 0;
}
</style>
실습해보기: Svelte REPL에서 이 코드를 직접 실행해보세요!
약점
생태계 비교
Svelte는 React 대비 생태계가 제한적이며, UI 라이브러리나 상태 관리 도구의 선택지가 현저히 적습니다.
카테고리 | React | Svelte |
---|---|---|
UI 라이브러리 | Material-UI, Ant Design, Chakra UI 등 수십 개 | Skeleton UI, Carbon Components Svelte 등 소수 |
상태 관리 | Redux, MobX, Zustand, Recoil 등 | 자체 스토어 시스템 위주 |
데이터 페칭 | React Query, SWR, Apollo 등 | 제한적 선택지 |
커뮤니티 규모 (2025년 기준)
커뮤니티 규모는 React(70% 점유율)에 비해 Svelte는 2% 수준으로 매우 작으며, 개발자 수도 수만 명 정도에 그칩니다.
프레임워크 | 개발자 수 | 시장 점유율 |
---|---|---|
React | 수백만 명 | ~70% |
Vue | 수십만 명 | ~20% |
Angular | 수십만 명 | ~8% |
Svelte | 수만 명 | ~2% |
채용 시장 현실
채용 시장에서도 Svelte 관련 구인 공고는 전체의 2%에 불과해 취업 기회가 상당히 제한적인 상황입니다.
프레임워크 | 구인 공고 비율 | 평균 연봉 |
---|---|---|
React | 70% | 높음 |
Vue | 20% | 중상 |
Angular | 8% | 높음 |
Svelte | 2% | 데이터 부족 |
1.4 언제 Svelte를 선택해야 하는가?
Svelte가 빛나는 순간
1. 성능이 최우선인 프로젝트
Svelte는 컴파일 타임 최적화를 통해 런타임 오버헤드를 최소화하여, React나 Vue 대비 더 적은 메모리와 CPU 리소스로 동일하거나 더 우수한 성능을 달성할 수 있습니다. 특히 실시간 데이터 처리나 60fps 애니메이션 같은 고성능이 요구되는 상황에서, 가상 DOM 없이 직접적인 DOM 조작을 통해 효율적인 렌더링을 제공합니다. 결과적으로 배터리 수명이 중요한 모바일 환경이나 제한된 하드웨어 환경에서 특히 유리한 프레임워크입니다.
<!-- 실시간 데이터 시각화 예시 -->
<script>
import { onMount } from 'svelte';
let data = $state([]);
onMount(() => {
const interval = setInterval(() => {
// 60fps로 업데이트되는 데이터
data = generateNewData();
}, 16);
return () => clearInterval(interval);
});
function generateNewData() {
return Array.from({ length: 100 }, () => ({
x: Math.random() * 500,
y: Math.random() * 300,
}));
}
</script>
<svg width="500" height="300">
{#each data as point}
<circle
cx="{point.x}"
cy="{point.y}"
r="2"
fill="#667eea"
/>
{/each}
</svg>
실습해보기: Svelte REPL에서 이 코드를 직접 실행해보세요!
2. 제한된 네트워크/디바이스 환경
제한된 네트워크나 디바이스 환경에서 Svelte는 현저히 작은 번들 크기를 자랑합니다. 간단한 앱의 경우 React 대비 10배 작은 10-30KB, 중간 복잡도에서는 5배 작은 30-50KB로 네트워크 비용과 로딩 시간을 크게 줄일 수 있습니다. 이는 저사양 디바이스나 느린 네트워크 환경의 사용자에게 더 나은 사용자 경험을 제공하며, 특히 개발도상국이나 모바일 우선 환경에서 중요한 장점이 됩니다.
앱 복잡도 | Svelte | React | 크기 차이 |
---|---|---|---|
간단한 앱 | 10-30KB | 100KB+ | 10배 |
중간 복잡도 | 30-50KB | 150KB+ | 5배 |
복잡한 앱 | 50-100KB | 200KB+ | 2-4배 |
3. 빠른 프로토타이핑이 필요한 경우
Svelte는 빠른 프로토타이핑에 매우 적합한 프레임워크입니다.
단 20줄의 코드로 완전한 Todo 앱을 구현할 수 있을 정도로 간결한 문법과 내장 기능($state
, bind:value
, {#each}
등)을 제공합니다.
별도의 상태 관리 라이브러리나 복잡한 설정 없이도 즉시 동작하는 애플리케이션을 만들 수 있어, 아이디어 검증이나 MVP 개발에 이상적입니다.
<script>
let todos = $state([]);
let newTodo = $state('');
function addTodo() {
if (newTodo.trim()) {
todos = [...todos, {
id: Date.now(),
text: newTodo,
done: false
}];
newTodo = '';
}
}
function toggleTodo(id) {
const todo = todos.find(t => t.id === id);
if (todo) todo.done = !todo.done;
}
</script>
<input
bind:value={newTodo}
placeholder="할 일 추가"
onkeypress={(e) => e.key === 'Enter' && addTodo()}
>
<button onclick={addTodo}>추가</button>
<ul>
{#each todos as todo (todo.id)}
<li>
<input
type="checkbox"
checked={todo.done}
onchange={() => toggleTodo(todo.id)}
>
<span class:done={todo.done}>{todo.text}</span>
</li>
{/each}
</ul>
<style>
.done { text-decoration: line-through; opacity: 0.5; }
</style>
실습해보기: Svelte REPL에서 이 코드를 직접 실행해보세요!
Svelte가 적합하지 않은 경우
대규모 엔터프라이즈 프로젝트
- 수백 명의 개발자가 참여하는 프로젝트
- React/Angular의 성숙한 아키텍처 패턴이 유리
특정 생태계 의존성이 높은 경우
- React Native 모바일 앱 개발
- Next.js 같은 특정 메타 프레임워크 필요
- 기존 React 컴포넌트 라이브러리 재사용
실제 도입 사례
Svelte를 선택한 기업들
실제로 New York Times는 인터랙티브 뉴스 그래픽에, Spotify는 마케팅 페이지에 Svelte를 도입하여 빠른 로딩과 성능 최적화를 달성했습니다.
기업 | 사용 사례 | 선택 이유 |
---|---|---|
New York Times | 인터랙티브 뉴스 그래픽 | 빠른 로딩, 부드러운 애니메이션 |
Spotify | 마케팅 페이지, Wrapped | 성능과 번들 크기 |
IKEA | 글로벌 사이트 템플릿 | 다국가 배포 시 작은 번들 |
1Password | 브라우저 확장 프로그램 | 메모리 효율성 |
프로젝트 유형별 적합도
Svelte는 랜딩 페이지, 대시보드, 데이터 시각화, 브라우저 확장 같은 성능과 번들 크기가 중요한 프로젝트에서 5점 만점의 적합도를 보입니다. 반면 대규모 SaaS나 엔터프라이즈 앱에서는 생태계 제약과 팀 확장성 문제로 인해 2점의 낮은 적합도를 나타내, 프로젝트 규모와 특성에 따른 신중한 선택이 필요합니다.
프로젝트 유형 | 적합도 | 이유 |
---|---|---|
랜딩 페이지 | ★★★★★ | 빠른 로딩, SEO 유리 |
대시보드 | ★★★★★ | 실시간 업데이트 성능 |
데이터 시각화 | ★★★★★ | 효율적인 DOM 조작 |
브라우저 확장 | ★★★★★ | 작은 번들 크기 |
PWA | ★★★★☆ | 오프라인 성능 |
대규모 SaaS | ★★☆☆☆ | 생태계 제약 |
엔터프라이즈 앱 | ★★☆☆☆ | 팀 확장성 문제 |
마이그레이션 가이드
점진적 도입 전략
Svelte는 기존 애플리케이션에 점진적으로 도입할 수 있는 전략을 제공합니다. 기존 JavaScript 코드에서 특정 영역에만 Svelte 컴포넌트를 마운트하여, 전체 앱을 리팩토링하지 않고도 부분적으로 활용할 수 있습니다. 이를 통해 위젯이나 특정 기능부터 시작해서 점차 확장하는 방식으로 리스크를 최소화하면서 Svelte의 장점을 경험할 수 있습니다.
// 1. 기존 앱에 Svelte 컴포넌트 임베드
// Widget.svelte
export default class Widget {
constructor(target) {
// 기존 앱의 특정 영역에 마운트
}
}
// 2. 기존 JavaScript에서 사용
import Widget from './Widget.svelte';
new Widget({
target: document.getElementById('svelte-widget'),
props: { data: existingData },
});
Svelte 4 → 5 마이그레이션
Svelte 4에서 5로의 마이그레이션은 매우 안전하고 점진적으로 진행할 수 있습니다.
기존의 let 변수
, $: 반응형
, export let
등 모든 Svelte 4 코드가 Svelte 5에서도 그대로 동작하므로 호환성 걱정 없이 업그레이드 가능합니다.
새로운 $state
, $derived
, $props
, $effect
같은 Rune 시스템은 선택적으로 도입할 수 있어, 기존 프로젝트의 안정성을 유지하면서 점진적으로 현대적 기능을 활용할 수 있습니다.
기능 | Svelte 4 | Svelte 5 | 호환성 |
---|---|---|---|
상태 관리 | let 변수 | $state Rune | 기존 코드 동작 |
계산된 값 | $: 반응형 | $derived Rune | 기존 코드 동작 |
Props | export let | $props Rune | 기존 코드 동작 |
부수 효과 | $: , onMount | $effect Rune | 기존 코드 동작 |
팁: Svelte 4 코드는 Svelte 5에서도 그대로 동작합니다. 새 기능은 점진적으로 도입하세요.
정리
Svelte는 컴파일 타임 최적화로 뛰어난 성능과 작은 번들 크기를 제공하는 현대적인 프레임워크입니다.
핵심 요약
- 장점: 최고의 성능, 최소 번들 크기, 간결한 문법
- 단점: 작은 생태계, 제한된 채용 시장
- 최적 사용처: 성능 중심 프로젝트, 프로토타이핑, 임베디드 위젯
다음 단계: 2장 "개발 환경 설정"에서는 실제 Svelte 프로젝트를 생성하고 개발 도구를 설정합니다. 첫 번째 Svelte 앱을 만들 준비가 되셨나요?