[Luvit ํ•œ๋‹ฌ ์Šคํ„ฐ๋””] ์ƒˆ๋กœ์šด ์›น ๊ฐœ๋ฐœ์˜ ์‹œ์ž‘ ์Šค๋ฒจํŠธ #1

2025. 7. 6. 22:47ยท๐Ÿ“šbook
์ œ์ดํŽ Luvit ํ•œ ๋‹ฌ ์Šคํ„ฐ๋””

 

๐Ÿ“™Svelte

์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๊ฐœ๋ฐœ์— ์‚ฌ์šฉ๋˜๋Š” ์˜คํ”ˆ์†Œ์Šค ํ”„๋ก ํŠธ์—”๋“œ ํ”„๋ ˆ์ž„์›Œํฌ

Svelte๋Š” React๋‚˜ Vue์™€๋Š” ๋‹ค๋ฅธ ๋ฐฉ์‹์œผ๋กœ ์ ‘๊ทผํ•˜๋Š” ํ”„๋ก ํŠธ์—”๋“œ ๋„๊ตฌ๋‹ค. ํ”„๋ ˆ์ž„์›Œํฌ๊ฐ€ ์•„๋‹Œ ์ปดํŒŒ์ผ๋Ÿฌ๋ผ๊ณ ๋„ ํ•˜๋Š” Svelte๋Š” React๋‚˜ Vue์ฒ˜๋Ÿผ ๋ธŒ๋ผ์šฐ์ €์—์„œ ์ฝ”๋“œ๋ฅผ ํ•ด์„ํ•˜๊ณ  ์‹คํ–‰ํ•˜๋Š” ๋Ÿฐํƒ€์ž„ ๋ฐฉ์‹(๊ฐ€์ƒ DOM)์„ ๋”ฐ๋ฅด์ง€ ์•Š๋Š”๋‹ค. ๋Œ€์‹ , ๊ฐœ๋ฐœ์ž๊ฐ€ ์ž‘์„ฑํ•œ ํŒŒ์ผ์„ ๋นŒ๋“œ ์‹œ์ ์— ๋ถ„์„ํ•ด ์ตœ์ ํ™”๋œ ์ˆœ์ˆ˜ JavaScript ์ฝ”๋“œ๋กœ ๋ณ€ํ™˜ํ•œ๋‹ค.

 

๋•๋ถ„์— ์ตœ์ข… ๊ฒฐ๊ณผ๋ฌผ์—๋Š” ํ”„๋ ˆ์ž„์›Œํฌ ์ž์ฒด์˜ ์ฝ”๋“œ๊ฐ€ ๊ฑฐ์˜ ํฌํ•จ๋˜์ง€ ์•Š๊ณ , ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๊ตฌ๋™ํ•˜๋Š” ๋ฐ ํ•„์š”ํ•œ ์ตœ์†Œํ•œ์˜ ์ฝ”๋“œ๋งŒ ๋‚จ๋Š”๋‹ค. ์ด๋กœ ์ธํ•ด ๋ฒˆ๋“ค ํฌ๊ธฐ๊ฐ€ ์ž‘๊ณ  ์ดˆ๊ธฐ ๋กœ๋”ฉ ์†๋„๊ฐ€ ๋น ๋ฅด๋ฉฐ, ๋Ÿฐํƒ€์ž„ ์„ฑ๋Šฅ๋„ ๋” ๋›ฐ์–ด๋‚˜๋‹ค.

 

Svelte ํŠน์ง•

โœ… No Virtual DOM

React ๊ฐ™์€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋Š” ์ƒํƒœ๊ฐ€ ๋ณ€๊ฒฝ๋  ๋•Œ๋งˆ๋‹ค ๊ฐ€์ƒ DOM(Virtual DOM)์ด๋ผ๋Š” ๋ฉ”๋ชจ๋ฆฌ์ƒ์˜ UI ํ‘œํ˜„์„ ์ƒˆ๋กœ ๋งŒ๋“ค๊ณ , ์ด์ „ ๋ฒ„์ „๊ณผ ๋น„๊ต(diffing)ํ•˜์—ฌ ์‹ค์ œ DOM์— ๋ณ€๊ฒฝ ์‚ฌํ•ญ์„ ์ ์šฉํ•œ๋‹ค. ์ด ๋ฐฉ์‹์€ ํšจ์œจ์ ์ด์ง€๋งŒ, ๋ชจ๋“  ๋น„๊ต์™€ ์—…๋ฐ์ดํŠธ๊ฐ€ ๋Ÿฐํƒ€์ž„์— ์ˆ˜ํ–‰๋˜๊ธฐ ๋•Œ๋ฌธ์— ์ผ์ •ํ•œ ์˜ค๋ฒ„ํ—ค๋“œ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.


