---
id: frontend-vue3-svelte5-patterns
title: Vue 3 / Svelte 5 — modern composition / runes
category: Coding
status: draft
source_trust_level: B
verification_status: conceptual
created_at: 2026-05-09
updated_at: 2026-05-09
tags: [frontend, vue, svelte, vibe-coding]
tech_stack: { language: "TS", applicable_to: ["Frontend"] }
applied_in: []
aliases: [Vue 3, Composition API, Pinia, Svelte 5, runes, $state, Nuxt, SvelteKit]
---

# Vue 3 / Svelte 5

> React 의 alternative. **Vue 3 (composition API), Svelte 5 (runes — signal식)**. Modern reactivity.

## 📖 핵심 개념
- Vue: composition API (React hooks 비슷).
- Svelte 5: runes (signal-based).
- 둘 다 modern reactivity.
- SSR 친화 (Nuxt, SvelteKit).

## 💻 코드 패턴

### Vue 3 SFC (Single File Component)
```vue
<script setup lang='ts'>
import { ref, computed } from 'vue';

const count = ref(0);
const double = computed(() => count.value * 2);

function increment() {
  count.value++;
}
</script>

<template>
  <button @click='increment'>{{ count }} ({{ double }})</button>
</template>

<style scoped>
button { padding: 8px; }
</style>
```

→ Template + script + style.

### Vue Composition API
```ts
import { ref, reactive, computed, watch, onMounted } from 'vue';

const count = ref(0);            // primitive
const user = reactive({ name: '' });  // object
const double = computed(() => count.value * 2);

watch(count, (newVal, oldVal) => {
  console.log('count:', newVal);
});

onMounted(() => {
  console.log('mounted');
});
```

→ React hooks 비슷.

### Vue composable (custom hook)
```ts
// composables/useCounter.ts
export function useCounter(initial = 0) {
  const count = ref(initial);
  const inc = () => count.value++;
  return { count, inc };
}

// 사용
const { count, inc } = useCounter();
```

### Pinia (Vue 의 Zustand)
```ts
import { defineStore } from 'pinia';

export const useUserStore = defineStore('user', {
  state: () => ({ name: '', age: 0 }),
  actions: {
    setName(name: string) { this.name = name; },
  },
  getters: {
    isAdult: (state) => state.age >= 18,
  },
});

// 사용
const store = useUserStore();
store.setName('Alice');
console.log(store.isAdult);
```

### Nuxt (Vue 의 Next)
```vue
<!-- pages/users/[id].vue -->
<script setup>
const route = useRoute();
const { data } = await useFetch(`/api/users/${route.params.id}`);
</script>

<template>
  <h1>{{ data.name }}</h1>
</template>
```

→ File-based route + SSR/SSG/edge.

### Svelte 5 (runes)
```svelte
<script>
  let count = $state(0);
  let double = $derived(count * 2);
  
  $effect(() => {
    console.log('count:', count);
  });
  
  function increment() {
    count++;
  }
</script>

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

<style>
  button { padding: 8px; }
</style>
```

→ `$state` / `$derived` / `$effect` = runes.

### Svelte 5 의 변화
```
Svelte 4: implicit reactivity (let, $:).
Svelte 5: explicit ($state, $derived).

→ 더 명시적. Compile-time.
```

### SvelteKit (Svelte 의 Next)
```svelte
<!-- routes/users/[id]/+page.svelte -->
<script>
  let { data } = $props();
</script>

<h1>{data.name}</h1>
```

```ts
// routes/users/[id]/+page.server.ts
export async function load({ params }) {
  const user = await fetchUser(params.id);
  return { name: user.name };
}
```

### Vue vs React vs Svelte
```
Vue:
- Template (HTML-friendly).
- Composition API (modern).
- 큰 ecosystem.
- Pinia / Vue Router.

Svelte:
- Compile-time (no runtime VDOM).
- 작은 bundle.
- Beautiful syntax.
- Smaller ecosystem.

React:
- 가장 큰 ecosystem.
- Compiler (modern).
- JSX (TS-friendly).
```

→ 다 좋음. Team 의 선호.

### Vue 의 reactivity caveat
```ts
const obj = reactive({ count: 0 });

// ❌ Lost reactivity
const { count } = obj;
count++;  // 안 trigger.

// ✅ Use ref
const count = ref(0);
// 또는
import { toRefs } from 'vue';
const { count } = toRefs(obj);
```

→ Destructure 가 lose reactivity.

### Svelte 5 의 reactive store
```svelte
<script>
  // global state file (state.svelte.ts)
  export const userStore = $state({ name: '' });
  
  // 사용
  $effect(() => {
    console.log(userStore.name);
  });
</script>
```

→ Global signal 식.

### Vue v-model (two-way)
```vue
<input v-model='message' />
<!-- 동등 -->
<input :value='message' @input='message = $event.target.value' />
```

→ Two-way binding 가 native.

### Vue Teleport (portal)
```vue
<Teleport to='body'>
  <div class='modal'>...</div>
</Teleport>
```

→ React Portal 비슷.

### Suspense
```vue
<Suspense>
  <template #default>
    <AsyncComponent />
  </template>
  <template #fallback>
    <Loading />
  </template>
</Suspense>
```

### Lifecycle (Vue)
```ts
import { onMounted, onUnmounted, onUpdated } from 'vue';

onMounted(() => { ... });
onUnmounted(() => { ... });
onUpdated(() => { ... });
```

### Lifecycle (Svelte 5)
```svelte
<script>
  import { onMount, onDestroy } from 'svelte';
  
  onMount(() => {
    return () => { /* cleanup */ };
  });
</script>
```

### Production
```
Vue:
- Alibaba, Tencent (China).
- Nuxt site / blog.
- Enterprise admin.

Svelte:
- The New York Times.
- Apple Music (옛).
- Brave browser.
```

### Migration from React
```
Vue:
- API 가 비슷 (composition).
- Template 다름.
- Pinia ≈ Zustand.
- Nuxt ≈ Next.

Svelte:
- 더 다름.
- 작은 bundle.
- 새 mental model.

→ Vue 가 React → migration 가 부드러움.
```

### Performance
```
Svelte: 가장 빠름 (compile-time).
Vue 3: 빠름 (reactivity).
React + Compiler: 빠름.

→ 매 framework 가 modern.
```

### LLM 도움
```
Vue / Svelte 의 docs 가 LLM 에 baked.
- Component 작성 OK.
- 작은 ecosystem 의 niche library 가 약.

→ React 보다 정확도 약간 ↓.
```

## 🤔 의사결정 기준
| 상황 | 추천 |
|---|---|
| 큰 ecosystem | React |
| 작은 bundle | Svelte |
| HTML-friendly | Vue |
| China market | Vue |
| Beautiful code | Svelte |
| Modern team | 매 다 OK |

## ❌ 안티패턴
- **Vue reactive destructure**: lost.
- **Svelte 4 → 5 mix runes**: 깨짐.
- **Library 가 React-only**: lock-in.
- **Mixed framework**: complexity.

## 🤖 LLM 활용 힌트
- Vue 3 composition API 가 modern.
- Svelte 5 runes = signal-based.
- Pinia / Nuxt / SvelteKit = ecosystem.
- React + Compiler 와 수렴.

## 🔗 관련 문서
- [[Frontend_SolidJS_Qwik]]
- [[Frontend_React_Compiler_Deep]]
- [[Frontend_State_Management_Modern]]
