6.3 KiB
6.3 KiB
id, title, category, status, source_trust_level, verification_status, created_at, updated_at, tags, tech_stack, applied_in, aliases
| id | title | category | status | source_trust_level | verification_status | created_at | updated_at | tags | tech_stack | applied_in | aliases | |||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| frontend-vue3-svelte5-patterns | Vue 3 / Svelte 5 — modern composition / runes | Coding | draft | B | conceptual | 2026-05-09 | 2026-05-09 |
|
|
|
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)
<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
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)
// 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)
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)
<!-- 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)
<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)
<!-- routes/users/[id]/+page.svelte -->
<script>
let { data } = $props();
</script>
<h1>{data.name}</h1>
// 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
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
<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)
<input v-model='message' />
<!-- 동등 -->
<input :value='message' @input='message = $event.target.value' />
→ Two-way binding 가 native.
Vue Teleport (portal)
<Teleport to='body'>
<div class='modal'>...</div>
</Teleport>
→ React Portal 비슷.
Suspense
<Suspense>
<template #default>
<AsyncComponent />
</template>
<template #fallback>
<Loading />
</template>
</Suspense>
Lifecycle (Vue)
import { onMounted, onUnmounted, onUpdated } from 'vue';
onMounted(() => { ... });
onUnmounted(() => { ... });
onUpdated(() => { ... });
Lifecycle (Svelte 5)
<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 와 수렴.