Svelte๋Š” ์ด ๊ณผ์ •์„ ์ปดํŒŒ์ผ ์‹œ์ ์œผ๋กœ ์˜ฎ๊ฒผ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด count๋ผ๋Š” ๋ณ€์ˆ˜๊ฐ€ ๋ณ€๊ฒฝ๋˜๋ฉด, Svelte ์ปดํŒŒ์ผ๋Ÿฌ๋Š” count์— ์˜์กดํ•˜๋Š” DOM ๋…ธ๋“œ๋ฅผ ๋ฏธ๋ฆฌ ํŒŒ์•…ํ•ด๋‘๊ณ , ํ•ด๋‹น ๋…ธ๋“œ์˜ ํ…์ŠคํŠธ๋ฅผ ์ง์ ‘ ๊ฐฑ์‹ ํ•˜๋Š” ์ตœ์ ํ™”๋œ JavaScript ์ฝ”๋“œ๋ฅผ ์ƒ์„ฑํ•œ๋‹ค. ๋”ฐ๋ผ์„œ ๋ณ„๋„์˜ ๊ฐ€์ƒ DOM์ด ํ•„์š” ์—†์œผ๋ฉฐ, ๋Ÿฐํƒ€์ž„ ์˜ค๋ฒ„ํ—ค๋“œ๋ฅผ ์ตœ์†Œํ™”ํ•  ์ˆ˜ ์žˆ๋‹ค.

 

โœ… Truly Reactive

Svelte์˜ ๋ฐ˜์‘์„ฑ ์‹œ์Šคํ…œ์€ $: ๋ ˆ์ด๋ธ” ๊ตฌ๋ฌธ์„ ํ†ตํ•ด ๊ตฌํ˜„๋œ๋‹ค. ์ด๋Š” JavaScript์˜ ๊ธฐ์กด ๋ ˆ์ด๋ธ” ๋ฌธ๋ฒ•์„ ์ฐฝ์˜์ ์œผ๋กœ ์žฌํ•ด์„ํ•œ ๊ฒƒ์œผ๋กœ, Svelte ์ปดํŒŒ์ผ๋Ÿฌ์—๊ฒŒ ํ•ด๋‹น ์ฝ”๋“œ๊ฐ€ ๋ฐ˜์‘ํ˜•์œผ๋กœ ๋™์ž‘ํ•ด์•ผ ํ•จ์„ ์•Œ๋ ค์ฃผ๋Š” ์‹ ํ˜ธ ์—ญํ• ์„ ํ•œ๋‹ค.


๊ฐœ๋ฐœ์ž๋Š” ์–ด๋–ค ์ƒํƒœ๊ฐ€ ๋ณ€ํ•  ๋•Œ ์–ด๋–ค ์ฝ”๋“œ๊ฐ€ ์‹คํ–‰๋ผ์•ผ ํ•˜๋Š”์ง€๋ฅผ ๋ณ„๋„๋กœ ์„ ์–ธํ•˜๊ฑฐ๋‚˜, React์˜ useEffect์ฒ˜๋Ÿผ ์˜์กด์„ฑ ๋ฐฐ์—ด์„ ๊ด€๋ฆฌํ•  ํ•„์š”๊ฐ€ ์—†๋‹ค. Svelte ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ ๋ณ€์ˆ˜ ๊ฐ„ ์˜์กด์„ฑ์„ ์ •์  ๋ถ„์„ํ•˜์—ฌ, ์ƒํƒœ ๋ณ€๊ฒฝ ์‹œ ํ•„์š”ํ•œ ์ฝ”๋“œ๋งŒ ์ž๋™์œผ๋กœ ์‹คํ–‰๋˜๋„๋ก ๋ณด์žฅํ•œ๋‹ค. ์ด ๋•๋ถ„์— ์˜์กด์„ฑ ๋ฐฐ์—ด ๊ด€๋ฆฌ์˜ ๋ณต์žก์„ฑ๊ณผ ๊ทธ๋กœ ์ธํ•œ ์ž ์žฌ์  ๋ฒ„๊ทธ์—์„œ ์ž์œ ๋กœ์›Œ์ง„๋‹ค.

 

โœ… Less Code

Svelte๋Š” ๋ถˆํ•„์š”ํ•œ ๋ณด์ผ๋Ÿฌํ”Œ๋ ˆ์ดํŠธ(boilerplate) ์ฝ”๋“œ๋ฅผ ์ค„์ด๋Š” ๋ฐ ์ดˆ์ ์„ ๋งž์ท„๋‹ค. ์ƒํƒœ๋ฅผ ๊ด€๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด useState ํ›…์„ ์‚ฌ์šฉํ•˜๊ฑฐ๋‚˜, ์ƒํƒœ ๋ณ€๊ฒฝ์„ ์œ„ํ•ด setCount ๊ฐ™์€ ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•  ํ•„์š”๊ฐ€ ์—†๋‹ค. ๋Œ€์‹  ์ผ๋ฐ˜ JavaScript ๋ณ€์ˆ˜์— ๊ฐ’์„ ํ• ๋‹นํ•˜๋Š” ๊ฒƒ๋งŒ์œผ๋กœ ์ƒํƒœ๊ฐ€ ๊ด€๋ฆฌ๋˜๊ณ  UI๊ฐ€ ๊ฐฑ์‹ ๋œ๋‹ค.


