Frontend/Svelte

Svelte란? + 프로젝트 생성 및 코드 맛보기

둉이 2022. 11. 21. 01:29

 

이번에 토이 프로젝트를 시작하면서 예전부터 유튜브에서 관심있게 본 svelte를 공부하면서 사용해 보려고 한다.

 

Svelte란?

Svelte는 2016년도에 등장한 프론트엔드 기술 중 하나로, 프레임워크가 없는 프레임워크 혹은 컴파일러라고도 한다.

 

따로 프레임워크를 로딩하지 않고 빌드시 자바스크립트 코드로 컴파일링하므로 React와 Vue, Angular 등의 기존 프론트엔드 기술보다 빠른 웹 어플리케이션을 만들 수 있다.

 

이제 Svelte의 특징에 대해 알아보고, 기존 프레임워크들과 비교해서 어떤 점들이 좋은지에 대해 알아보자.

 

 

 

Svelte의 특징

적은 코드로도 기능 작성 가능

Svelte는 동일한 코드를 작성하더라도 React, Vue에 비해 적은 양의 코드로도 작성이 가능하다.

 

간단하게 두 숫자를 더하는 코드를 작성한다고 하자.

 

React로 코드를 작성하는 것보다 Svelte로 코드를 작성하는 것이 한 눈에 봐도 간결하다는 걸 알 수 있다.

// React.js
import { useState } from 'react';

const App = () => {
	const [a, setA] = useState(0);
	const [b, setB] = useState(0);

	const handleChangeA = ({ target }) => setA(+target.value);
	const handleChangeB = ({ target }) => setB(+target.value);

	return (
		<>
			<input type="number" value={a} onChange={handleChangeA} />
			<input type="number" value={b} onChange={handleChangeB} />
			<p>sum: {a + b}</p>
		</>
	);
};

export default App;

// Svelte
<script>
	let a = 0;
	let b = 0;
</script>

<input type="number" bind:value={a} onChange={handleChangeA} />
<input type="number" bind:value={b} onChange={handleChangeB} />
<p>sum: {a + b}</p>

적은 코드를 사용하게 되면 유지보수에 필요한 리소스도 줄어들게 되고 번들 사이즈도 감소하므로 더욱 빠른 페이지 렌더링이 가능하다는 장점이 있다.

 

 

가상 DOM을 사용하지 않음

Svelte의 가장 큰 장점으로는 리액트, 뷰 등의 기존 프레임워크들에 비해 뛰어난 성능을 보장한다는 점이다.

 

뛰어난 성능의 이유에는 가상 DOM을 사용하지 않는다는 이유가 있다.

 

가상 DOM이란 메모리에 가상으로 존재하는 실제 DOM과 동일한 값을 갖는 자바스크립트 객체이다.

 

실제 DOM에 변경 사항을 반영하는 것이 아닌, 가상 DOM에서 변경 사항을 적용한 후 실제 DOM과 다른 부분만 비교하여 변경함으로써 불필요한 렌더링 횟수를 줄일 수 있다.

 

React와 Vue에서는 이러한 가상 DOM을 사용하여 화면을 업데이트하기 때문에 보다 빠른 페이지 업데이트가 가능하다.

 

하지만 가상 DOM은 여전히 DOM 업데이트가 필요할 때마다 부가 작업이 필요하다는 점과 메모리 공간을 많이 차지한다는 단점이 존재한다.

 

Svelte는 빌드시 작성한 컴포넌트들을 명령형 코드로 변환함으로써 가상 DOM 없이도 빠르게 DOM을 업데이트할 수 있는 뛰어난 성능을 제공한다.

 

 

상태 관리 라이브러리를 사용하지 않음

react는 전역 상태 관리를 위해 redux, recoil 등의 상태 관리 라이브러리를 사용한다.

(물론 상태 관리 라이브러리를 사용하지 않는 방법도 있음)

 

