Svelte 5의 새로운 문법
Svelte 5가 2024년에 정식 출시되면서 기존 문법과 많은 부분이 달라졌다. 특히 반응성 시스템이 완전히 새로워졌는데, 이제 $state, $derived, $effect 같은 rune이라는 개념을 사용한다.
1. $state - 상태 관리의 새로운 방식
기존 Svelte에서는 그냥 let count = 0 이렇게 선언하면 반응성이 자동으로 작동했다. 하지만 Svelte 5에서는 명시적으로 $state()를 사용해야 한다. (스벨트5에서도 여전히 스벨트4 문법을 지원하지만 가독성을 위해)
<script>
let count = $state(0);
let user = $state({ name: '김철수', age: 30 });
function increment() {
count++;
}
</script>
<button onclick={increment}>클릭: {count}</button>
<p>{user.name}님의 나이는 {user.age}세</p>
$state()로 선언한 변수는 값이 변경되면 자동으로 UI가 업데이트된다. 객체나 배열도 깊은 반응성을 지원하기 때문에 중첩된 속성을 변경해도 감지된다.
2. $derived - 계산된 값
다른 상태에 의존하는 값을 만들 때 $derived()를 사용한다. Vue의 computed나 비슷한 개념이다.
<script>
let firstName = $state('홍');
let lastName = $state('길동');
let fullName = $derived(`${firstName}${lastName}`);
let numbers = $state([1, 2, 3, 4, 5]);
let sum = $derived(numbers.reduce((a, b) => a + b, 0));
</script>
<p>전체 이름: {fullName}</p>
<p>합계: {sum}</p>
$derived()는 내부에서 사용하는 $state 값이 변경될 때마다 자동으로 재계산된다. 따로 의존성을 명시할 필요가 없다.
3. $effect - 부수 효과 처리
컴포넌트가 마운트되거나 상태가 변경될 때 특정 코드를 실행하려면 $effect()를 사용한다.
<script>
let count = $state(0);
$effect(() => {
console.log(`카운트가 ${count}로 변경됨`);
document.title = `카운트: ${count}`;
});
$effect(() => {
const interval = setInterval(() => {
count++;
}, 1000);
return () => {
clearInterval(interval);
};
});
</script>
$effect() 내부에서 사용된 $state 값이 변경되면 자동으로 다시 실행된다. 함수를 반환하면 cleanup 로직으로 사용되는데, 컴포넌트가 언마운트되거나 effect가 재실행되기 전에 호출된다.
4. $props - Props 받기
부모 컴포넌트로부터 데이터를 받을 때는 $props()를 사용한다.
<script>
let { title, count = 0, onClick } = $props();
</script>
<div>
<h2>{title}</h2>
<button onclick={onClick}>카운트: {count}</button>
</div>
구조 분해 할당으로 props를 받고, 기본값도 설정할 수 있다. TypeScript를 사용한다면 타입도 지정 가능하다.
5. 이벤트 핸들링
Svelte 5에서는 on:click 대신 표준 HTML 속성인 onclick을 사용한다.
<script>
let message = $state('');
function handleClick(event) {
message = '버튼이 클릭됨';
}
function handleInput(event) {
message = event.target.value;
}
</script>
<button onclick={handleClick}>클릭</button>
<input oninput={handleInput} value={message} />
<p>{message}</p>
이벤트 수식어도 달라졌다. |preventDefault나 |stopPropagation 같은 방식이 아니라 함수 내부에서 직접 처리해야 한다.
6. 조건부 렌더링과 반복
조건부 렌더링과 리스트 렌더링은 기존과 비슷하지만, key 지정 방식이 약간 다르다.
<script>
let isLoggedIn = $state(false);
let todos = $state([
{ id: 1, text: 'Svelte 5 공부하기' },
{ id: 2, text: '프로젝트 만들기' }
]);
</script>
{#if isLoggedIn}
<p>환영합니다!</p>
{:else}
<p>로그인이 필요합니다.</p>
{/if}
<ul>
{#each todos as todo (todo.id)}
<li>{todo.text}</li>
{/each}
</ul>
#each 블록에서 괄호 안에 key를 지정하는 방식은 동일하다.
7. 양방향 바인딩
bind: 디렉티브는 Svelte 5에서도 그대로 사용된다.
<script>
let text = $state('');
let checked = $state(false);
let selected = $state('option1');
</script>
<input bind:value={text} />
<p>입력값: {text}</p>
<input type="checkbox" bind:checked={checked} />
<p>체크 상태: {checked}</p>
<select bind:value={selected}>
<option value="option1">옵션 1</option>
<option value="option2">옵션 2</option>
</select>
Svelte 5의 rune 시스템은 처음에는 낯설 수 있지만, 반응성이 어떻게 작동하는지 명확하게 보여준다는 장점이 있다. 특히 복잡한 상태 관리나 부수 효과를 다룰 때 예측 가능한 동작을 보장한다. 기존 Svelte 3/4 문법과는 많이 다르지만, 더 명확하고 강력한 도구가 된 것은 확실하다.
'개발' 카테고리의 다른 글
| [React] 이벤트 처리하기_2 (0) | 2025.12.25 |
|---|---|
| [Cursor] 인공지능과 함께하는 개발 (1) | 2025.12.22 |
| [Svelte] Svelte vs React, 스벨트와 리액트 (1) | 2025.12.19 |
| [claude] 클로드와 함께 바이브 코딩(intellij) (0) | 2025.12.17 |
| [javascript] Promise (0) | 2025.12.17 |
댓글