본문 바로가기
web

Svelte 5 Runes 완벽 가이드 2026 — ·· 반응성 시스템으로 React 없이 빠른 웹앱 완전 정복

by bamsik 2026. 3. 15.
반응형

Svelte 5 Runes란 무엇인가?

2024년 10월 공식 출시된 Svelte 5는 기존의 암묵적 반응성 시스템을 버리고 Runes(룬)라는 완전히 새로운 반응성 모델을 도입했습니다. 2026년 현재, Svelte 프로젝트를 새로 시작하면 Svelte 5가 기본값이며, Runes는 이제 선택이 아닌 표준입니다.

Runes는 $로 시작하는 특수 함수들로, 컴파일러에게 반응성을 명시적으로 알려주는 역할을 합니다. React의 훅(Hooks)과 유사하지만 훨씬 더 직관적이고 성능이 뛰어납니다. 가장 큰 차이점은 Svelte가 런타임 없이 컴파일 단계에서 최적화된 바닐라 JavaScript를 생성한다는 점입니다.

핵심 Runes 5가지 완전 정복

1. $state — 반응형 상태 선언

기존 Svelte 4에서는 let count = 0만으로 반응성이 동작했지만, 이는 컴포넌트 내부에서만 작동하는 마법이었습니다. Svelte 5에서는 명시적으로 $state를 사용합니다.

<script>
  let count = $state(0);
  let user = $state({ name: '밤식', age: 30 });
</script>

<button onclick={() => count++}>
  클릭 수: {count}
</button>

핵심 변화: $state는 컴포넌트 경계를 넘어 어디서든 사용할 수 있습니다. .svelte.js 파일에서 전역 상태를 만들어 여러 컴포넌트에서 공유하는 것이 가능합니다.

2. $derived — 계산된 값

다른 상태에서 파생되는 값을 선언할 때 사용합니다. 기존의 $: 반응형 선언을 대체합니다.

<script>
  let items = $state([1, 2, 3, 4, 5]);
  let total = $derived(items.reduce((a, b) => a + b, 0));
  let doubled = $derived(total * 2);
</script>

<p>합계: {total}, 두 배: {doubled}</p>

복잡한 계산이 필요하다면 $derived.by()를 사용해 함수 형태로 작성할 수 있습니다.

3. $effect — 사이드 이펙트 처리

상태가 변경될 때 실행할 코드를 정의합니다. React의 useEffect와 유사하지만 의존성 배열이 필요 없습니다. Svelte 컴파일러가 자동으로 의존성을 추적합니다.

<script>
  let title = $state('홈');
  
  $effect(() => {
    document.title = `${title} | 내 블로그`;
    // 클린업 함수 반환 가능
    return () => {
      document.title = '내 블로그';
    };
  });
</script>

4. $props — 컴포넌트 속성

부모에서 전달받는 props를 명시적으로 선언합니다. TypeScript와의 통합이 훨씬 자연스러워졌습니다.

<script>
  let { name, age = 25, ...rest } = $props();
</script>

<div>
  <p>이름: {name}, 나이: {age}</p>
</div>

5. $bindable — 양방향 바인딩

자식 컴포넌트에서 부모로 값을 역방향 전달하고 싶을 때 사용합니다.

<!-- Child.svelte -->
<script>
  let { value = $bindable() } = $props();
</script>
<input bind:value />

Svelte 5가 React·Vue보다 빠른 이유

Svelte의 근본적인 차이점은 "컴파일러 우선(Compiler-First)" 접근 방식입니다.

  • 가상 DOM 없음: React·Vue는 런타임에 가상 DOM을 비교(diffing)하지만, Svelte는 컴파일 시점에 정확히 어떤 DOM을 업데이트할지 결정합니다.
  • 번들 크기: Svelte 앱은 프레임워크 런타임이 없어 번들 크기가 최소 30~50% 작습니다.
  • 메모리 효율: 가상 DOM 트리를 메모리에 유지할 필요가 없어 메모리 사용량이 낮습니다.
  • 세밀한 반응성: 전체 컴포넌트를 재렌더링하는 대신, 변경된 DOM 노드만 정확히 업데이트합니다.

전역 상태 관리 — Svelte Stores 대신 $state 활용

Svelte 5에서는 복잡한 Stores 패턴 없이 $state만으로 전역 상태를 관리할 수 있습니다.

// store.svelte.js
export let cartItems = $state([]);
export let totalPrice = $derived(
  cartItems.reduce((sum, item) => sum + item.price, 0)
);

export function addItem(item) {
  cartItems.push(item);
}

// 어디서든 import해서 사용
// import { cartItems, addItem } from './store.svelte.js'

기존 Svelte 4의 writable(), readable() 스토어 패턴보다 훨씬 직관적이며, TypeScript 타입 추론도 자연스럽게 동작합니다.

SvelteKit 2와의 시너지

Svelte 5는 SvelteKit 2와 함께 사용할 때 진가를 발휘합니다. 주요 특징은 다음과 같습니다.

  • 서버 사이드 렌더링(SSR): +page.server.ts에서 데이터를 불러와 SEO 최적화된 HTML 생성
  • 파일 기반 라우팅: src/routes 폴더 구조가 URL 경로와 일치
  • 엣지 배포: Cloudflare Pages, Vercel Edge, Netlify에 별도 설정 없이 배포 가능
  • Form Actions: Progressive Enhancement로 JavaScript 없이도 폼 처리 가능

Svelte 5 마이그레이션 가이드

기존 Svelte 4 프로젝트를 Svelte 5로 마이그레이션할 때 알아야 할 핵심 변경사항입니다.

  • let x = 0let x = $state(0)
  • $: doubled = x * 2let doubled = $derived(x * 2)
  • $: { 사이드이펙트 }$effect(() => { 사이드이펙트 })
  • export let proplet { prop } = $props()
  • 이벤트 디렉티브 on:click={handler}onclick={handler}

공식 마이그레이션 도구를 사용하면 대부분의 변경사항을 자동으로 처리할 수 있습니다: npx sv migrate svelte-5

2026년 Svelte 생태계 현황

Svelte는 지속적으로 개발자 만족도 설문에서 높은 점수를 받고 있습니다. Stack Overflow 2025 설문에서 가장 사랑받는 프레임워크 2위를 차지했으며, 특히 성능을 중시하는 프로젝트, 인터랙티브 데이터 시각화, 임베디드 위젯 개발에서 강세를 보이고 있습니다.

Rich Harris(Svelte 창시자)가 Vercel에 합류하면서 SvelteKit의 서버 기능과 엣지 배포 지원이 크게 강화되었고, 2026년에는 Svelte 6의 초기 RFC도 논의되고 있습니다.

시작하기 — 5분 만에 SvelteKit 프로젝트 생성

# SvelteKit 프로젝트 생성
npx sv create my-app

# 개발 서버 실행
cd my-app
npm install
npm run dev

# 빌드
npm run build

📎 참고 자료

반응형