하지만 svelte는 자바스크립트 자체에 반응성(Reactive)을 제공하기 때문에 별도의 상태 관리 라이브러리를 사용하지 않아도 된다.

 

let 키워드를 사용하여 변수를 선언하면, 그대로 해당 변수를 state처럼 사용할 수 있다.

 

 

번들링 속도가 빠르고 번들 크기가 작음

Svelte 공식 홈페이지에서는 Vite를 사용하여 프로젝트 환경설정을 하는 것을 권장하고 있다.

 

번들러란 여러 모듈들을 합쳐서 하나의 번들로 만드는 도구이다.

 

기존에 주로 사용되던 Webpack, Rollup 등의 번들러는 매번 파일이 수정될 때마다 번들링이 실행되기 때문에 파일이 많아지고 어플리케이션의 크기가 커질 수록 번들링 속도가 느려진다는 단점이 있었다.

 

이러한 느린 속도 문제를 개선하여 등장한 것이 바로 esbuild이며, 기존 번들러보다 무려 100배나 빠른 속도를 제공한다.

 

하지만 esbuild는 바닐라 자바스크립트 환경에서만 사용이 가능했고, 빌드만을 위한 도구이므로 프레임워크 개발 환경에서 주로 사용되는 Webpack처럼 트랜스파일링, 코드 스플리팅, 트리 셰이킹 등의 기능 지원도 미비했기 때문에 빠른 속도에도 불구하고 널리 사용되지 못했다.

 

하지만 Snowpack이 등장하면서 위 문제는 자연스럽게 해결되었다.

 

Snowpack은 수정이 잦은 개발 환경에서는 esbuild를 사용하여 빌드를 하고, 프로덕션 빌드를 할 때에는 Webpack을 사용하여 번들링을 함으로써 esbuild의 빠른 빌드 속도와 Webpack의 편의 기능을 둘 다 취할 수 있었다.

 

또한 파일의 일부가 수정되면 수정된 파일의 내용만 반영할 수 있는 HMR(Hot Module Replace) 기능을 지원한다.

 

Vite는 이러한 Snowpack의 컨셉을 그대로 이어받은 번들러로, Snowpack과 마찬가지로 esbuild를 사용한 빠른 번들링, HMR 지원 등을 제공하는 번들러이다.

 

 

 

이렇게 장점이 많은 Svelte이지만 물론 단점도 존재한다.

 

작은 커뮤니티 규모

비교적 최근에 나온 기술이기 때문에 React, Vue에 비해 커뮤니티 규모가 그리 크지 않다.

 

그 말은 즉슨 개발에 참고할 레퍼런스도 부족하다.

 

Svelte를 사용하다 예상치 못한 에러가 발생해도 검색을 통해 도움을 받지 못할 수도 있기 때문에 이러한 점은 각오해야 한다.

 

 

 

 

 

 

프로젝트 생성

2022년도 5월부터 SvelteKit을 사용하여 프로젝트를 생성하는 방법이 도입되었다.

아래와 같이 간단한 명령어로 프로젝트를 생성할 수 있다.

npm create svelte [프로젝트 이름]  # 해당 프로젝트 이름으로 생성
# 혹은
npm create svelte .  # 현재 폴더 경로에 프로젝트 생성

npm i  # 의존성 모듈 설치
npm run dev -- --open  # 어플리케이션 실행

 

참고로 기존에 사용되던 vite-cli을 이용한 프로젝트 생성 방법은 다음과 같다.

npm create vite@latest myapp -- --template svelte
cd myapp
npm install
npm run dev

 

 

둘 중 편한 방법으로 프로젝트를 생성하면 된다.

 

create 명령어를 실행하게 되면 아래 사진과 같이 프로젝트 생성에 필요한 템플릿과 여러 옵션들을 선택할 수 있는 콘솔이 출력된다.

 

템플릿은 총 3가지 종류가 있다.

svelte 템플릿 종류

 

