웹 프레임워크를 쓰면 HTML, CSS, JavaScript만 사용하는 것보다 더 편리하게 웹개발을 할 수 있습니다. 오늘부터 ‘SvelteKit‘이라는 풀 스택 웹 프레임워크를 공부하고자 합니다.
목차
1. SvelteKit 개발 환경 구축, 기본 구조 및 Rune(현재 글)
1.1. SvelteKit 개발 환경 구축
1.2. SvelteKit 프로젝트 구조
1.3. 디버깅(npm run dev)
1.4. VS Code 확장 설치
1.5. +page.svelte 예제
1.6. Rune 알아보기
1.6.1. $state와 $derived
1.6.2. $effect
1.6.3. $props와 $bindable
1.6.4. $inspect
1.7. Routing(웹 페이지 추가)
1.7.1. 프로젝트명\src\route\+page.svelte 예제
1.7.2. 프로젝트명\src\route\test\+page.svelte 예제
1.7.3. 결과
2. Nested component와 Loading Data(2025. 05. 10. 업로드 예정)
3. Node 서버로 빌드
1.1. SvelteKit 개발 환경 구축
1.1.1. Node.js가 필요합니다. Node.js가 설치되어 있지 않다면 먼저 설치합니다.
Windows PC에 Node.js 설치, npm 명령어
1.1.2. SvelteKit 프로젝트를 만들 폴더에서 터미널을 엽니다.
1.1.3. npx sv create 프로젝트명 명령을 실행합니다.
1.1.4. 방향키로 원하는 항목을 지정한 후 엔터키로 선택할 수 있습니다.
- SvleteKit minimal: 새 앱을 만들기 위한 뼈대(barebones scaffolding)
- SvelteKit demo: Sverdle 게임이 있는 예제 프로젝트
- Svlete library: Svelte 라이브러리를 만들기 위한 템플릿
SvelteKit minimal을 선택합니다.
1.1.5. TypeScript 사용 여부를 선택합니다. 요즘 대세인 TypeScript를 사용하기 위해 Yes, using TypeScript syntax를 선택하겠습니다.
1.1.6. 추가하고 싶은 것을 스페이스바로 체크하고, 선택이 끝났으면 엔터를 누릅니다.
1.1.7. 패키지 관리자를 선택합니다. 저는 npm으로 하겠습니다.
1.1.8. 프로젝트명으로 폴더가 생성되었습니다. cd 프로젝트명 명령을 실행하여 프로젝트 폴더 안에 들어갑니다.(또는 VS Code 상에서 폴더 열기를 하여 프로젝트 폴더로 진입)
1.2. SvelteKit 프로젝트 구조
- 📁프로젝트명
- 📁.sveltekit
- 📁node_modules
- 📁src: Svelte 코드들이 들어 있는 폴더
- 📁lib
- 📁route: 이 폴더 안에 Svelte 코드들을 넣음.
- +page.svelte: 메인 페이지. index.html과 비슷함.
- 📁static: 정적 파일들이 들어 있는 폴더(예: CSS 코드, 이미지 등)
- .gitignore: Git 사용 시 제외할 파일 목록
- .npmrc
- package-lock.json
- package.json
- README.md
- svelte.config.js
- tsconfig.json
- vite.config.ts
route 폴더 안에 또 다른 폴더를 만들어서 다른 페이지를 추가할 수 있습니다. 1.7절을 참고하세요.
1.3. 디버깅(npm run dev)
방법1) npm run dev -- -open 명령을 실행하면 웹 브라우저가 열리며, 작업 결과를 실시간으로 확인할 수 있습니다.
방법2)
1.3.방법2.1. npm run dev 명령을 실행합니다.
1.3.방법2.2. http://localhost:5173/로 접속합니다.(Ctrl을 누른 채로 http://localhost:5173/을 클릭하시면 됩니다.)
프로젝트명\src\route\+page.svelte에 작성된 대로 출력됩니다.
디버깅을 종료할 때는 터미널에서 Ctrl+C를 누른 후 y를 입력하고 엔터를 누릅니다.
1.4. VS Code 확장 설치
Visual Studio Code에서 Svelte 코딩을 편하게 하기 위해 확장을 설치하겠습니다.
1.4.1. VS Code에서 +page.svelte를 열어 보면 오른쪽 아래에 “+page.svelte에 대한 권장되는 Svelte의 ‘Svelte for VS Code’ 확장을(를) 설치하시겠습니까?”라는 창이 뜹니다. 설치를 클릭합니다.
이 팝업창을 놓쳤다면 VS Code의 확장 탭에서 ‘Svelte for VS Code’ 확장을 검색하여 설치하시면 됩니다.
1.4.2. 게시자 신뢰 및 설치를 클릭합니다.
1.4.3. 오른쪽 아래 팝업창에서 Enable을 클릭합니다.
1.5. +page.svelte 예제
+page.svelte에 JavaScript/TypeScript, HTML, CSS 코드를 모두 작성합니다.
<script lang="ts">
function make_alert(){
alert("Hello, world!");
}
</script>
<svelte:head>
<title>Welcome to SvelteKit</title>
</svelte:head>
<h1>Welcome to SvelteKit</h1>
<p>Visit <a href="https://svelte.dev/docs/kit">svelte.dev/docs/kit</a> to read the documentation</p>
<p><button onclick={make_alert}>알림창 띄우기</button></p>
<style>
h1{background-color: #aaa;}
</style>
[Line 1~5 script]
JavaScript/TypeScript 코드를 작성하는 곳입니다.
script 태그를 열 때 lang=”ts”를 추가해 주면 TypeScript 코드를 사용할 수 있습니다.
본 예제에서는 “Hello, world!” 창이 뜨는 함수를 만들었습니다.
[Line 7~9 svelte:head]
HTML의 <head> 태그에 해당하는 부분을 작성하는 곳입니다.
메타태그나 title 태그 등을 여기에 작성하시면 됩니다.
[Line 11~13]
script 태그 그룹과 style 태그 그룹 사이에 HTML 코드를 작성합니다.
HTML 코드 작성 중 script 태그 그룹에서 선언한 변수나 함수를 불러올 때는 {변수명}과 같이 사용합니다.
[Line 13]\
<p><button onclick={make_alert}>알림창 띄우기</button></p>
onclick 같은 기능을 사용할 때는 HTML과 달리 큰따옴표를 대신 중괄호를 사용하여 {함수명}과 같이 사용합니다. 함수 이름 대신 람다 함수를 사용할 수도 있습니다.
[Line 15~17 style]
CSS 코드를 작성하는 곳입니다.
예제대로 프로젝트명\src\route\+page.svelte를 작성하면 아래와 같이 출력됩니다.
‘알림창 띄우기’ 단추를 클릭하면 “Hello, world!” 메시지 창이 뜹니다.
1.6. Rune 알아보기
Svelte는 script 태그 그룹에서 선언한 변수가 사용자에 의해 수정되면 그것을 웹 브라우저 화면상에 반영합니다. 다만, 변수가 다른 변수에 의존하는 경우 추적이 어려울 수 있으므로 Svelte 5에서 Rune이 도입되었습니다.
1.6.1. $state와 $derived
- $state: 일반적인 변수(혹은 ‘state’ 의미대로 상태)
- $derived: 다른 변수에 의해 값이 달라질 수 있는 변수
변수 선언은 let 변수명: type = $state(초기값); 같은 식으로 합니다.
<script lang="ts">
let a0: number = 0;
let a1: number = a0;
let a2: number = $state(a0);
let a3: number = $derived(a0);
let b0: number = $state(0);
let b1: number = b0;
let b2: number = $state(b0);
let b3: number = $derived(b0);
let c0: number = $derived(0);
let c1: number = c0;
let c2: number = $state(c0);
let c3: number = $derived(c0);
function increment(){
a0++;
b0++;
c0++;
}
</script>
<svelte:head>
<title>Welcome to SvelteKit</title>
</svelte:head>
<h1>state vs derived</h1>
<p><button onclick={increment}>모든 변수 1씩 증가</button></p>
<p>변수 a0: {a0}</p>
<p>변수 a0 값을 저장한 변수 a1: {a1}</p>
<p>변수 a0 값을 저장한 state 변수 a2: {a2}</p>
<p>변수 a0 값을 저장한 derived 변수 a3: {a3}</p>
<p>state 변수 b0: {b0}</p>
<p>state 변수 b0 값을 저장한 변수 b1: {b1}</p>
<p>state 변수 b0 값을 저장한 state 변수 b2: {b2}</p>
<p>state 변수 b0 값을 저장한 derived 변수 b3: {b3}</p>
<p>deirved 변수 c0: {c0}</p>
<p>deirved 변수 c0 값을 저장한 변수 c1: {c1}</p>
<p>deirved 변수 c0 값을 저장한 state 변수 c2: {c2}</p>
<p>deirved 변수 c0 값을 저장한 derived 변수 c3: {c3}</p>
<style>
h1{background-color: #aaa;}
</style>
이 코드대로 프로젝트명\src\route\+page.svelte를 작성하고 웹 브라우저에서 확인해 보면 감이 잡힐 것입니다.
먼저, 코드를 살짝 설명해 드리면 아래와 같습니다.
[Line 2~13]
여러 가지 방식으로 변수를 선언하고 초기화했습니다.
[Line 15~18]
a0, b0, c0를 각각 1 증가시키는 함수 increment를 만들었습니다.
[Line 27]\
<p><button onclick={increment}>모든 변수 1씩 증가</button></p>
increment 함수를 호출하는 버튼입니다.
[Line 28]\
<p>변수 a0: {a0}</p>
만약 a0==0이면 “변수 a0: 0”이라고 출력됩니다.
여기서 모든 변수 1씩 증가를 클릭해 보면
일단 0으로 초기화했던 변수 중 state 변수 b0과 dervied 변수 c0은 1로 바뀝니다.
다른 변수로 초기화했던 변수 중 state 변수는 출력이 변경되지 않았으며, derived 변수는 1로 바뀌었습니다.
1.6.2. $effect
$effect(함수)을 작성하면 변수의 값이 바뀌었을 때 괄호 안의 함수를 실행합니다.
<script lang="ts">
let a0: number = $state(1);
let a1: number = $derived(0);
let a2: string = $derived("");
let b0: number = $state(1);
let b1: number = $derived(0);
let b2: string = $derived("");
function sync(){
a1=a0;
b1=b0;
}
if(a0==a1){
a2="같습니다";
}
else{
a2="다릅니다";
}
$effect(() => {
if(b0==b1){
b2="같습니다";
}
else{
b2="다릅니다";
}
});
</script>
<svelte:head>
<title>Welcome to SvelteKit</title>
</svelte:head>
<h1>effect</h1>
<p><button onclick={sync}>변수 동기화</button></p>
<p>a0: {a0}</p>
<p>a1: {a1}</p>
<p>a0과 a1은 {a2}.</p>
<p>b0: {b0}</p>
<p>b1: {b1}</p>
<p>b0과 b1은 {b2}.</p>
<style>
h1{background-color: #aaa;}
</style>
[Line 2~7]
a0, b0은 state 변수이며 1로 초기화했습니다.
a1, b1은 derived 변수이며 0으로 초기화했습니다.
a2, b2는 derived 변수이며 ““으로 초기화했습니다.
[Line 9~12]
a1=a0; b1=b0;을 수행하는 함수 sync를 만들었습니다.
[Line 14~19]
a0==a1이면 a2에 “같습니다”를, 그렇지 않으면 a2에 “다릅니다”를 저장합니다.
[Line 21~28]
$effect를 사용합니다. 괄호 안의 함수는 람다 함수로 작성하였습니다. b0==b1이면 b2에 “같습니다”를, 그렇지 않으면 b2에 “다릅니다”를 저장합니다.
[Line 36]\
<p><button onclick={sync}>변수 동기화</button></p>
sync 함수를 호출하는 버튼입니다.
지금은 a0!=a1 && b0!=b1이므로 “a0과 a1은 다릅니다.”, “b0과 b1은 다릅니다.”로 출력됩니다.
이제 변수 동기화를 클릭해 보겠습니다.
sync 함수가 호출되어 a1=a0; b1=b0;이 수행되었습니다.
이제 a0과 a1이 둘 다 1로 같고, b0과 b1이 둘 다 1로 같습니다.
그러나 “a0과 a1은 다릅니다.”, “b0과 b1은 같습니다.”로 출력됩니다.
왜냐하면 sync 함수 호출 후 14~19행은 실행되지 않았지만, 21~28행 $effect 괄호 안의 함수는 실행되었기 때문입니다.
1.6.3. $props와 $bindable
$props와 $bindable은 .svelte 파일을 여러 개 만들 때 다른 파일에서 값을 불러오기 위해 사용합니다.
$props에 대해서는 다음 글에서 다루겠습니다.
1.6.4. $inspect
$inspect는 변수의 값이 바뀔 때 console.log로 개발자 도구에 출력해 주는 Rune입니다.
$inspect(변수명)과 같이 사용합니다.
<script lang="ts">
let a: number = $state(0);
$inspect(a);
</script>
<svelte:head>
<title>Welcome to SvelteKit</title>
</svelte:head>
<h1>inspect</h1>
<p>a 값: {a}</p>
<p><button onclick={() => {a++;}}>a 증가</button></p>
<style>
h1{background-color: #aaa;}
</style>
[Line 2]
let a: number = $state(0);
a는 state 변수이며 0으로 초기화했습니다.
[Line 4]
$inspect(a);
[Line 13]\
<p><button onclick={() => {a++;}}>a 증가</button></p>
람다 함수를 사용하였습니다. a++;를 실행하는 버튼입니다.
F12를 눌러 개발자 도구를 연 뒤 Console 탭을 보겠습니다.
이제 a 증가를 클릭해 보면
a 값이 증가하며 개발자 도구에도 기록이 남는 것을 보실 수 있습니다.
1.7. Routing(웹 페이지 추가)
Single Page Application을 만드는 것이 아닌 이상 여러 페이지로 누리집을 만들고 싶을 것입니다. 페이지를 나누려면 프로젝트명\src\route 안에 폴더를 만들고 폴더 이름을 Path로 합니다. 예제에서는 Path를 test로 하겠습니다.
참고로 URL 구조는 이와 같습니다. Path가 뭔지 모르겠는 분들은 한 번 찾아 보세요.
1.7.1. 프로젝트명\src\route\+page.svelte 예제
<script lang="ts">
</script>
<svelte:head>
<title>Welcome to SvelteKit</title>
</svelte:head>
<h1>Welcome to SvelteKit</h1>
<p>Visit <a href="https://svelte.dev/docs/kit">svelte.dev/docs/kit</a> to read the documentation</p>
<p><a href="/test">테스트 페이지 보기</a></p>
<style>
h1{background-color: #aaa;}
</style>
[Line 10]\
<p><a href="/test">테스트 페이지 보기</a></p>
하이퍼링크를 /test로 연결했습니다.
1.7.2. 프로젝트명\src\route\test\+page.svelte 예제
<script lang="ts">
</script>
<svelte:head>
<title>Welcome to Test</title>
</svelte:head>
<h1>Welcome to Test</h1>
<p>하이퍼링크 잘 되죠?</p>
<p><a href="/">메인으로</a></p>
<style>
h1{background-color: #aaa;}
</style>
[Line 10]\
<p><a href="/">메인으로</a></p>
하이퍼링크를 /로 연결했습니다.
1.7.3. 결과
테스트 페이지 보기를 클릭해 보겠습니다.
localhost:5173/test로 연결되며, 프로젝트명\src\route\test\+page.svelte에 작성한 대로 잘 출력됩니다.
1.8. 글 마무리
제 글을 읽어 주셔서 감사합니다. 다음에는 Nested component와 Loading Data를 비교해 보겠습니다. 다음에 만나요!
1.9. 참고 자료
1) denev6. 2025. “SvelteKit과 Svelte 기초”, 낙서장. (2025. 04. 26. 방문). https://denev6.tistory.com/208
2) brunnerh 외 1명. 2023. “What is the difference between Skeleton project and Library project when installing SvelteKit template?”, stackoverflow. (2025. 04. 26. 방문). https://stackoverflow.com/questions/76888854/what-is-the-difference-between-skeleton-project-and-library-project-when-install
3) sting01. 2023. “svelte 5 rune”, sting01.log. (2025. 04. 26. 방문). https://velog.io/@sting01/svelte-5-rune
4) BEUSABLE. 2021. “데이터 분석을 위한 기초, URL 이해하기”, Beusable. (2025. 04. 26. 방문). https://www.beusable.net/blog/?p=4507