Skip to content

Instantly share code, notes, and snippets.

@YangSiJun528
Created June 9, 2025 02:17
Show Gist options
  • Select an option

  • Save YangSiJun528/7c83fc134f45fd998ec20bd70c2d9180 to your computer and use it in GitHub Desktop.

Select an option

Save YangSiJun528/7c83fc134f45fd998ec20bd70c2d9180 to your computer and use it in GitHub Desktop.
Svelte Store

Svelte Store 종합 가이드

개요

Svelte의 Store는 컴포넌트 간 상태 공유와 반응형 데이터 관리를 위한 핵심 기능입니다. 이 가이드에서는 Svelte Store의 다양한 기능, SvelteKit이 제공하는 기본 store, 그리고 Svelte 5의 runes와의 관계에 대해 상세히 알아보겠습니다.

1. Svelte Store 기본 기능

1.1 writable - 읽기/쓰기 가능한 기본 스토어

writable은 가장 기본적인 store 타입으로, 외부에서 값을 설정할 수 있는 store입니다.

주요 특징:

  • set() 메서드: 새로운 값으로 직접 설정
  • update() 메서드: 콜백 함수를 통해 기존 값을 기반으로 업데이트
  • subscribe() 메서드: 값 변경 시 콜백 실행

기본 사용법:

import { writable } from 'svelte/store';

const count = writable(0);

// 구독
count.subscribe((value) => {
    console.log(value); // 0
});

// 값 설정
count.set(1); // 1

// 값 업데이트
count.update((n) => n + 1); // 2

컴포넌트에서 사용:

<script>
    import { writable } from 'svelte/store';
    
    const count = writable(0);
    console.log($count); // $ 접두사로 자동 구독
    
    $count = 2; // 직접 할당도 가능
</script>

<button on:click={() => $count++}>
    {$count}
</button>

구독자 수에 따른 시작/정지 함수:

const count = writable(0, () => {
    console.log('첫 번째 구독자 등록');
    return () => console.log('마지막 구독자 해제');
});

1.2 readable - 읽기 전용, 외부 이벤트 연동

readable은 외부에서 값을 설정할 수 없는 읽기 전용 store입니다. 주로 외부 데이터 소스나 이벤트와 연동할 때 사용합니다.

주요 특징:

  • 외부에서 set() 불가능
  • 내부 로직으로만 값 변경
  • 타이머, API 호출, 이벤트 리스너 등과 연동

시간 예제:

import { readable } from 'svelte/store';

const time = readable(new Date(), (set) => {
    set(new Date());
    
    const interval = setInterval(() => {
        set(new Date());
    }, 1000);
    
    return () => clearInterval(interval);
});

토글 예제:

const ticktock = readable('tick', (set, update) => {
    const interval = setInterval(() => {
        update(sound => sound === 'tick' ? 'tock' : 'tick');
    }, 1000);
    
    return () => clearInterval(interval);
});

1.3 derived - 다른 스토어로부터 파생된 계산된 값

derived는 하나 이상의 다른 store로부터 계산된 값을 제공하는 store입니다.

주요 특징:

  • 의존하는 store가 변경될 때 자동으로 재계산
  • 동기 및 비동기 계산 지원
  • 여러 store를 조합 가능

단일 store 파생:

import { derived } from 'svelte/store';

const doubled = derived(a, ($a) => $a * 2);

비동기 파생:

const delayed = derived(
    a,
    ($a, set) => {
        setTimeout(() => set($a), 1000);
    },
    2000 // 초기값
);

여러 store 조합:

const summed = derived([a, b], ([$a, $b]) => $a + $b);

const delayed = derived([a, b], ([$a, $b], set) => {
    setTimeout(() => set($a + $b), 1000);
});

1.4 get - 스토어 값을 함수 내부에서 동기적으로 획득

get 함수는 구독 없이 store의 현재 값을 동기적으로 가져올 때 사용합니다.