SvelteKit demo app은 말 그대로 라우팅, 상태 변경, 스타일 예제 코드들이 포함된 데모 앱을 생성한다.

 

Skeleton project는 페이지 1개만 있는 빈 프로젝트를 생성한다.

 

Library skeleton project는 Svelte 라이브러리를 만들기 위한 빈 프로젝트이다.

 

 

템플릿을 선택하고 나면 Typescript, ESLint, Prettier, Playwright 옵션 설치 유무를 묻는 콘솔이 출력되는데, 필요에 따라 선택하자.

 

프로젝트 생성이 완료되면, 콘솔 메시지에 나와있는 대로 의존성 설치 후 npm run dev 명령어로 어플리케이션 서버를 실행할 수 있다.

프로젝트 생성 완료

 

 

 

Svelte 프로젝트 구조

템플릿으로 Svelte 프로젝트를 생성하게 되면, 기본적으로 다음과 같은 구조를 갖는다.

src
   lib   - 리소스, 스크립트, 모듈이 위치 / $lib alias 사용 가능
      server   - 서버 단에서만 사용되는 파일
   routes   - 라우팅을 위한 페이지가 위치
      +page.svelte
      +path.js
  params   - path 파라미터를 사용할 때 특정 조건의 매개변수만 매칭할 수 있도록 하는 matcher 모음
static   - html에서 사용되는 정적 리소스가 위치
tests   - 테스트 관련 파일

 

여기서 중요한 점은 Svelte도 Next.js와 마찬가지로 폴더 구조 라우팅을 지원한다는 점이다.

 

src/routes 폴더 하위에 페이지로 사용할 컴포넌트를 위치시키면 자동으로 페이지를 인식하여 렌더링한다.

 

여기서 주의할 점은, 페이지 컴포넌트가 될 Svelte 컴포넌트 파일명은 앞에 + 기호가 붙은 +page.svelte이어야 한다.

 

+page.svelte는 기본적으로 초기 페이지 렌더링을 제외한 경우에는 항상 CSR로 동작한다.

 

만약 API 호출과 같이 서버 사이드에서 실행되어야 할 작업이 있는 경우에는 +page.js(혹은 +page.ts) 파일을 따로 생성해주면 서버 단에서 미리 연산 후 결과값을 클라이언트로 전달할 수 있다.

// page.js 예시
export const prerender = true;
 
/** @type {import('./$types').PageLoad} */
export async function load({ fetch }) {
  const res = await fetch('/my-server-route.json');
  return await res.json();
}

 

+page.js에서는 load 함수와 페이지 옵션인 prerender, ssr, csr 사용이 가능하다.

옵션 설명
load 페이지(클라이언트)로 props를 전달하기 위한 함수
load()에서 반환한 값은 +page.svelte에서 data라는 이름으로 접근 가능
prerender pre-render 여부
true/false(boolean) 혹은 'auto' 값 설정 가능
ssr SSR 여부
서버에서 미리 HTML을 렌더링하지 않으려면 false로 설정
(단, 이 경우에는 초기에 빈 페이지가 렌더링)
csr CSR 여부
자바스크립트를 사용하지 않는 정적 페이지에서는 false 설정 가능

 

주의할 점으로는 ssr, csr 둘 다 false 값을 가질 경우에는 아무 것도 렌더링되지 않아 빈 페이지만 생성된다.

 

 

 

특정 path의 페이지를 추가하려면 해당 path를 이름으로 갖는 폴더를 생성한 후, 해당 폴더 내에 +page.svelte 파일이 위치하도록 하면 된다.

 

이 부분도 Next.js와 마찬가지로 동적 파라미터를 지원하므로 [slug] 형태로 폴더명을 생성하면 동적인 라우팅이 가능하다.

 

+page.svelte 외에도 Svelte에서는 아래와 같은 특별한 컴포넌트를 제공한다.