์ด๋Ÿฌํ•œ ์ ‘๊ทผ ๋ฐฉ์‹์€ ์ฝ”๋“œ๋Ÿ‰์„ ํฌ๊ฒŒ ์ค„์ด๊ณ , ๊ฐ€๋…์„ฑ์„ ๋†’์ด๋ฉฐ, ๊ฐœ๋ฐœ์ž๊ฐ€ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์— ๋” ์ง‘์ค‘ํ•  ์ˆ˜ ์žˆ๋„๋ก ๋•๋Š”๋‹ค. ๋˜ํ•œ HTML, CSS, JavaScript๊ฐ€ ํ•˜๋‚˜์˜ ํŒŒ์ผ(.svelte)์— ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ํ†ตํ•ฉ๋˜๊ธฐ ๋•Œ๋ฌธ์— ์ปดํฌ๋„ŒํŠธ ๋‹จ์œ„์˜ ์œ ์ง€๋ณด์ˆ˜์™€ ์ƒ์‚ฐ์„ฑ์ด ๋†’๋‹ค.


๐Ÿ“™Svelte ๊ฐœ๋ฐœ ํ™˜๊ฒฝ ์„ค์ •

Svelte๋Š” Git ์ €์žฅ์†Œ ๋ณต์ œ ๋„๊ตฌ์ธ degit์„ ์‚ฌ์šฉํ•œ๋‹ค. degit์€ git ํžˆ์Šคํ† ๋ฆฌ๋ฅผ ์ œ์™ธํ•˜๊ณ  ์ตœ์‹  ๋ฒ„์ „์˜ ํŒŒ์ผ๋งŒ ๊ฐ€์ ธ์˜จ๋‹ค.

# Svelte ๊ณต์‹ ํ…œํ”Œ๋ฆฟ์œผ๋กœ 'my-svelte-app' ํ”„๋กœ์ ํŠธ ์ƒ์„ฑ
npx degit sveltejs/template my-svelte-app

# ์ƒ์„ฑ๋œ ํด๋”๋กœ ์ด๋™ํ•˜์—ฌ ์˜์กด์„ฑ ์„ค์น˜
cd my-svelte-app
npm install

# ๊ฐœ๋ฐœ ์„œ๋ฒ„ ์‹คํ–‰
npm run dev

degit์œผ๋กœ ํ…œํ”Œ๋ฆฟ์„ ๋ฐ”๋‹ค์˜ค๋ฉด ๊ธฐ๋ณธ์ ์œผ๋กœ svelte 3.x.x ๋ฒ„์ „์ด ์„ค์น˜๋œ๋‹ค. ์ตœ์‹  ๋ฉ”์ด์ € ๋ฒ„์ „์€ 6์ด์ง€๋งŒ, ๋ฒ„์ „ 5๋ถ€ํ„ฐ๋Š” SvelteKit์ด๋ผ๋Š” ํ’€์Šคํ… ํ”„๋ ˆ์ž„์›Œํฌ ๊ฐœ๋…์ด ํ†ตํ•ฉ๋˜์—ˆ๋‹ค. ์ผ๋ฐ˜ ์Šค๋ฒจํŠธ๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์‹ถ๋‹ค๋Š” v4๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹๋‹ค.

# ํ”„๋กœ์ ํŠธ ๋ฃจํŠธ์—์„œ ์‹คํ–‰
npx svelte-migrate@latest svelte-4

CLI์—์„œ ๋ช‡ ๊ฐ€์ง€ ์„ธ๋ถ€ ์„ค์ •์„ ๋ฌผ์–ด๋ณด๋ฉด ์„ ํƒํ•œ ํ›„ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜์„ ์™„๋ฃŒํ•˜๋ฉด ๋œ๋‹ค.

 

ํด๋”๊ตฌ์กฐ

์ƒ์„ฑ๋œ ํ”„๋กœ์ ํŠธ์˜ ๊ธฐ๋ณธ์ ์ธ ๊ตฌ์กฐ๋Š” ๋ฆฌ์•กํŠธ์™€ ์œ ์‚ฌํ•˜๋‹ค.

my-svelte-app/
โ”œโ”€โ”€ public/          # ์ •์  ํŒŒ์ผ (favicon, ์ด๋ฏธ์ง€ ๋“ฑ)
โ”‚   โ””โ”€โ”€ index.html
โ”œโ”€โ”€ src/             # Svelte ์ปดํฌ๋„ŒํŠธ ์†Œ์Šค
โ”‚   โ”œโ”€โ”€ App.svelte   # ๋ฃจํŠธ ์ปดํฌ๋„ŒํŠธ
โ”‚   โ””โ”€โ”€ main.js      # ์•ฑ ์ง„์ž…์ 
โ”œโ”€โ”€ package.json     # ์˜์กด์„ฑ ์ •๋ณด
โ””โ”€โ”€ rollup.config.js # ๋ฒˆ๋“ค๋ง ์„ค์ • (Rollup)

Svelte 4๋Š” ๊ธฐ๋ณธ ๋ฒˆ๋“ค๋Ÿฌ๋กœ Rollup์„ ์‚ฌ์šฉํ•˜๊ธฐ ๋•Œ๋ฌธ์—, rollup.config.js๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ๋‹ค. ์—ฌ๊ธฐ์„œ ๋นŒ๋“œ ์„ค์ •์„ ํ™•์ธํ•˜๊ณ  ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ๋‹ค. 


