React 진영 개발자가 Svelte 입문하게 된다면 던지는 단골 질문이 하나 있습니다.
“Svelte에서 어떻게 React의 useEffect
처럼 상태를 구독할 수 있나요?”
이를 답하기 위해선, Svelte 특유의 reactive
문법을 상황에 따라 잘 활용해야 합니다.
간단한 상태 구독
React에서는 useEffect
훅을 사용하여 컴포넌트의 상태 변화를 감지하고, 특정 상태가 변경될 때마다 부수 효과(side effects)를 실행합니다.
useEffect(() => {
console.log(name);
}, [name]);
js
Svelte에서는 reactive statement(반응형 선언)을 사용하여 유사한 기능을 구현할 수 있습니다. Svelte의 반응형 선언은 $:
기호를 사용하여 정의되며, Svelte 컴파일러는 표현식 안에 사용된 모든 변수를 파악하여 해당 값이 변경될 때마다 자동으로 다시 표현식 구문을 실행합니다.
<script>
$: console.log(name);
// 여러 줄 형태
$: {
console.log(name);
}
// 즉시 실행 함수 형태
$: (() => {
console.log(name);
})();
</script>
svelte
특정 상태만 구독
React는 의존성 배열을 활용하여 특정 상태에만 의존하는 부수 효과를 실행할 수 있습니다.
useEffect(() => {
console.log(state1, state2, state3);
// state1이 변경될 때만 수행된다.
}, [state1]);
js
하지만 Svelte에서는 $:
기호를 사용한 반응형 선언이 모든 관련 상태의 변경에 반응합니다. 즉, state1, state2, state3 중 어느 하나라도 변경되면 부수 효과가 실행됩니다.
<script>
$: console.log(state1, state2, state3);
// 🚨 state1, state2, state3이 변경될 때 모두 수행된다.
</script>
svelte
이를 해결하기 위해, 불필요한 의존성을 $:
표현식 밖으로 내보내면 됩니다. 즉, 부수 효과 함수를 별도로 선언하고 의존할 상태만을 건네주면 됩니다.
<script>
const effect = (state1) => {
console.log(state1, state2, state3);
};
$: effect(state1);
</script>
svelte
더 React 스럽게 작성한다면 다음과 같이 할 수도 있습니다.
<script>
const effect = () => {
console.log(state1, state2, state3);
};
$: effect(), [state1];
// $: (() => {
// effect();
// })(), [state1];
</script>
svelte
조금 난해할 수 있지만 함수에 인자를 건네 줄 필요가 없어 코드가 더 간결한 것 같습니다. 특히 Typescript에서 더 빛을 발합니다.
reactive 과 rendering
Svelte는 React와 다르게 랜더링과 상태 구독이 별개로 진행됩니다. 따라서 랜더링 이후의 DOM
을 접근하려면 tick
을 활용해야하는 점을 꼭 유의하셔야 합니다.
<script>
import { tick } from 'svelte';
let btnEl;
let cnt = 1;
const checkBtnWidth = async () => {
if (!btnEl) return;
// 상태가 DOM에 적용되는 것을 보장하는 promise
await tick();
const { width } = btnEl.getBoundingClientRect();
console.log(width);
};
$: checkBtnWidth(), [cnt];
const onClick = () => {
cnt = cnt * 10;
};
</script>
<button bind:this={btnEl} on:click={onClick}>
{cnt}
</button>
svelte
REPL에서 직접 테스트 해보세요!
맺으면서
Svelte의 진입 장벽이 타 프레임워크에 비해 낮다고 합니다. 분명히 쉽게 간결한 코드를 작성할 수 있는 점이 있지만 Svelte도 React만큼이나 프레임워크에 대한 이해도가 뒷바침 되어야 복잡한 웹 어플리케이션을 다룰 수 있는 것 같습니다.
최근 Svelte 5에 대한 예고와 함께 runes이라는 새로운 reactive
시스템이 소개되었는데요. 코드 형태가 조금 기괴(?)해졌지만 개인적으로 더 직관적으로 의존성을 다룰 수 있는 것 같습니다. 프론트엔드 초심자에게 조금 더 진입장벽이 생겼지만, React 진영의 개발자는 더 쉽게 Svelte로 정착할 수 있지 않을까 기대합니다.