파일명 설명
+page.svelte 페이지 컴포넌트
초기 페이지 요청 시에는 SSR+CSR, 이후 요청은 CSR로 동작
+layout.svelte 모든 페이지의 레이아웃이 되는 컴포넌트
레이아웃 영역 외 페이지 컴포넌트가 들어갈 위치는 <slot />으로 지정
+error.svelte 에러 페이지 컴포넌트
페이지 load 중 에러가 발생하거나 존재하지 않는 경로로 접근시 표출
+server.js(ts)
(혹은 +layout.server.js)
서버 단에서 preload할 페이지 props
+page.ts와 마찬가지로 load 함수 호출 및 prerender, ssr, csr export 가능

 

 

위에서 설명한 부분 외에 더 자세한 정보가 알고싶다면 svelte 공식 문서를 참고하자.

 

Project structure • Docs • SvelteKit

Project structure Edit this page on GitHub A typical SvelteKit project looks like this: my-project/ ├ src/ │ ├ lib/ │ │ ├ server/ │ │ │ └ [your server-only lib files] │ │ └ [your lib files] │ ├ params/ │ │ └ [your param

kit.svelte.dev

 

 

Svelte 문법 알아보기

이제 본격적으로 개발을 시작하기 위한 Svelte의 문법을 알아보자.

 

기본적으로 자바스크립트 베이스 + jsp, ejs 등의 템플릿 엔진의 문법과 유사하다.

 

조건문

{#if 조건}
  ...
{:else if 조건}
  ...
{:else}
  ...
{/if}

 

조건문은 javascript와 비슷하게 if, else if, else 문을 제공하며, 조건 첫 줄에는 # 기호, 마지막 줄에는 / 기호, 중간 줄에는 : 기호를 붙인다.

 

아래는 조건문 예제 코드이다.

<script>
  let message = 'hello world';
  let toggle = false;
</script>
 
<button on:click={() => {toggle = !toggle}}>
  Toggle
</button>
 
{#if toggle}
  <h1>{message}!</h1>
{:else}
  <div>No message</div>
{/if}

 

 

반복문

{#each 배열 as 배열 요소}
  ...
{/each}

 

반복문은 for of가 아닌 each as 키워드를 사용한다.

 

each 오른쪽에는 반복의 대상이 되는 이터러블한 값을 아래는 반복문 예제 코드이다.

<script>
  let fruits = ['Apple', 'Banana', 'Cherry', 'Orange', 'Mango'];
  function deleteFruit() {
    fruits = fruits.slice(1);
  }
</script>

<ul>
  {#each fruits as fruit}
    <li>{fruit}</li>
  {/each}
</ul>
<button on:click={deleteFruit}>Eat it!</button>

 

 

데이터 바인딩

Vue와 마찬가지로, Svelte는 데이터를 양방향으로 바인딩하여 사용할 수 있다.

 

bind: 접두어를 이용해 state와 속성을 바인딩하고, on: 접두어를 이용하여 이벤트 핸들러를 바인딩할 수 있다.

<script>
  let text = '';
</script>

<h1>{text}</h1>

<input type="text" bind:value={text} />

<button
  on:click={() => {
    text = '';
  }}
  >초기화
</button>

 

 

 

참고 자료

 

스벨트 vs 리액트, 누가 더 뛰어날까? | 요즘IT

스벨트(Svelte)와 리액트(React) 사이에서 고민하고 계신가요? 걱정하지 마세요. 모두가 비슷한 고민을 하고 있습니다. 온갖 기술이 난무하는 요즘, 최고의 개발 도구를 선택하는 것은 쉬운 일이

yozm.wishket.com

 

Vite 이야기 (feat. Svelte)

바이트 아니고 **비트** 입니다. 이번 글은 Vite에 관한 내용입니다. 최근 Svelte와 관련한 사내 발표 내용 중 다들 재미있어 했던 Vite에 관한 이야기를 블로그 형식으로 각색하여 다시 정리해보았습

velog.io