발표
7주차 발표
김연수

Solid.js 에 대하여

Solid.js 란?

React와 같은 프론트엔드 프레임워크

2021년 정식 출시된 새로우면서도, 안정적인 툴이다.

기본적으로 선언적으로 쓸 수 있는 점도 동일하고, JSX를 쓴다.

Solid.js에서는 컴포넌트의 상태가 변경될 때마다 전체 함수를 재호출하지 않으며 대신, 변경된 상태에만 영향을 받는 DOM 노드를 최적화된 방식으로 직접 업데이트함

벨로그 탐방의 결과 4년후(?) 대체될 가능성이 있어보임

function MyComponent(props) {
  return <div>Hello My name is{props.name}</div>;
}
 
<MyComponent name="Solid" />;

상태 관리 , signal

리액트의 상태 훅처럼 읽기, 쓰기가 나뉘어져있음

Reactivity(반응성)을 가진 Signal 이 존재함

jsx useState+uesRef+useMemo 이며 상태가 변하면 지속적으로 rendering되는 부분을 줄여줌

// React
const [status, setStatus] = useState()
const processStatus = useCallback(() => {
	doSomethingWith(status)
}, [status])
 
// Solid
const [status, setStatus] = createSignal()
 
// 의존성없음
const processStatus = () => {
  doSomethingWith(status())
}
 
// 의존성 없음
createEffect(() => {
  doSomethingWith(status())
})
import { createSignal, onCleanup } from "solid-js";
 
function Counter() {
  const [count, setCount] = createSignal(0);
 
  const increment = () => setCount(count() + 1);
 
  return (
    <>
      <div>Count: {count()}</div>
      <button onClick={increment}>Increment</button>
    </>
  );
}

Q . 위의 예제에서 button은 re-rendering되지 않는가? 어떻게 그것이 가능한가?

위 예제에서 버튼은 상태 변경에 따라서 실제로 다시 렌더링되지 않습니다. Solid.js는 fine-grained reactivity를 사용하여 DOM 노드를 직접 업데이트하는 방식으로 최적화되어 있습니다.

count 상태 변수의 변경은 count 라인에서만 관찰되므로, 버튼에는 영향을 주지 않습니다. Solid.js는 컴포넌트를 처음 렌더링할 때 관찰 가능한 값들에 대한 의존성 그래프를 구축합니다. 이후에 상태가 변경될 때, 변경된 상태에 의존하는 DOM 노드만 업데이트합니다.

이 경우, count 상태 변수가 변경되어도 버튼에는 영향을 주지 않으므로, 버튼은 다시 렌더링되지 않습니다. 이렇게 Solid.js는 필요한 부분만 업데이트하므로 성능이 향상되고 불필요한 렌더링을 방지합니다. 이 최적화 방식 덕분에 Solid.js는 React와 같은 전통적인 리액티브 프레임워크에 비해 더 빠른 성능을 보여줍니다.

[특징]

Solid의 Signal은 순수한 오브젝트가 아니라 Proxy로 만들어진 특수한 오브젝트.

Proxy는 오브젝트의 Getter와 Setter를 하이잭킹해서 오브젝트의 속성 값을 읽어질 때와 값이 변경될 때,

Effect를 넣어 추가로 일을 해준다.

  1. 사용자가 특정 상태를 쓰기만 한다면, Signal은 Effect를 작동시켜 이 상태값이 어디에 쓰였는지를 정확히 기억해, 그 값이 변경시 쓰였던 컴포넌트만 정확히 업데이트를 해준다.

  2. React의 Hook과는 달리 딱히 규칙이 없다.

조건문 안에선 만들면 안되는 React Hook의 룰이, Signal에선 아무런 상관이 없다고함.

조건문 안에 만들든, 렌더마다 몇개의 시그널이 만들어지든 알아서 정리해준다.

심지어 콜백 안에서도 Signal을 만들어도, 아무런 문제없이 작동하고, 깔끔하게 정리해준다.

  1. 배열을 렌더링할때 필요한 key는 Soild.js 엔 필요없다.
// React
// item 중 하나가 바꾸려면 list도 바뀌어야하기에 map이 다시 실행된다.
return <>{list.map(item => <div key={item.id}>{item.name}</div>)}</>
// Solid
// 어느 항목이 변경시 해당 <div>를 직접 조작하기 때문에 map 메소드가 작동할 일이 없다.
// 알아서 찾아서 변경해준다는 느낌이 강함
return <>{list().map(item => <div>{item.name}</div>)}</>

key값은 그냥 그 오브젝트의 레퍼런스로, 해당 오브젝트의 속성 값이 바뀌면, 해당 속성값이 쓰인 항목만 바로 바꿔버려서, 아예 배열을 다시 이터레이션 할 필요가 없음

[제약]

상태는 모두 Signal로 관리되므로, 값을 불러오려면 Getter함수를 써서 불러와야한다.