๐Ÿ“™Svelte ์ปดํฌ๋„ŒํŠธ ๊ตฌ์กฐ

svelte์˜ ๋ชจ๋“  ์ปดํฌ๋„ŒํŠธ๋Š” .svelte ํ™•์žฅ์ž๋ฅผ ๊ฐ€์ง„ ํ•˜๋‚˜์˜ ํŒŒ์ผ๋กœ ์กด์žฌํ•œ๋‹ค. ์Šคํฌ๋ฆฝํŠธ ์˜์—ญ, ๋งˆํฌ์—… ์˜์—ญ, ์Šคํƒ€์ผ ์˜์—ญ์œผ๋กœ ๊ตฌ์„ฑ๋œ๋‹ค. 

<!-- App.svelte -->
<script>
  // 1. ์Šคํฌ๋ฆฝํŠธ ์˜์—ญ: JS ๋กœ์ง
  let name = "Svelte";
</script>

<!-- 2. ๋งˆํฌ์—… ์˜์—ญ: HTML ๊ตฌ์กฐ -->
<h1>Hello {name}!</h1>

<!-- 3. ์Šคํƒ€์ผ ์˜์—ญ: CSS -->
<style>
  /* ์—ฌ๊ธฐ์— ์ž‘์„ฑ๋œ ์Šคํƒ€์ผ์€ ์ด ์ปดํฌ๋„ŒํŠธ์—๋งŒ ์ ์šฉ๋œ๋‹ค! */
  h1 {
    color: royalblue;
  }
</style>

๐Ÿ“™Svelte ๋ฌธ๋ฒ•

์ƒํƒœ ๊ด€๋ฆฌ

Svelte์˜ ์ƒํƒœ ๊ด€๋ฆฌ๋Š” `useState` ๊ฐ™์€ ํŠน๋ณ„ํ•œ API ์—†์ด, ์ผ๋ฐ˜์ ์ธ JavaScript ๋ณ€์ˆ˜ ์„ ์–ธ(`let`)์œผ๋กœ ์‹œ์ž‘

๋‹จ์ˆœ ์ƒํƒœ๊ฐ’

<script>
  let name = 'Svelte';
</script>

<h1>Hello, {name}!</h1>

 

 

์ด๋ฒคํŠธ๋กœ ์ƒํƒœ๊ฐ’ ๋ณ€๊ฒฝ

์ด๋ฒคํŠธ๋ฅผ ํ†ตํ•ด ๋ณ€์ˆ˜์— ์ƒˆ๋กœ์šด ๊ฐ’์„ ํ• ๋‹นํ•˜๋ฉด Svelte๊ฐ€ ๋ณ€๊ฒฝ์„ ๊ฐ์ง€ํ•˜๊ณ  ํ™”๋ฉด์„ ์ž๋™์œผ๋กœ ๋ Œ๋”๋งํ•œ๋‹ค.

<script>
  let count = 0;

  function increment() {
    count = count + 1;
  }
</script>

<p>Count: {count}</p>
<button on:click={increment}>Increment</button>

 

๊ฐ์ฒด ์†์„ฑ์„ ์ƒํƒœ๊ฐ’์œผ๋กœ ์‚ฌ์šฉ
๊ฐ์ฒด ๋˜ํ•œ ์ƒํƒœ๊ฐ’์ด ๋  ์ˆ˜ ์žˆ๋‹ค. ๊ฐ์ฒด์˜ ์†์„ฑ์„ ๋ณ€๊ฒฝํ•  ๋•Œ๋„ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ํ• ๋‹น(`=`)์„ ์‚ฌ์šฉํ•ด์•ผ Svelte๊ฐ€ ๋ณ€ํ™”๋ฅผ ๊ฐ์ง€ํ•œ๋‹ค.

<script>
  let user = {
    name: '์Šค๋ฒจํŠธ',
    isLoggedIn: false,
  };

  function login() {
    user = { ...user, isLoggedIn: true };
  }
</script>