주요 특징:

  • 일회성 값 조회
  • 구독/구독 해제 자동 처리
  • 핫 코드 경로에서는 권장하지 않음

사용법:

import { get } from 'svelte/store';

const value = get(store);

주의사항:

  • 내부적으로 구독 → 값 읽기 → 구독 해제 과정을 거침
  • 반복적인 호출은 성능에 영향을 줄 수 있음

1.5 커스텀 스토어 - 메서드를 확장해 도메인 로직을 내부화

커스텀 store는 기본 store에 추가 메서드를 제공하여 도메인별 로직을 캡슐화합니다.

기본 패턴:

function createCount() {
    const { subscribe, set, update } = writable(0);
    
    return {
        subscribe,
        increment: () => update(n => n + 1),
        decrement: () => update(n => n - 1),
        reset: () => set(0)
    };
}

const count = createCount();

고급 예제:

function createTodos() {
    const { subscribe, set, update } = writable([]);
    
    return {
        subscribe,
        add: (text) => update(todos => [...todos, { 
            id: Date.now(), 
            text, 
            done: false 
        }]),
        remove: (id) => update(todos => todos.filter(t => t.id !== id)),
        toggle: (id) => update(todos => todos.map(t => 
            t.id === id ? { ...t, done: !t.done } : t
        )),
        clear: () => set([])
    };
}

1.6 readonly - 쓰기 방지 래퍼

readonly 함수는 writable store를 읽기 전용으로 만들어 외부에서의 수정을 방지합니다.

import { readonly, writable } from 'svelte/store';

const writableStore = writable(1);
const readableStore = readonly(writableStore);

readableStore.subscribe(console.log);

writableStore.set(2); // 정상 동작
// readableStore.set(2); // 에러 - set 메서드 없음

1.7 Context API와의 연동

Context API를 통해 컴포넌트 트리 깊숙이 store를 전달할 수 있습니다.

// 부모 컴포넌트
import { setContext } from 'svelte';
import { writable } from 'svelte/store';

const userStore = writable({ name: 'John' });
setContext('user', userStore);
// 자식 컴포넌트
import { getContext } from 'svelte';

const userStore = getContext('user');

2. SvelteKit 기본 제공 Store

SvelteKit은 애플리케이션의 상태와 네비게이션 정보를 제공하는 여러 내장 store를 제공합니다. Svelte 5와 SvelteKit 2.12부터는 $app/state 모듈을 권장하며, 이전 버전에서는 $app/stores를 사용합니다.

2.1 $app/stores (레거시, Svelte 4 및 SvelteKit 2.12 이전)

page

현재 페이지의 정보를 담고 있는 readable store입니다.

타입:

const page: Readable<{
    url: URL;
    params: Record<string, string>;
    route: { id: string | null };
    status: number;
    error: Error | null;
    data: Record<string, any>;
    form: any;
}>;

사용법:

<script>
    import { page } from '$app/stores';
</script>

<p>현재 URL: {$page.url.pathname}</p>
<p>라우트 파라미터: {JSON.stringify($page.params)}</p>

navigating

현재 진행 중인 네비게이션 정보를 제공하는 readable store입니다.

타입:

const navigating: Readable<Navigation | null>;

interface Navigation {
    from: URL | null;
    to: URL | null;
    type: 'enter' | 'form' | 'leave' | 'link' | 'goto' | 'popstate';
    delta?: number; // popstate인 경우에만
}

사용법:

<script>
    import { navigating } from '$app/stores';
</script>

