Skip to main content

SvelteKit 5 Runes란 무엇인가?

SvelteKit 5 Runes 마이그레이션 가이드

SvelteKit 5는 2024년 말 정식 출시된 메이저 버전으로, 반응성 시스템을 근본적으로 재설계한 Runes를 도입했습니다. 기존 SvelteKit 4의 $: 문법과 스토어 기반 반응성에 익숙하다면 처음에는 낯설 수 있지만, 마이그레이션을 마친 뒤에는 훨씬 명확하고 예측 가능한 코드를 작성할 수 있게 됩니다. 이 글에서는 실제 프로젝트에서 SvelteKit 4를 5로 마이그레이션하면서 겪은 주요 변화와 실전 패턴을 정리합니다.

핵심 Runes 개요 — $state, $derived, $effect

SvelteKit 5 Runes는 크게 세 가지 핵심 rune으로 구성됩니다. $state는 반응형 상태를 선언하고, $derived는 다른 상태에서 파생된 값을 정의하며, $effect는 사이드 이펙트를 처리합니다. 기존의 암묵적 반응성 대신 명시적 선언 방식을 채택해 코드의 의도가 명확해졌습니다.

Before: SvelteKit 4 문법

<script>
  // SvelteKit 4 — 암묵적 반응성
  let count = 0;
  let doubled;

  $: doubled = count * 2;  // 반응형 선언

  $: {  // 반응형 블록
    console.log('count changed:', count);
    if (count > 10) {
      alert('카운트가 10을 넘었습니다!');
    }
  }

  function increment() {
    count += 1;
  }
</script>

<button on:click={increment}>{count} (doubled: {doubled})</button>

After: SvelteKit 5 Runes 문법

<script>
  // SvelteKit 5 — 명시적 Runes
  let count = $state(0);
  let doubled = $derived(count * 2);

  $effect(() => {
    console.log('count changed:', count);
    if (count > 10) {
      alert('카운트가 10을 넘었습니다!');
    }
  });

  function increment() {
    count += 1;
  }
</script>

<button onclick={increment}>{count} (doubled: {doubled})</button>

눈에 띄는 변화가 몇 가지 있습니다. $: 반응형 선언이 $derived()로, 반응형 블록이 $effect()로 바뀌었고, 이벤트 핸들러 문법도 on:click에서 onclick으로 변경되었습니다. 또한 let count = 0let count = $state(0)로 바뀌어 어떤 변수가 반응형인지 코드만 보고도 즉시 알 수 있게 되었습니다.

$props — 컴포넌트 Props 마이그레이션

SvelteKit 5에서는 컴포넌트 props 선언 방식도 크게 바뀌었습니다. 기존의 export let 패턴 대신 $props() rune을 사용합니다. 특히 TypeScript와의 통합이 더욱 자연스러워졌습니다.

<script lang="ts">
  // SvelteKit 4 방식
  // export let name: string;
  // export let age: number = 0;
  // export let onClose: () => void;

  // SvelteKit 5 Runes 방식
  interface Props {
    name: string;
    age?: number;
    onClose: () => void;
    children?: import('svelte').Snippet;
  }

  let { name, age = 0, onClose, children }: Props = $props();
</script>

<div>
  <h2>{name} ({age})</h2>
  {@render children?.()}
  <button onclick={onClose}>닫기</button>
</div>

한 가지 중요한 변화는 slot이 Snippet으로 대체된 것입니다. 기존의 <slot /><slot name="header" /> 패턴은 각각 {@render children?.()}와 named snippet으로 바뀝니다. 처음에는 다소 verbose하게 느껴질 수 있지만, TypeScript 자동완성이 정확하게 동작하는 장점이 있습니다.

스토어(Store) → $state 마이그레이션

SvelteKit 4에서 전역 상태 관리를 위해 자주 쓰던 Svelte 스토어(writable, readable, derived)는 SvelteKit 5에서도 여전히 사용 가능합니다. 하지만 $state를 활용한 클래스 기반 상태 관리 패턴이 더 간결하고 테스트하기 쉬운 경우가 많습니다.

// src/lib/stores/user.svelte.ts
// SvelteKit 5 — 클래스 기반 반응형 상태 관리

class UserStore {
  name = $state('');
  email = $state('');
  isLoggedIn = $derived(this.name !== '' && this.email !== '');

  login(name: string, email: string) {
    this.name = name;
    this.email = email;
  }

  logout() {
    this.name = '';
    this.email = '';
  }
}

// 싱글톤으로 export
export const userStore = new UserStore();

// 컴포넌트에서 사용
// import { userStore } from '$lib/stores/user.svelte';
// <p>{userStore.name}</p>  ← 자동 반응형!

파일 확장자를 .svelte.ts로 지정해야 Runes가 활성화됩니다. 일반 .ts 파일에서는 $state를 사용할 수 없으니 주의하세요.

마이그레이션 체크리스트 및 자동화 도구

SvelteKit 팀은 공식 마이그레이션 스크립트를 제공합니다. 대부분의 기계적 변환은 자동으로 처리되지만, 복잡한 반응형 로직은 수동 검토가 필요합니다.

# 공식 마이그레이션 CLI 실행
npx sv migrate svelte-5

# 주요 자동 변환 항목:
# - on:click → onclick
# - export let → $props()
# - $: expr → $derived()
# - $: { } → $effect()
# - <slot> → {@render children()}

# 수동 확인 필요 항목:
# - createEventDispatcher → $props() 콜백 방식으로 변경
# - 스토어 구독 ($store) → 대부분 자동 처리되나 복잡한 경우 수동 검토
# - beforeUpdate / afterUpdate → $effect.pre() / $effect()

# 마이그레이션 후 타입 체크
npx tsc --noEmit
npm run check

자주 겪는 문제와 해결법

1. $effect 무한 루프: $effect 내부에서 해당 effect가 의존하는 상태를 변경하면 무한 루프가 발생합니다. $effect.pre()를 사용하거나 untrack()으로 특정 의존성을 추적에서 제외하세요.

2. 배열/객체 깊은 반응성: $state로 선언된 배열이나 객체는 기본적으로 deep reactive입니다. 기존 SvelteKit 4에서 arr = [...arr]처럼 재할당해야 했던 패턴이 이제는 arr.push(item)으로 직접 변이해도 UI가 업데이트됩니다.

3. SSR 호환성: 서버사이드 렌더링 중에는 $effect가 실행되지 않습니다. 브라우저 전용 초기화 코드는 반드시 $effectonMount 안에 작성하세요.

코드벤터는 글로벌 협력 네트워크를 기반으로 다양한 프론트엔드 프로젝트에서 SvelteKit 5 Runes를 실전 적용해왔습니다. 마이그레이션 과정에서의 노하우와 패턴은 앞으로도 이 블로그를 통해 계속 공유할 예정입니다. 새로운 기술 스택 도입이나 프로젝트 개발에 관심 있으시다면 언제든지 코드벤터에 문의해 주세요.

코드픽 - 외주 전문 AI 바이브 코딩 글로벌 진출

댓글 남기기