{#if user.isLoggedIn}
  <p>{user.name}๋‹˜ ํ™˜์˜ํ•ฉ๋‹ˆ๋‹ค.</p>
{:else}
  <button on:click={login}>๋กœ๊ทธ์ธ</button>
{/if}


๊ฐ์ฒด๋กœ ์ด๋ฃจ์–ด์ง„ ๋ฐฐ์—ด๋กœ ์ƒํƒœ๊ฐ’ ํ‘œ์‹œ

<script>
  let todos = [
    { id: 1, text: 'Svelte ๊ณต๋ถ€ํ•˜๊ธฐ', done: true },
    { id: 2, text: '์šด๋™ํ•˜๊ธฐ', done: false },
  ];

  function addTodo() {
    const newTodo = { id: Date.now(), text: '์ƒˆ๋กœ์šด ํ•  ์ผ', done: false };
    // ๋ฐฐ์—ด์— push ํ•œ ํ›„, ์ž๊ธฐ ์ž์‹ ์—๊ฒŒ ๋‹ค์‹œ ํ• ๋‹นํ•ฉ๋‹ˆ๋‹ค.
    todos.push(newTodo);
    todos = todos;
  }
</script>

<button on:click={addTodo}>ํ•  ์ผ ์ถ”๊ฐ€</button>
<ul>
  {#each todos as todo (todo.id)}
    <li class:done={todo.done}>{todo.text}</li>
  {/each}
</ul>

<style>
  .done { text-decoration: line-through; color: #aaa; }
</style>

 

๋ฐ˜์‘์„ฑ

๋ฐ˜์‘์„ฑ์€ ํŠน์ • ์ƒํƒœ๊ฐ€ ๋ณ€ํ•  ๋•Œ ๋‹ค๋ฅธ ๊ฐ’์ด๋‚˜ UI๊ฐ€ ์ž๋™์œผ๋กœ ์—…๋ฐ์ดํŠธ๋˜๋Š” ๊ฒƒ

์‚ผํ•ญ ์—ฐ์‚ฐ์ž๋ฅผ ํ†ตํ•œ ๋งˆํฌ์—…์—์„œ์˜ ๋ฐ˜์‘์„ฑ
์Šคํฌ๋ฆฝํŠธ ๋กœ์ง ์—†์ด๋„ ๋งˆํฌ์—… ๋‚ด์—์„œ ๊ฐ„๋‹จํ•œ ๋ฐ˜์‘์„ฑ์„ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค.

<script>
  let loggedIn = false;
</script>

<button on:click={() => loggedIn = !loggedIn}>
  {loggedIn ? '๋กœ๊ทธ์•„์›ƒ' : '๋กœ๊ทธ์ธ'}
</button>


์Šคํฌ๋ฆฝํŠธ ๋ฐ˜์‘์„ฑ ์ฝ”๋“œ (`$:`)
Svelte์˜ ํ•ต์‹ฌ ๊ธฐ๋Šฅ. $: ๋ ˆ์ด๋ธ”์€ ์˜์กดํ•˜๋Š” ๋ณ€์ˆ˜๊ฐ€ ๋ณ€๊ฒฝ๋  ๋•Œ๋งˆ๋‹ค ํ•ด๋‹น ๋ผ์ธ์˜ ์ฝ”๋“œ๋ฅผ ๋‹ค์‹œ ์‹คํ–‰์‹œํ‚จ๋‹ค.

<script>
  let count = 0;
  
  $: doubled = count * 2;
  $: message = `ํ˜„์žฌ ์นด์šดํŠธ ${count}์˜ ๋‘ ๋ฐฐ๋Š” ${doubled}์ž…๋‹ˆ๋‹ค.`;

  // $: ๋’ค์— ๋กœ์ง ๋ธ”๋ก๋„ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.
  $: if (count >= 5) {
    console.log('์นด์šดํŠธ๊ฐ€ 5 ์ด์ƒ์ž…๋‹ˆ๋‹ค!');
  }
</script>

<button on:click={() => count += 1}>
  Count: {count}
</button>
<p>{message}</p>

 

Svelte ์ด๋ฒคํŠธ

์ด๋ฒคํŠธ ๋ฌธ๋ฒ•
on: ์ง€์‹œ์–ด๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ HTML ์š”์†Œ์— ์ด๋ฒคํŠธ๋ฅผ ์—ฐ๊ฒฐํ•œ๋‹ค.

<script>
  function handleClick() {
    alert('๋ฒ„ํŠผ์ด ํด๋ฆญ๋˜์—ˆ์Šต๋‹ˆ๋‹ค!');
  }
</script>

<button on:click={handleClick}>ํด๋ฆญ</button>
์ž์ฃผ ์“ฐ๋Š” ์ด๋ฒคํŠธ ์„ค๋ช…
on:click ์š”์†Œ๋ฅผ ํด๋ฆญํ–ˆ์„ ๋•Œ   
on:mouseover ๋งˆ์šฐ์Šค ํฌ์ธํ„ฐ๊ฐ€ ์š”์†Œ ์œ„๋กœ ์˜ฌ๋ผ์™”์„ ๋•Œ
on:input input, textarea ๋“ฑ์˜ ๊ฐ’์ด ๋ณ€๊ฒฝ๋  ๋•Œ
on:submit <form>์ด ์ œ์ถœ๋  ๋•Œ
on:keydown` ํ‚ค๋ณด๋“œ๋ฅผ ๋ˆŒ๋ €์„ ๋•Œ


์ด๋ฒคํŠธ ์ˆ˜์‹์–ด
| ๊ธฐํ˜ธ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ด๋ฒคํŠธ์˜ ๋™์ž‘์„ ์ œ์–ดํ•˜๋Š” ์ˆ˜์‹์–ด๋ฅผ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ๋‹ค.

<form on:submit|preventDefault={handleSubmit}>
  <button on:click|once>ํ•œ ๋ฒˆ๋งŒ ํด๋ฆญ ๊ฐ€๋Šฅ</button>
</form>
์ž์ฃผ ์“ฐ๋Š” ์ˆ˜์‹์–ด ์„ค๋ช…
preventDefault ์ด๋ฒคํŠธ์˜ ๊ธฐ๋ณธ ๋™์ž‘์„ ๋ง‰๋Š”๋‹ค.
stopPropagation ์ด๋ฒคํŠธ๊ฐ€ ์ƒ์œ„ ์š”์†Œ๋กœ ์ „ํŒŒ(๋ฒ„๋ธ”๋ง)๋˜๋Š” ๊ฒƒ์„ ๋ง‰๋Š”๋‹ค.
once ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๋ฅผ ์ตœ์ดˆ ํ•œ ๋ฒˆ๋งŒ ์‹คํ–‰ํ•œ๋‹ค.
self event.target์ด ์ž๊ธฐ ์ž์‹ ์ผ ๋•Œ๋งŒ ํ•ธ๋“ค๋Ÿฌ๋ฅผ ์‹คํ–‰ํ•œ๋‹ค.

 

Svelte Props

props๋Š” ๋ถ€๋ชจ ์ปดํฌ๋„ŒํŠธ์—์„œ ์ž์‹ ์ปดํฌ๋„ŒํŠธ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์ „๋‹ฌํ•˜๋Š” ๋ฐฉ๋ฒ•

Props ๊ธฐ๋ณธ ๋ฌธ๋ฒ•
์ž์‹ ์ปดํฌ๋„ŒํŠธ์˜ <script> ๋ธ”๋ก ์•ˆ์—์„œ export let์œผ๋กœ ๋ณ€์ˆ˜๋ฅผ ์„ ์–ธํ•˜๋ฉด ํ•ด๋‹น ๋ณ€์ˆ˜๋Š” prop์ด ๋œ๋‹ค.

<!-- Child.svelte -->
<script>
  export let userName; 
</script>

<p>{userName}๋‹˜, ํ™˜์˜ํ•ฉ๋‹ˆ๋‹ค.</p>

<!-- Parent.svelte -->
<script>
  import Child from './Child.svelte';
</script>

<Child userName="์Šค๋ฒจํŠธ" />


Props ๊ธฐ๋ณธ๊ฐ’ ์„ค์ •
prop์„ ์„ ์–ธํ•  ๋•Œ ๊ฐ’์„ ํ• ๋‹นํ•˜๋ฉด ๊ธฐ๋ณธ๊ฐ’์ด ๋œ๋‹ค. ๋ถ€๋ชจ์—์„œ ํ•ด๋‹น prop์„ ์ „๋‹ฌํ•˜์ง€ ์•Š์œผ๋ฉด ์ด ๊ธฐ๋ณธ๊ฐ’์ด ์‚ฌ์šฉ๋œ๋‹ค.

<!-- Child.svelte -->
<script>
  export let userName = '๋ฐฉ๋ฌธ์ž'; // ๊ธฐ๋ณธ๊ฐ’ ์„ค์ •
</script>

 

์Šคํ”„๋ ˆ๋“œ Props
๊ฐ์ฒด์˜ ๋ชจ๋“  ์†์„ฑ์„ ํ•œ ๋ฒˆ์— props๋กœ ์ „๋‹ฌํ•˜๊ณ  ์‹ถ์„ ๋•Œ ์‚ฌ์šฉํ•œ๋‹ค.

<script>
  import InfoCard from './InfoCard.svelte';

  const userInfo = {
    name: '๊น€์Šค๋ฒจํŠธ',
    age: 10,
    country: 'ํ•œ๊ตญ',
  };
</script>

<InfoCard {...userInfo} />

 

 

Svelte ๋กœ์ง

ํ…œํ”Œ๋ฆฟ ์•ˆ์—์„œ ๋™์ ์ธ UI๋ฅผ ๊ทธ๋ฆฌ๊ธฐ ์œ„ํ•œ ์ œ์–ด๋ฌธ

๋…ผ๋ฆฌ ๋กœ์ง: if ๋ธ”๋ก
์กฐ๊ฑด์— ๋”ฐ๋ผ ๋‹ค๋ฅธ ๋งˆํฌ์—…์„ ๋ Œ๋”๋งํ•œ๋‹ค.

{#if status === 'loading'}
  <p>๋กœ๋”ฉ ์ค‘...</p>
{:else if status === 'error'}
  <p>์˜ค๋ฅ˜ ๋ฐœ์ƒ!</p>
{:else}
  <p>๋กœ๋”ฉ ์™„๋ฃŒ.</p>
{/if}

 

 

๋ฐ˜๋ณต ๋กœ์ง: each ๋ธ”๋ก
๋ฐฐ์—ด์˜ ๊ฐ ํ•ญ๋ชฉ์„ ์ˆœํšŒํ•˜๋ฉฐ ๋ Œ๋”๋งํ•œ๋‹ค. (item.id)์™€ ๊ฐ™์ด ๊ณ ์œ ํ•œ ํ‚ค๋ฅผ ์ง€์ •ํ•ด์ฃผ๋ฉด ์„ฑ๋Šฅ ์ตœ์ ํ™”์— ๋„์›€์ด ๋œ๋‹ค.

<ul>
  {#each items as item (item.id)}
    <li>{item.name}</li>
  {:else}
    <li>ํ‘œ์‹œํ•  ํ•ญ๋ชฉ์ด ์—†์Šต๋‹ˆ๋‹ค.</li>
  {/each}
</ul>

๐Ÿ“™๋„์„œ ํ›„๊ธฐ

1์ฃผ์ฐจ์—๋Š” 2๋ถ€๊นŒ์ง€ ๊ณต๋ถ€ํ–ˆ๋‹ค. ์ด 512ํŽ˜์ด์ง€ ์ค‘ 2๋ถ€๋Š” 91ํŽ˜์ด์ง€๊นŒ์ง€์˜€๊ณ , Svelte ๊ฐœ๋ฐœ ํ™˜๊ฒฝ ์„ธํŒ…๊ณผ ๊ธฐ๋ณธ ๋ฌธ๋ฒ•์„ ๋‹ค๋ฃจ๋Š” ๋‚ด์šฉ์ด๋ผ ํฐ ์–ด๋ ค์›€์€ ์—†์—ˆ๋‹ค. ์ฝ์œผ๋ฉด์„œ ๊ถ๊ธˆํ•œ ์ ์„ ์ฐพ์•„๋ณด๊ณ  ์ •๋ฆฌํ•˜๋Š” ๋ฐ๊นŒ์ง€ 2์‹œ๊ฐ„์ด ์ฑ„ ๊ฑธ๋ฆฌ์ง€ ์•Š์•˜๋‹ค.

 

์ง€๊ธˆ๊นŒ์ง€ ๋А๋‚€ ์ ์€ ์„ค๋ช…์ด ์ •๋ง ์‰ฝ๋‹ค๋Š” ๊ฒƒ์ด๋‹ค. ๊ธฐ๋ณธ์ ์ธ ๋‚ด์šฉ์ด๋ผ ๊ทธ๋ ‡๊ฒŒ ๋А๊ปด์ง€๋Š” ๊ฑธ ์ˆ˜๋„ ์žˆ๊ฒ ์ง€๋งŒ, ์ฑ… ์ž์ฒด๊ฐ€ ๊ฐ€๋ณ๊ณ  ๋น ๋ฅด๊ฒŒ ์ฝํžˆ๋Š” ๋‚œ์ด๋„๋‹ค. (๋ฌผ๋ก  JavaScript์— ๋Œ€ํ•œ ๊ธฐ๋ณธ ์ง€์‹์ด ์žˆ๋‹ค๋Š” ์ „์ œํ•˜์—) ํ”„๋ก ํŠธ์—”๋“œ ํ”„๋ ˆ์ž„์›Œํฌ๋‚˜ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ๊ฒฝํ—˜์ด ์—†๋Š” ์‚ฌ๋žŒ๋„ ์ด ์ฑ…์œผ๋กœ๋ผ๋ฉด ๊ฝค ๋น ๋ฅด๊ฒŒ ๋ฐฐ์šธ ์ˆ˜ ์žˆ์„ ๊ฒƒ ๊ฐ™๋‹ค.

 

์ฑ•ํ„ฐ๋งˆ๋‹ค ํ€ด์ฆˆ์™€ ์‹ค์Šต ๋ฌธ์ œ๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ๊ณ , ๋ชฉ์ฐจ๊ฐ€ ๊ต‰์žฅํžˆ ์„ธ๋ถ„ํ™”๋˜์–ด ์žˆ๋‹ค๋Š” ์ ๋„ ๋งˆ์Œ์— ๋“ค์—ˆ๋‹ค. ์œ„์—์„œ ์ •๋ฆฌํ•œ ๋ฌธ๋ฒ•๋“ค์ด ์‚ฌ์‹ค ๋ชฉ์ฐจ๋ฅผ ๊ทธ๋Œ€๋กœ ์˜ฎ๊ธด ์ˆ˜์ค€์ธ๋ฐ, ๊ทธ๋งŒํผ ๋ฌธ๋ฒ• ํ•˜๋‚˜ํ•˜๋‚˜๊ฐ€ ๋…๋ฆฝ๋œ ์†Œ์ฃผ์ œ๋กœ ์ •๋ฆฌ๋ผ ์žˆ์–ด ํ•„์š”ํ•  ๋•Œ ๋’ค์ ์ด๊ธฐ ์ข‹์•˜๋‹ค.

 

React์™€ ๋‹ค๋ฅธ ์ ์ด ๋งŽ์•„์„œ ์กฐ๊ธˆ ํ—ท๊ฐˆ๋ฆฌ๋ฉด์„œ๋„, ์žฌ๋ฏธ์žˆ๋‹ค. ๋‹ค์Œ์ฃผ๋ถ€ํ„ฐ ์‹ค์Šต ํŒŒํŠธ ๊ณต๋ถ€ํ• ํ…๋ฐ ๋„ˆ๋ฌด ๊ธฐ๋Œ€๋œ๋‹ค.

'๐Ÿ“šbook' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€

[Luvit ํ•œ๋‹ฌ ์Šคํ„ฐ๋””] ์ƒˆ๋กœ์šด ์›น ๊ฐœ๋ฐœ์˜ ์‹œ์ž‘ ์Šค๋ฒจํŠธ #3  (1) 2025.07.20
[ํ˜ผ๊ณตํ•™์Šต๋‹จ 14๊ธฐ] ๊ฐ•์•„์ง€ ๊ณ ์–‘์ด ์‚ฌ์ง„ ๋ถ„๋ฅ˜ ์‹ค์Šต(AlexNet, VGGNet, ResNet)  (6) 2025.07.20
[ํ˜ผ๊ณตํ•™์Šต๋‹จ 14๊ธฐ] LeNet ์‹ค์Šต-Fashoin MNIST ๋ถ„๋ฅ˜ ์‹ค์Šต  (3) 2025.07.13
[Luvit ํ•œ๋‹ฌ ์Šคํ„ฐ๋””] ์ƒˆ๋กœ์šด ์›น ๊ฐœ๋ฐœ์˜ ์‹œ์ž‘ ์Šค๋ฒจํŠธ #2  (8) 2025.07.13
[ํ˜ผ๊ณตํ•™์Šต๋‹จ 14๊ธฐ] CNN ๊ตฌ์กฐ์™€ ๋™์ž‘ ์›๋ฆฌ์˜ ์ดํ•ด  (4) 2025.07.06
'๐Ÿ“šbook' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€
  • [ํ˜ผ๊ณตํ•™์Šต๋‹จ 14๊ธฐ] ๊ฐ•์•„์ง€ ๊ณ ์–‘์ด ์‚ฌ์ง„ ๋ถ„๋ฅ˜ ์‹ค์Šต(AlexNet, VGGNet, ResNet)
  • [ํ˜ผ๊ณตํ•™์Šต๋‹จ 14๊ธฐ] LeNet ์‹ค์Šต-Fashoin MNIST ๋ถ„๋ฅ˜ ์‹ค์Šต
  • [Luvit ํ•œ๋‹ฌ ์Šคํ„ฐ๋””] ์ƒˆ๋กœ์šด ์›น ๊ฐœ๋ฐœ์˜ ์‹œ์ž‘ ์Šค๋ฒจํŠธ #2
  • [ํ˜ผ๊ณตํ•™์Šต๋‹จ 14๊ธฐ] CNN ๊ตฌ์กฐ์™€ ๋™์ž‘ ์›๋ฆฌ์˜ ์ดํ•ด
ํ‚ํ‚์ž‰
ํ‚ํ‚์ž‰
๋ฟŒ๋ก ํŠธ ๊ฐœ๋ฐœ์ž(์ง€๋ง์ƒ)์˜ ํ’€์Šคํƒ ๊ฐœ๋ฐœ์ž ๋„์ „๊ธฐ
  • ํ‚ํ‚์ž‰
    monicx.dev
    ํ‚ํ‚์ž‰
  • ์ „์ฒด
    ์˜ค๋Š˜
    ์–ด์ œ
    • ๋ถ„๋ฅ˜ ์ „์ฒด๋ณด๊ธฐ (173)
      • ๐Ÿ–ฅ๏ธdevelop (2)
        • Github (2)
        • Frontend (4)
        • Backend (5)
        • Mobile (0)
        • CS (0)
        • Three.js (0)
        • Docker (2)
      • ๐Ÿ“šbook (9)
        • npm Deep Dive (4)
      • ๐Ÿ“•review (33)
        • ์ฑ… (24)
        • ํ–‰์‚ฌ (1)
        • ํšŒ๊ณ  (2)
      • โญproject (5)
        • petiary (2)
        • ๆšŽ่ฉ  (0)
        • ์ธํ„ด (2)
      • ๐Ÿ˜ถ‍๐ŸŒซ๏ธalgorithm (0)
      • ๐Ÿ’กtips (1)
      • ๐Ÿ˜Ždaily (10)
      • ๐Ÿ•น๏ธgame (0)
      • ๐Ÿ•Š๏ธํ”„๋กœ๊ทธ๋ž˜๋จธ์Šค ๋ฐ๋ธŒ์ฝ”์Šค (87)
        • TIL (61)
        • ํ”„๋กœ์ ํŠธ (18)
        • ํšŒ๊ณ  (8)
  • ๋ธ”๋กœ๊ทธ ๋ฉ”๋‰ด

    • ํ™ˆ
    • ํƒœ๊ทธ
  • ๋งํฌ

    • ๋ฒจ๋กœ๊ทธ
  • ์ธ๊ธฐ ๊ธ€

  • ์ตœ๊ทผ ๊ธ€

  • hELLOยท Designed By์ •์ƒ์šฐ.v4.10.3
ํ‚ํ‚์ž‰
[Luvit ํ•œ๋‹ฌ ์Šคํ„ฐ๋””] ์ƒˆ๋กœ์šด ์›น ๊ฐœ๋ฐœ์˜ ์‹œ์ž‘ ์Šค๋ฒจํŠธ #1
์ƒ๋‹จ์œผ๋กœ

ํ‹ฐ์Šคํ† ๋ฆฌํˆด๋ฐ”