{#if $navigating}
    <p>네비게이션 중: {$navigating.from?.pathname} → {$navigating.to?.pathname}</p>
{/if}

updated

앱의 새 버전이 배포되었는지 확인하는 readable store입니다.

타입:

const updated: Readable<boolean> & {
    check(): Promise<boolean>;
};

사용법:

<script>
    import { updated } from '$app/stores';
</script>

{#if $updated}
    <div class="toast">
        새 버전이 있습니다. 
        <button on:click={() => location.reload()}>새로고침</button>
    </div>
{/if}

getStores

서버 사이드에서 store들에 접근할 때 사용하는 함수입니다.

import { getStores } from '$app/stores';

const { page, navigating, updated } = getStores();

2.2 $app/state (Svelte 5, SvelteKit 2.12+)

Svelte 5의 runes 시스템과 호환되는 새로운 상태 객체들입니다.

page

현재 페이지 정보를 담은 반응형 객체입니다.

특징:

  • runes와 완전 호환
  • 레거시 반응성 구문에서는 변경사항이 반영되지 않음
  • 서버에서는 렌더링 중에만 읽기 가능

사용법:

<script>
    import { page } from '$app/state';
</script>

<p>현재 URL: {page.url.pathname}</p>
<p>라우트 파라미터: {JSON.stringify(page.params)}</p>

navigating

진행 중인 네비게이션을 나타내는 읽기 전용 객체입니다.

타입:

const navigating: Navigation | {
    from: null;
    to: null;
    type: null;
    willUnload: null;
    delta: null;
    complete: null;
};

사용법:

<script>
    import { navigating } from '$app/state';
</script>

{#if navigating.from}
    <p>네비게이션 중...</p>
{/if}

updated

앱 업데이트 상태를 나타내는 반응형 값입니다.

타입:

const updated: {
    get current(): boolean;
    check(): Promise<boolean>;
};

사용법:

<script>
    import { updated } from '$app/state';
</script>

{#if updated.current}
    <div class="update-notification">
        새 버전이 있습니다!
        <button on:click={() => location.reload()}>새로고침</button>
    </div>
{/if}

<button on:click={() => updated.check()}>
    업데이트 확인
</button>

2.3 주요 사용 사례

현재 경로 기반 네비게이션 스타일링

<script>
    import { page } from '$app/state'; // 또는 '$app/stores'
</script>

<nav>
    <a href="/" class:active={page.url.pathname === '/'}>홈</a>
    <a href="/about" class:active={page.url.pathname === '/about'}>소개</a>
    <a href="/contact" class:active={page.url.pathname === '/contact'}>연락처</a>
</nav>

<style>
    .active {
        font-weight: bold;
        color: blue;
    }
</style>

로딩 인디케이터

<script>
    import { navigating } from '$app/state';
</script>

{#if navigating.from}
    <div class="loading-bar">
        <div class="progress"></div>
    </div>
{/if}

<style>
    .loading-bar {
        position: fixed;
        top: 0;
        left: 0;
        width: 100%;
        height: 3px;
        background: #f0f0f0;
        z-index: 9999;
    }
    
    .progress {
        height: 100%;
        background: #007acc;
        animation: loading 2s ease-in-out infinite;
    }
    
    @keyframes loading {
        0% { width: 0%; }
        50% { width: 70%; }
        100% { width: 100%; }
    }
</style>

폼 데이터 접근

<script>
    import { page } from '$app/state';
    
    // 폼 액션 후 결과 데이터 접근
    $: if (page.form?.success) {
        console.log('폼 제출 성공!');
    }
</script>

{#if page.form?.errors}
    <div class="errors">
        {#each Object.entries(page.form.errors) as [field, error]}
            <p>{field}: {error}</p>
        {/each}
    </div>
{/if}

3. 반응형 상태 관리와의 관계

3.1 Svelte 5 Runes와 Store의 관계

Svelte 5에서는 새로운 runes 시스템이 도입되어 반응형 상태 관리 방식이 크게 변화했습니다. 하지만 store는 여전히 유효하며, 특정 상황에서는 더 적합할 수 있습니다.

3.1.1 Runes 개요

주요 Runes:

  • $state(): 반응형 상태 선언
  • $derived(): 파생된 값 계산
  • $effect(): 부수 효과 처리
  • $props(): 컴포넌트 속성 선언

3.1.2 언제 Store를 사용하고 언제 Runes를 사용할까?

Runes 사용 권장 상황:

  • 컴포넌트 내부 상태 관리
  • 간단한 전역 상태 관리
  • TypeScript와의 호환성이 중요한 경우
  • 성능이 중요한 경우

Store 사용 권장 상황:

  • 복잡한 비동기 데이터 스트림
  • 기존 RxJS 지식 활용
  • 세밀한 구독 제어가 필요한 경우
  • 라이브러리 호환성이 중요한 경우

3.2 Store에서 Runes로 마이그레이션

3.2.1 기본 상태 관리

Svelte 4 (Store):

// store.js
import { writable } from 'svelte/store';

export const count = writable(0);
<!-- Component.svelte -->
<script>
    import { count } from './store.js';
</script>

<button on:click={() => $count++}>
    {$count}
</button>

Svelte 5 (Runes):

// state.svelte.js
let count = $state(0);

export function getCount() {
    return count;
}

export function setCount(newCount) {
    count = newCount;
}

export function incrementCount() {
    count++;
}
<!-- Component.svelte -->
<script>
    import { getCount, incrementCount } from './state.svelte.js';
</script>

<button on:click={incrementCount}>
    {getCount()}
</button>

3.2.2 더 나은 API 패턴

Getter/Setter 객체 패턴:

// counter.svelte.js
let count = $state(0);

export const counter = {
    get value() {
        return count;
    },
    set value(newCount) {
        count = newCount;
    },
    increment() {
        count++;
    },
    decrement() {
        count--;
    },
    reset() {
        count = 0;
    }
};

사용법:

<script>
    import { counter } from './counter.svelte.js';
</script>

<div>
    <button on:click={counter.decrement}>-</button>
    <span>{counter.value}</span>
    <button on:click={counter.increment}>+</button>
    <button on:click={counter.reset}>Reset</button>
</div>

3.2.3 클래스 기반 패턴

// TodoStore.svelte.js
class TodoStore {
    #todos = $state([]);
    
    get todos() {
        return this.#todos;
    }
    
    get completed() {
        return this.#todos.filter(todo => todo.completed);
    }
    
    get pending() {
        return this.#todos.filter(todo => !todo.completed);
    }
    
    add(text) {
        this.#todos.push({
            id: Date.now(),
            text,
            completed: false
        });
    }
    
    toggle(id) {
        const todo = this.#todos.find(t => t.id === id);
        if (todo) {
            todo.completed = !todo.completed;
        }
    }
    
    remove(id) {
        this.#todos = this.#todos.filter(t => t.id !== id);
    }
}

export const todoStore = new TodoStore();

3.3 $props()와 $state()의 관계

3.3.1 기본 사용법

Svelte 4:

<script>
    export let initialValue = 0;
    let count = initialValue;
</script>

Svelte 5:

<script>
    let { initialValue = 0 } = $props();
    let count = $state(initialValue);
</script>

3.3.2 Props 변경에 반응하기

<script>
    let { initialValue = 0 } = $props();
    let count = $state(initialValue);
    
    // initialValue가 변경될 때 count도 업데이트
    $effect(() => {
        count = initialValue;
    });
</script>

3.3.3 양방향 바인딩 패턴

<script>
    let { value = $bindable(), onchange } = $props();
    
    function handleInput(event) {
        value = event.target.value;
        onchange?.(value);
    }
</script>

<input {value} on:input={handleInput} />

3.4 Universal Reactivity (범용 반응성)

Svelte 5의 가장 큰 장점 중 하나는 runes가 컴포넌트 외부에서도 작동한다는 것입니다.

3.4.1 .svelte.js 파일에서의 반응성

// utils.svelte.js
let theme = $state('light');
let user = $state(null);

export const appState = {
    get theme() { return theme; },
    set theme(value) { theme = value; },
    
    get user() { return user; },
    set user(value) { user = value; },
    
    get isLoggedIn() {
        return user !== null;
    },
    
    toggleTheme() {
        theme = theme === 'light' ? 'dark' : 'light';
    }
};

// 부수 효과도 가능
$effect(() => {
    document.body.className = theme;
});

3.4.2 모듈 간 반응성 공유

// auth.svelte.js
let currentUser = $state(null);

export const auth = {
    get user() { return currentUser; },
    
    async login(credentials) {
        const user = await api.login(credentials);
        currentUser = user;
        return user;
    },
    
    logout() {
        currentUser = null;
        api.logout();
    }
};
// navigation.svelte.js
import { auth } from './auth.svelte.js';

let currentRoute = $state('/');

export const navigation = {
    get route() { return currentRoute; },
    
    navigate(path) {
        // 인증이 필요한 경로 체크
        if (path.startsWith('/admin') && !auth.user) {
            currentRoute = '/login';
        } else {
            currentRoute = path;
        }
    }
};

// auth 상태 변화에 반응
$effect(() => {
    if (!auth.user && currentRoute.startsWith('/admin')) {
        currentRoute = '/login';
    }
});

3.5 Store와 Runes의 상호 운용성

Store와 runes는 함께 사용할 수 있습니다.

3.5.1 Store를 Runes로 감싸기

import { writable } from 'svelte/store';

const store = writable(0);
let value = $state(0);

// Store 변화를 runes로 동기화
store.subscribe(v => value = v);

export { value, store };

3.5.2 Runes를 Store로 변환

function runeToStore(getValue) {
    let subscribers = [];
    let currentValue = getValue();
    
    $effect(() => {
        const newValue = getValue();
        if (newValue !== currentValue) {
            currentValue = newValue;
            subscribers.forEach(fn => fn(newValue));
        }
    });
    
    return {
        subscribe(fn) {
            subscribers.push(fn);
            fn(currentValue);
            
            return () => {
                subscribers = subscribers.filter(s => s !== fn);
            };
        }
    };
}

// 사용 예
let count = $state(0);
const countStore = runeToStore(() => count);

3.6 성능 고려사항

3.6.1 Runes의 장점

  • 더 세밀한 반응성 제어
  • 불필요한 재계산 방지
  • 더 나은 TypeScript 지원
  • 런타임 오버헤드 감소

3.6.2 Store의 장점

  • 성숙한 생태계
  • 복잡한 비동기 패턴 지원
  • 기존 코드와의 호환성
  • 명시적인 구독 관리

3.7 마이그레이션 전략

  1. 점진적 마이그레이션: 새로운 기능은 runes로, 기존 코드는 store 유지
  2. 핵심 상태부터: 가장 자주 사용되는 상태부터 runes로 변환
  3. 테스트 우선: 마이그레이션 전 충분한 테스트 코드 작성
  4. 성능 측정: 마이그레이션 전후 성능 비교
  5. 팀 교육: 새로운 패턴에 대한 팀 내 교육 진행

4. 실전 예제와 패턴

4.1 복합 상태 관리 예제

4.1.1 쇼핑카트 (Store 버전)

// cart.js
import { writable, derived } from 'svelte/store';

function createCart() {
    const { subscribe, set, update } = writable([]);
    
    return {
        subscribe,
        addItem: (product) => update(items => {
            const existing = items.find(item => item.id === product.id);
            if (existing) {
                return items.map(item => 
                    item.id === product.id 
                        ? { ...item, quantity: item.quantity + 1 }
                        : item
                );
            }
            return [...items, { ...product, quantity: 1 }];
        }),
        removeItem: (id) => update(items => items.filter(item => item.id !== id)),
        updateQuantity: (id, quantity) => update(items => 
            items.map(item => 
                item.id === id ? { ...item, quantity } : item
            )
        ),
        clear: () => set([])
    };
}

export const cart = createCart();

export const cartTotal = derived(cart, $cart => 
    $cart.reduce((total, item) => total + (item.price * item.quantity), 0)
);

export const cartItemCount = derived(cart, $cart => 
    $cart.reduce((count, item) => count + item.quantity, 0)
);

4.1.2 쇼핑카트 (Runes 버전)

// cart.svelte.js
let items = $state([]);

export const cart = {
    get items() { return items; },
    
    get total() {
        return items.reduce((total, item) => total + (item.price * item.quantity), 0);
    },
    
    get itemCount() {
        return items.reduce((count, item) => count + item.quantity, 0);
    },
    
    addItem(product) {
        const existing = items.find(item => item.id === product.id);
        if (existing) {
            existing.quantity++;
        } else {
            items.push({ ...product, quantity: 1 });
        }
    },
    
    removeItem(id) {
        items = items.filter(item => item.id !== id);
    },
    
    updateQuantity(id, quantity) {
        const item = items.find(item => item.id === id);
        if (item) {
            item.quantity = quantity;
        }
    },
    
    clear() {
        items = [];
    }
};

4.2 비동기 데이터 관리

4.2.1 API 데이터 페칭 (Store)

// api-store.js
import { writable, derived } from 'svelte/store';

function createApiStore(url) {
    const loading = writable(false);
    const error = writable(null);
    const data = writable(null);
    
    const fetch = async () => {
        loading.set(true);
        error.set(null);
        
        try {
            const response = await fetch(url);
            if (!response.ok) throw new Error('Failed to fetch');
            const result = await response.json();
            data.set(result);
        } catch (err) {
            error.set(err.message);
        } finally {
            loading.set(false);
        }
    };
    
    return {
        loading: { subscribe: loading.subscribe },
        error: { subscribe: error.subscribe },
        data: { subscribe: data.subscribe },
        fetch,
        refresh: fetch
    };
}

export const userStore = createApiStore('/api/user');

4.2.2 API 데이터 페칭 (Runes)

// api-state.svelte.js
class ApiState {
    #loading = $state(false);
    #error = $state(null);
    #data = $state(null);
    
    constructor(url) {
        this.url = url;
    }
    
    get loading() { return this.#loading; }
    get error() { return this.#error; }
    get data() { return this.#data; }
    
    async fetch() {
        this.#loading = true;
        this.#error = null;
        
        try {
            const response = await fetch(this.url);
            if (!response.ok) throw new Error('Failed to fetch');
            this.#data = await response.json();
        } catch (err) {
            this.#error = err.message;
        } finally {
            this.#loading = false;
        }
    }
    
    refresh() {
        return this.fetch();
    }
}

export const userApi = new ApiState('/api/user');

4.3 폼 상태 관리

// form-state.svelte.js
function createFormState(initialValues = {}) {
    let values = $state({ ...initialValues });
    let errors = $state({});
    let touched = $state({});
    let isSubmitting = $state(false);
    
    return {
        get values() { return values; },
        get errors() { return errors; },
        get touched() { return touched; },
        get isSubmitting() { return isSubmitting; },
        
        get isValid() {
            return Object.keys(errors).length === 0;
        },
        
        setValue(field, value) {
            values[field] = value;
            touched[field] = true;
            this.validate(field);
        },
        
        setError(field, error) {
            errors[field] = error;
        },
        
        clearError(field) {
            delete errors[field];
        },
        
        validate(field) {
            // 검증 로직 구현
            if (!values[field]) {
                this.setError(field, 'Required field');
            } else {
                this.clearError(field);
            }
        },
        
        async submit(onSubmit) {
            isSubmitting = true;
            
            try {
                await onSubmit(values);
            } catch (error) {
                console.error('Submit error:', error);
            } finally {
                isSubmitting = false;
            }
        },
        
        reset() {
            values = { ...initialValues };
            errors = {};
            touched = {};
            isSubmitting = false;
        }
    };
}

export { createFormState };

5. 모범 사례와 주의사항

5.1 Store 사용 시 주의사항

5.1.1 메모리 누수 방지

// 잘못된 예
let unsubscribe;
onMount(() => {
    unsubscribe = store.subscribe(value => {
        // 처리 로직
    });
});
// onDestroy에서 unsubscribe 호출 누락

// 올바른 예
onMount(() => {
    const unsubscribe = store.subscribe(value => {
        // 처리 로직
    });
    
    return unsubscribe; // onDestroy에서 자동 호출
});

5.1.2 서버 사이드 렌더링 고려

// 브라우저에서만 실행되는 store
import { browser } from '$app/environment';
import { writable } from 'svelte/store';

export const clientOnlyStore = writable(
    browser ? localStorage.getItem('key') : null
);

if (browser) {
    clientOnlyStore.subscribe(value => {
        localStorage.setItem('key', value);
    });
}

5.2 Runes 사용 시 주의사항

5.2.1 클로저 문제 해결

// 문제가 있는 코드
let count = $state(0);
export { count }; // 값이 고정됨

// 올바른 코드
let count = $state(0);
export function getCount() { return count; }
export function setCount(value) { count = value; }

5.2.2 Effect 사용 시 주의사항

// 무한 루프 위험
let count = $state(0);
$effect(() => {
    count++; // 이렇게 하면 안됨!
});

// 올바른 사용
let count = $state(0);
$effect(() => {
    console.log('Count changed:', count);
    // 읽기만 하고 수정하지 않음
});

5.3 성능 최적화

5.3.1 불필요한 재계산 방지

// Store 버전
const expensiveComputation = derived(
    [store1, store2],
    ([$store1, $store2], set) => {
        // 비용이 큰 계산을 debounce
        const timeoutId = setTimeout(() => {
            set(heavyCalculation($store1, $store2));
        }, 300);
        
        return () => clearTimeout(timeoutId);
    }
);

// Runes 버전
let input1 = $state('');
let input2 = $state('');
let debouncedResult = $state('');

let timeoutId;
$effect(() => {
    clearTimeout(timeoutId);
    timeoutId = setTimeout(() => {
        debouncedResult = heavyCalculation(input1, input2);
    }, 300);
});

6. 결론

6.1 Store vs Runes 선택 가이드

상황 권장 방식 이유
새 프로젝트 (Svelte 5) Runes 더 나은 성능과 TypeScript 지원
기존 프로젝트 마이그레이션 점진적 전환 안정성과 호환성
복잡한 비동기 로직 Store 성숙한 패턴과 도구
간단한 상태 관리 Runes 더 직관적이고 간단함
라이브러리 개발 Store 더 넓은 호환성
성능이 중요한 앱 Runes 더 효율적인 반응성

6.2 핵심 요약

  1. Store는 여전히 유효: Svelte 5에서도 store는 완전히 지원되며, 특정 상황에서는 더 적합할 수 있습니다.

  2. Runes의 장점: 더 명시적이고 성능이 좋으며, TypeScript와 잘 호환됩니다.

  3. 점진적 마이그레이션: 기존 프로젝트는 점진적으로 runes로 전환할 수 있습니다.

  4. 상황에 맞는 선택: 프로젝트의 요구사항에 따라 적절한 방식을 선택하는 것이 중요합니다.

  5. Universal Reactivity: Runes는 컴포넌트 외부에서도 작동하여 더 유연한 상태 관리를 가능하게 합니다.

6.3 추가 학습 자료

이 가이드를 통해 Svelte Store의 다양한 기능과 Svelte 5 runes와의 관계를 이해하고, 프로젝트에 적합한 상태 관리 방식을 선택할 수 있기를 바랍니다.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment