두더지게임 모듈화하기 (1) feat 함수형 코딩 를 바탕으로 client 화면을 그려보기 전에 반응형 룬에 대해 알아보자.
svelte5 기반으로 구성했기 때문에 새로 적용된 rune을 사용해보았다.
약간 react와 비슷해진 느낌이다.
간단히 svete5의 rune을 알아보고 가겠다.
반응형시스템 비교
$state는 변수를 반응형으로 만드는 특별한 표시다. 반응형이란 변수가 변경될 때 화면도 자동으로 업데이트 되는 것을 의미한다.
//svelte5
let gameState = $state<GameState>({
isPlaying: false,
score: 0,
moles: []
})
값 변경 : 직접 할당으로 간단한게 업데이트한다.
gameState.score += 1)
//react
const [gameState, setGameState] = useState({
isPlaying: false,
score: 0,
moles: []
});
get과 set 함수를 분리하여 반환한다.
값 변경 시 항상 상태 설정함수를 사용한다.
setGameState(prev => ({...prev, score: prev.score + 1}))
불변성(Immutability)을 직접 관리해야 함
다른 상태를 기반으로 자동 계산 되는 값, 의존하는 상태가 변경될 때마다 자동으로 재계산된다.
// svelte5
// Derived state for UI conditions
let showStartButton = $derived(!gameState.isPlaying)
let showGameOver = $derived(!gameState.isPlaying && gameState.score > 0)
표현식을 직접 할당하는 간결한 방식으로 사용된다.
// react
const showStartButton = useMemo(
() => !gameState.isPlaying,
[gameState.isPlaying]
);
함수의 의존성 배열을 명시적으로 제공해야 한다. []에서! 의존성을 수동으로 명시하므로 누락할 수 있다. 보일러플레이트 코드가 더 많기도하다.
반응형 상태 변경시 부수 효과(side effect) 실행 사용하는 반응형 값을 자동으로 추적하여 변경 시 재실행한다.
// svelte5
$effect(() => {
const unsubscribe = gameInstance.subscribe(handleStateChange);
return unsubscribe; // 클린업 함수
})
클린업은 반환함수로 컴포넌트 제거 또는 효과 재실행 전 호출 됨
// react
useEffect(() => {
const unsubscribe = gameInstance.subscribe(handleStateChange);
return () => unsubscribe();
}, [gameInstance]); // 의존성 배열 명시
의존성 배열을 명시적으로 제공해야 함 의존성 배열을 잘못 지정하면 버그 발생 가능
Svelte: 일반 변수처럼 직접 할당, 간결한 문법 React: Hook 함수 호출 방식, 의존성 배열 필요
Svelte: 자동으로 의존성 추적 React: 의존성 배열을 수동으로 명시
Svelte: gameState.score += 1 처럼 직접 변이 가능 React: setGameState({...gameState, score: gameState.score + 1})와 같이 불변성 유지 필요
Svelte: 일반적으로 더 적은 코드로 동일한 기능 구현 가능 React: 상용구(boilerplate) 코드가 더 많음
두 프레임워크 모두 장단점이 있지만, Svelte 5는 보다 직관적이고 간결한 문법을 제공하여 초보자가 접근하기 쉬운 반면, React는 명시적인 코드 스타일로 복잡한 상태 관리에 더 구조적인 접근을 제공한다.