Solid is a declarative JavaScript library for creating user interfaces. Instead of using a Virtual DOM, it compiles its templates to real DOM nodes and updates them with fine-grained reactions. Declare your state and use it throughout your app, and when a piece of state changes, only the code that depends on it will rerun.
At a Glance
import{createSignal}from"solid-js";import{render}from"solid-js/web";functionCounter(){const[count,setCount]=createSignal(0);constdoubleCount=()=>count()*2;console.log("The body of the function runs once...");return(<><buttononClick={()=>setCount(c=>c+1)}>{doubleCount(
이걸로 잠시 관리자 페이지를 만들다가 협업의 어려움으로 React로 전환한 뼈아픔이 있었지만, Solid도 상당히 매력적인 라이브러리다.
그래서 이제서야 꺼내게 되었다. React와 Solid.js의 차이점을.
가상 DOM
기본적으로, 일단 Solid.js 들어본 적 있다면 이미 알고 있을 것이다.
React와 Vue 는 가상 DOM을 사용하는 대표적인 라이브러리다. 아, Angular도.
그러나 Preact, Solid.js, Svelte 등은 가상 DOM 없이 실제 DOM을 바로 렌더링한다.
그래서, 이들의 장단점을 정리하면 대충 이렇다.
가상 DOM
장점: 렌더링 전의 자주 발생하는 변경사항을 빠르게 정리할 수 있다.
단점: 렌더링 할때마다 가상DOM을 경유하여 실제DOM으로 옮기기 때문에 상대적으로 렌더링 속도가 느리다.
적합한 케이스: 태그 변경이 많이 일어나는 데이터그리드, 차트 등의 업무 중심의 컴포넌트
가상 DOM 사용하지 않음
장점: 렌더링 빈도가 적을 수록 성능이 빨라진다.
단점: 렌더링 빈도가 많을 수록 성능이 느려진다.
적합한 케이스: 태그 변경이 적게 일어나는 CMS, 쇼핑몰에 쓰는 컨텐츠 중심의 컴포넌트
따라서, 이 문제에 대해서는, 당신의 앱이 어느 쪽이 적당할 지는 직접 써보고 판단해야 할 문제인 것이기 때문에, 존중이니 취향해 드리겠다.
상태관리
리액트의 기본 상태관리 함수는 useState 이다.
Solid의 기본 상태관리 함수는 createSignal 이다.
이 둘의 차이점을 알아보자.
React 상태관리
상태관리 함수는 React 컴포넌트 함수 내에서만 호출이 가능하다.
(단, React 상태관리 결과물은 함수 외부에서도 호출 가능하다.)
React 상태관리는 빌드 과정을 거쳐 렌더링 상태의 기준을 정의한다.
Solid.js 상태관리
상태관리 함수들은 컴포넌트 내외 모두 호출이 가능하다.
Solid.js 상태관리 함수 호출부와 결과물 모두 빌드하지 않는다.
따라서, 스코프에 따라 유연한 상태관리 기준을 정의할 수 있다.
심지어, setter 호출만 해도 상태를 바꾸는 옵션도 설정할 수 있다.
// 두번째 인자에 옵션이 있는데, 아래처럼 하면 상태값이 같아도 상태가 바뀐다.const[,render]=createSignal(undefined,{equals:false})
여기서 주의사항! 솔리드의 상태관리 결과물은 대부분 함수다! 따라서 호출해야 한다! 애초에 시스템이 다른데, 리액트가 렌더링 시 컴포넌트 함수 본문를 갈아엎기 때문에 가능하지만, 솔리드는 함수 원형을 유지하고 상태관리가 별개로 작동하기 때문이다.
const[getter,setter]=createSignal()setTimeout(()=>setter('메롱'),1000)// react와 달리 getter 는 함수로 호출해야 한다!return<div>{getter()}</div>
부작용(Side-Effect)
React
설명 해봐야 손만 아프다. 리액트 개발자야 말 안해도 알지?
그리고 이 함수 리액트 컴포넌트 본문에서만 호출 가능한 것도 알제?
useEffect(()=>{/* 상태 바뀌면 실행할 함수 */return ()=>{/* 정리(Cleanup)할 함수 */}},[...영향받을속성이나상태])
Solid.js
사실 사용법은 큰 차이 없고, 당연하겠지만 리액트와 동일하게 비동기로 동작한다.
사소한 차이점이 있는데, 이제 설명하겠다.
먼저, 컴포넌트 함수 외에서도 호출 가능하다.
그다음, 위 React 구문을 똑같이 적용한다는 기준으로,
createEffect(()=>{/* 상태 바뀌면 실행할 함수 */onCleanup(()=>{/* 정리(Cleanup)할 함수 */})})// 위 함수 본문에 명시한 상태값들이 영향받을 때 호출된다!
첫번째, 영향 받을 상태를 명시적으로 지정 가능한 React와 달리, Svelte처럼 부작용 함수 본문에 언급한 상태가 바뀔 때 함수가 실행된다. 따라서 영향받을 상태값을 따로 함수로 빼는 꼼수를 통해 영향받을 상태를 한정짓는 방식으로 해결할 수 있다.
두번째, useEffect 함수에서는 리턴 함수로 정리할 수 있지만, createEffect 는 새로운 상태관리 영역 방식으로 관리하여 onCleanup 같은 생명주기 함수를 컴포넌트와 별개로 사용할 수 있다.
범위 관리(Context)
둘의 차이 별로 없다. 기능도 딱히 차이점 없으니 그냥 쓰던대로 쓰면 된다.
동적 컴포넌트
React
사실상 다이렉트로 동적 컴포넌트 호출 가능하다. 하지만, 빌드가 필요하고, 컴포넌트 함수임을 인지해야 하기 때문에 상수를 선언 후 그 상수를 컴포넌트 함수로 사용하는 살짝 번거로운 방법을 써야 한다. (JSX,TSX 한정, JS/TS일 경우 그럴 필요 없이 컴포넌트 함수임이 확실하면 함수처럼 호출하거나, 태그일 경우 React.createElement 함수 쓰면 됨)
React 처럼 콜백으로 받을 수 있다. 하지만 Solid에서는 더 강력한 요소의 상태관리 기능을 지원하는데,
바로 use: 속성이다. 이건 Svelte에도 있는 기능인데, 하나의 상태관리 영역으로 취급하기 때문에, 여기서도 컴포넌트 초기화될 때 호출하는 onMount 함수와 컴포넌트 정리할 때 onCleanup 함수를 쓸 수 있다.
어자피 요소 받은 뒤 호출하기 때문에 onMount 함수 호출은 필요없고, removeEventListener 같이 정리가 필요할 경우에 onCleanup 함수의 콜백 인자에 구현하면 된다.
하지만 Solid는 상태가 바뀌어도 본문은 그대로 유지가 되기 때문에 React처럼 속성 분해하는 등의 편리한 구문을 썼다간 큰 낭패를 본다. 당장 볼 수 있는 일이라면, 초기 상태에만 한 번 반영하고 그 이후로는 아무런 미동도 없는 네 컴포넌트를 발견할 수 있다. 따라서, 객체를 분해하는 짓은 여기서는 하지 않는 것이 좋고, 만약 "범주별 분리"를 하고 싶다면, Solid에서 제공하는 splitProps 유틸리티를 써야 한다.
즉, 중요한 핵심은, 절대 개별 속성으로 분해하지 말 것!