Svelte

개요
모처럼 새로운 개념의 프론트 엔드 프레임워크가 등장했다. Svelte!
기존의 react, vue 등의 framework 는 가상의 DOM 을 사용해서 새로운 Virtual DOM을 이전 Snapshot과 비교하거나, 상태 변화에 따른 새로운 가상 요소 생성해서 실제 DOM 에 반영한다. 하지만 Svelte 는 가상돔을 사용하지 않는 새로운 개념의 라이브러리다?
Svelte
기존 프레임워크(혹은 라이브러리)와의 차이
기존 프레임워크들은 선언적인 State Driven Code 를 사용한다. 때문에 DOM operation 에 추가적인 구조 설계 작입이 필요하다.
Svelte 는 build time compiler 다. 다른 프레임워크처럼 run time 이 아니다.
코드를 작고 프레임워크에 속하지 않는 vanillaJS 로 컴파일 한기 때문에 초기 load 속도가 빠르다!
기존 프레임워크가 브라우저에서 작업의 대부분을 수행했다면 svelte는 앱을 빌드할 때 발생하는 컴파일 단계에서 작업의 대부분을 수행한다
No virtual DOM
가상돔은???
기존 가상돔은 어떻게 동작하는가 (브라우저 동작 방식)
VirtualDOM 이 성능이 좋다고 하는 것은 raw DOM 이 update 되는 것이 무거운 작업이기 때문에 상대적으로 성능이 좋다는 것이다. 브라우저가 DOM 을 랜더링 하는 방식은
HTML을 파싱하여 DOM Tree를 생성하고, CSS를 파싱하여 스타일 규칙을 만듭니다.
이 두개를 합쳐서 실제로 웹 브라우저에 보여져야할 요소를 표현한 "렌더 트리" 라는 것을 만듭니다.
이 렌더 트리를 기준으로 레이아웃을 배치하고 색을 칠하는 등의 작업을 합니다.
DOM 을 조작하면 랜더트리를 재생성하고 (그러면 모든 요소들의 스타일이 다시 계산됨), 레이아웃을 만들고, 페인팅을 한다. 복잡한 DOM 변경이 자주 일어나는 SPA 에서는 브라우저가 겁나 일해야한다는 의미!
프로그래밍을 하면서 DOM 을 100개의 구성요소를 변경시키려하면 100번의 렌더링이 있는 것이다. 그러나 VirtualDOM 은 Snapshot 을 통해서 변경점을 파악한 다음 변경되는 부분을 한꺼번에 한번만 렌더링 시키기에. 성능에 좋다고 하는 경우는 주로 이 플로우에서 가져오는 이점을 말한다. (사실 이 부분은 VirtualDOM 을 사용하지 않고도 해결할 수 있음. 변화를 묶어서 DOM Fragment에 적용한 다음 기존 DOM 에 적용시키는 방법). 가상돔을 통해서 얻는 이점으로 State driven UI 를 개발할 수 있도록 하는 수단이 된다는 것이다
좀 더 자세히 알고싶다면 이 링크를 참조하자
그런데 가상돔은 느리다고?
느리지 않다! 보통의 경우 가상돔은 충분히 빠르다. 그러나 가상돔은 assembler 를 C 로 컴파일 하는 것과 같이 raw DOM operation 을 React 와 같은 API 를 통해서 호출하는 것이다.
가상돔을 통해서 DOM 을 업데이트 할 때는 어쨋든 중간 과정에서 많은 일들이 일어난다. 어찌되었는 Diffing 과정이 있고, 이 과정은 오버헤드를 불러올 수도 있다.
가상돔이 기능(feature)의 개념은 아니지만 가상돔을 통해서 얻는 이점으로 State driven UI 를 개발할 수 있도록 하는 수단이 된다는 것이다! 그러나 Svelte 는 가상돔을 사용하지 않고도 유사한 프로그래밍 모델을 만들 수 있다는 사실을 보여준다.
그래서 Sevelte 는
Svelte는 Virtual(가상) DOM을 사용하지 않습니다. Virtual DOM은 충분히 빠르고 유용하지만 이는 기능이 아닌 수단일 뿐이며, 이를 사용하지 않고도 유사한 프로그래밍 모델을 얻을 수 있다고 Svelte는 설명합니다. 새로운 Virtual DOM을 이전 Snapshot과 비교하거나(Diffing), 상태 변화에 따른 새로운 가상 요소 생성 등에 많은 오버헤드가 있을 수 있으며 최종적으론 실제 DOM을 업데이트해야 하므로 그 과정을 생략하는 것이 더욱 빠를 수 있다고 합니다.
benchmark
size
💡
The smaller the file, the faster the download, and less to parse.
Transfer size in KB - fewer is better
Styling
// p.svelte <style> p { color: purple; font-family: 'Comic Sans MS', cursive; font-size: 2em; } </style> <p>This is a paragraph.</p>
JavaScript
<style> 태그 안에 css 규칙을 선언할 수 있으며, 해당 컴포넌트(파일단위) 단위의 scope 를 가진다.
Nested Components
<script> import Nested from './Nested.svelte'; let scope = 1; </script> <p>This is a paragraph.</p> <Nested/>
JavaScript
반응성
assignment
반응성은 변경된 값이 DOM에 자동으로 반영됨을 의미합니다.
Svelte는 별도의 Setter 없이 값의 할당(assignments)만으로 업데이트를 트리거(Trigger)할 수 있습니다.
실제로 상당히 편리합니다!
<script> let count = 0; </script> <button on:click={() => count += 1}> {count} </button>
JavaScript
assignment 가 reactivity 를 trigger 하기 때문에 array 의 push, splice 같은 함수는 reactivity 를 trigger 하지 않는다. ⇒ immutable 개념이 필요하다.
rethinking reactivity
react 에서는 상태값을 다음과 같이 명시적으로 명령한다
const { count } = this.state; this.setState({ count: count + 1 });
JavaScript
Rich Harris 는 리액트는 reactive 하지 않다고 말한다.
기존 프레임워크들은 그들만의 hook 을 사용하여 프레임워크를 구현한다. 기존의 hook 들은 몇가지 매력적인 점이 있지만, 자연스럽지 않은 코드와 garbage collector 에게 불필요한 작업을 하게 만드는 것과 같은 단점도 있다. 이와 같은 단점을 생각하면서 svelte 는 다른 방식으로 접근해본다.
바로 svelte 가 compile 이 가능하다는 점을 이용하는 것이다.
realised that the best API is no API at all. We can just use the language. Updating some count value — and all the things that depend on it — should be as simple as this ⇒ code += 1 from here
Svelte 3부터는 다음과 같이 변경을 탐지하고자 하는 문을 $ 라벨(JavaScript의 라벨)로 애너테이션한다. 이 라벨로 지정된 변수의 값이 변경 됐을 때 UI를 갱신하는 코드가 컴파일 시 생성된다($$invalidate라는 변경을 전파하는 코드가 빌드 파일에 포함됨). (참고로 svelte2 까지는 react와 비슷한 느낌의 코드였음. setState 대신 .set ?)
전역 상태 관리
ETC
Svelte Devtools
UI Components
Svelte Material UI - https://sveltematerialui.com/
Svelte Flat UI Components - https://svelteui.js.org
Framework
sapper - react framework 인 Next.js 에서 영감을 받아 만들어짐
typescript, scss, etc...
svelte.preprocess api 를 사용해서 여러 preprocessing plugin 을 사용가능하다. 여기를 참조하자
참고