[Luvit ν•œλ‹¬ μŠ€ν„°λ””] μƒˆλ‘œμš΄ μ›Ή 개발의 μ‹œμž‘ 슀벨트 #2

2025. 7. 13. 21:41Β·πŸ“šbook
Luvit ν•œλ‹¬ μŠ€ν„°λ””

 

 

μ΄λ²ˆμ£ΌλŠ” 3λΆ€(9μž₯ 폼 κ΄€λ ¨ μš”μ†Œ 바인딩 ~ 14μž₯ μŠ€ν† μ–΄)λ₯Ό κ³΅λΆ€ν–ˆλ‹€.

 

✏️폼 κ΄€λ ¨ μš”μ†Œ 바인딩

바인딩

μƒνƒœκ°’κ³Ό κ·Έ 값을 μ œμ–΄ν•˜λŠ” μš”μ†Œλ₯Ό κ²°ν•©ν•˜λŠ” 것

바인딩은 bind: λ₯Ό μ‚¬μš©ν•˜μ—¬ HTML μš”μ†Œμ˜ κ°’κ³Ό Javascript λ³€μˆ˜λ₯Ό μžλ™μœΌλ‘œ λ™κΈ°ν™”ν•˜λŠ” 것이닀. 바인딩은 크게 단방ν–₯ 바인딩과 μ–‘λ°©ν–₯ 바인딩이 μžˆλ‹€.

 

  • 단방ν–₯ 바인딩:μš”μ†Œκ°€ μƒνƒœκ°’μ„ 직접 λ³€ν™”μ‹œν‚€μ§€ λͺ»ν•œλ‹€(props).
  • μ–‘λ°©ν–₯ 바인딩: μž…λ ₯κ³Ό 좜λ ₯이 λ™μ‹œμ— λ³€κ²½λ˜λ„λ‘ μ²˜λ¦¬ν•œλ‹€. 즉, μž…λ ₯ μƒμžμ— 값을 μž…λ ₯ν•˜λ©΄ 그와 μ—°κ²°λœ 값듀도 μžλ™μœΌλ‘œ μ—…λ°μ΄νŠΈλœλ‹€.

μŠ€λ²¨νŠΈμ—μ„œλŠ” 폼 데이터 μ œμ–΄ μ‹œ μ–‘λ°©ν–₯ 바인딩을 μ‚¬μš©ν•œλ‹€.μ‚¬μš©μžκ°€ μž…λ ₯ ν•„λ“œμ— 값을 μž…λ ₯ν•˜λ©΄ μ—°κ²°λœ λ³€μˆ˜κ°€ μ¦‰μ‹œ μ—…λ°μ΄νŠΈλ˜κ³ , λ°˜λŒ€λ‘œ λ³€μˆ˜κ°€ λ³€κ²½λ˜λ©΄ UIκ°€ μžλ™μœΌλ‘œ κ°±μ‹ λœλ‹€. μ΄λŠ” λ‹€λ₯Έ ν”„λ ˆμž„μ›Œν¬μ—μ„œ μˆ˜λ™μœΌλ‘œ 이벀트 λ¦¬μŠ€λ„ˆλ₯Ό μ„€μ •ν•˜κ³  μƒνƒœλ₯Ό 관리해야 ν–ˆλ˜ λ²ˆκ±°λ‘œμ›€μ„ 크게 쀄여쀀닀!

<νƒœκ·Έ μš”μ†Œ bind:νƒœκ·Έμ†μ„±={μƒνƒœκ°’} />

 

μž…λ ₯ μš”μ†Œ κ΄€λ ¨ 바인딩

λ‹€μ–‘ν•œ μž…λ ₯ μš”μ†Œ(ν…μŠ€νŠΈ, μ²΄ν¬λ°•μŠ€, λΌλ””μ˜€ λ²„νŠΌ λ“±)에 바인딩 속성을 μ‚¬μš©ν•  수 μžˆλ‹€.

SvelteλŠ” HTML μž…λ ₯ μš”μ†Œμ˜ νŠΉμ„±μ— 따라 μ„œλ‘œ λ‹€λ₯Έ 바인딩 속성을 μ œκ³΅ν•œλ‹€. ν…μŠ€νŠΈ μž…λ ₯μ—λŠ” bind:value, μ²΄ν¬λ°•μŠ€μ—λŠ” bind:checked, λΌλ””μ˜€ λ²„νŠΌμ—λŠ” bind:group을 μ‚¬μš©ν•œλ‹€. 이런 νƒ€μž…λ³„ 바인딩은 각 μš”μ†Œμ˜ λ„€μ΄ν‹°λΈŒ λ™μž‘μ„ κ·ΈλŒ€λ‘œ ν™œμš©ν•˜λ©΄μ„œλ„, μƒνƒœ 관리λ₯Ό λ‹¨μˆœν™”ν•œλ‹€.

<script>
  let text = '';
  let isChecked = false;
  let selectedOption = '';
  let textarea = '';
</script>

<input type="text" bind:value={text} />
<input type="checkbox" bind:checked={isChecked} />
<input type="radio" bind:group={selectedOption} value="option1" />
<input type="radio" bind:group={selectedOption} value="option2" />
<textarea bind:value={textarea}></textarea>

<div>
  <p>ν…μŠ€νŠΈ: {text}</p>
  <p>체크됨: {isChecked}</p>
  <p>μ„ νƒλœ μ˜΅μ…˜: {selectedOption}</p>
  <p>ν…μŠ€νŠΈ μ˜μ—­: {textarea}</p>
</div>

 

선택 μƒμž κ΄€λ ¨ 바인딩

select μš”μ†Œμ—μ„œ 단일 선택과 닀쀑 선택 λͺ¨λ‘ bind:value둜 μ²˜λ¦¬ν•  수 μžˆλ‹€.

Select μš”μ†Œμ˜ 바인딩은 단일 선택과 닀쀑 선택 λͺ¨λ“œμ— 따라 λ‹€λ₯΄κ²Œ λ™μž‘ν•œλ‹€. 단일 선택 λͺ¨λ“œμ—μ„œλŠ” μ„ νƒλœ 값이 λ¬Έμžμ—΄λ‘œ λ°”μΈλ”©λ˜κ³ , 닀쀑 선택 λͺ¨λ“œ(multiple 속성)μ—μ„œλŠ” μ„ νƒλœ 값듀이 λ°°μ—΄λ‘œ λ°”μΈλ”©λœλ‹€. 

<script>
  let selected = '';
  let multiSelected = [];
  let options = ['사과', 'λ°”λ‚˜λ‚˜', 'μ˜€λ Œμ§€', '포도'];
</script>

<!-- 단일 선택 -->
<select bind:value={selected}>
  <option value="">μ„ νƒν•˜μ„Έμš”</option>
  {#each options as option}
    <option value={option}>{option}</option>
  {/each}
</select>

<!-- 닀쀑 선택 -->
<select multiple bind:value={multiSelected}>
  {#each options as option}
    <option value={option}>{option}</option>
  {/each}
</select>

<p>μ„ νƒλœ ν•­λͺ©: {selected}</p>
<p>닀쀑 μ„ νƒλœ ν•­λͺ©: {multiSelected.join(', ')}</p>

닀쀑 선택 μ‹œμ—λŠ” ctrl + 클릭


πŸͺ’기타 μš”μ†Œ 바인딩

each 블둝 바인딩

반볡 블둝 λ‚΄μ—μ„œ 각 ν•­λͺ©μ˜ 속성을 κ°œλ³„μ μœΌλ‘œ λ°”μΈλ”©ν•˜μ—¬ λͺ©λ‘ 데이터λ₯Ό 효과적으둜 관리할 수 μžˆλ‹€

each 블둝 λ‚΄μ—μ„œ 바인딩을 ν•˜λ©΄ λͺ©λ‘μ˜ 각 ν•­λͺ©μ„ λ…λ¦½μ μœΌλ‘œ μ œμ–΄ν•  수 μžˆλ‹€. 각 ν•­λͺ©μ˜ μƒνƒœ λ³€ν™”κ°€ λ‹€λ₯Έ ν•­λͺ©μ— 영ν–₯을 μ£Όμ§€ μ•ŠμœΌλ©΄μ„œλ„ 전체 λͺ©λ‘μ˜ μƒνƒœλ₯Ό μ‹€μ‹œκ°„μœΌλ‘œ 좔적할 수 μžˆλ‹€.

<script>
  let items = [
    { id: 1, name: 'ν•­λͺ©1', completed: false },
    { id: 2, name: 'ν•­λͺ©2', completed: true },
    { id: 3, name: 'ν•­λͺ©3', completed: false }
  ];
</script>

{#each items as item}
  <div>
    <input type="checkbox" bind:checked={item.completed} />
    <input type="text" bind:value={item.name} />
    <span>{item.completed ? 'μ™„λ£Œ' : 'λ―Έμ™„λ£Œ'}</span>
  </div>
{/each}

<p>μ™„λ£Œλœ ν•­λͺ©: {items.filter(item => item.completed).length}</p>

 

λ©€ν‹°λ―Έλ””μ–΄ μš”μ†Œ 바인딩

λΉ„λ””μ˜€μ™€ μ˜€λ””μ˜€ μš”μ†Œμ˜ μž¬μƒ μƒνƒœ, λ³Όλ₯¨, μ§„ν–‰ μ‹œκ°„ 등을 λ°”μΈλ”©ν•˜μ—¬ μ»€μŠ€ν…€ λ―Έλ””μ–΄ ν”Œλ ˆμ΄μ–΄λ₯Ό κ΅¬ν˜„ν•  수 μžˆλ‹€.

 

읽기 μ „μš© 속성

속성 μ„€λͺ…
iduration 총 μž¬μƒ 길이(초)
buffered {start, end} κ°μ²΄λ“€μ˜ λ°°μ—΄λ‘œ, 버퍼 된 μœ„μΉ˜ ν‘œμ‹œ
seekable {start, end} κ°μ²΄λ“€μ˜ λ°°μ—΄λ‘œ, μœ„μΉ˜λ₯Ό 찾을 수 μžˆλŠ” λ²”μœ„ ν‘œμ‹œ
played {start, end} κ°μ²΄λ“€μ˜ λ°°μ—΄λ‘œ, μž¬μƒν–ˆλ˜ μœ„μΉ˜λ“€μ„ ν‘œμ‹œ
seeking μ°ΎλŠ” 쀑인지λ₯Ό true/false둜 ν‘œμ‹œ 
ended μž¬μƒμ΄ λλ‚¬λŠ”μ§€λ₯Ό true/false둜 ν‘œμ‹œ
videoWidth video νƒœκ·Έμ˜ λ„ˆλΉ„λ₯Ό λ‚˜νƒ€λƒ„(only video)
videoHeight video νƒœκ·Έμ˜ 높이λ₯Ό λ‚˜νƒ€λƒ„(only video)

 

읽고 μ“°κΈ° 속성

속성 μ„€λͺ…
currentTime ν˜„μž¬ μž¬μƒ μœ„μΉ˜(초)
playbackRate μž¬μƒ 속도
paused μΌμ‹œ μ •μ§€λλŠ”μ§€ true/false둜 ν‘œμ‹œ
volume μŒλŸ‰ 크기(0~1)

 

곡간 바인딩

μš”μ†Œμ˜ 크기와 μœ„μΉ˜ 정보λ₯Ό λ°”μΈλ”©ν•˜μ—¬ λ°˜μ‘ν˜• λ ˆμ΄μ•„μ›ƒ, 동적 UIλ₯Ό κ΅¬ν˜„ν•  수 μžˆλ‹€.

블둝 레벨의 μš”μ†Œ(div, h1 λ“±)듀은 clientWidth, clientHeight, offsetWidth, offsetHeightλ₯Ό 읽기 μ „μš© μ†μ„±μœΌλ‘œ 바인딩 ν•  수 μžˆλ‹€. 곡간 바인딩을 톡해 μš”μ†Œμ˜ 크기 변화에 λ”°λ₯Έ λ°˜μ‘ν˜• λ™μž‘μ„ κ΅¬ν˜„ν•˜κ±°λ‚˜, μš”μ†Œμ˜ μœ„μΉ˜λ₯Ό κΈ°λ°˜ν•œ μƒν˜Έμž‘μš©μ„ λ§Œλ“€ 수 있고, 특히 차트, κ·Έλž˜ν”„, 동적 λ ˆμ΄μ•„μ›ƒ λ“±μ—μ„œ μœ μš©ν•˜κ²Œ μ‚¬μš©λœλ‹€.

<script>
	let w;
	let h;
	let size = 20;
</script>

<p>κΈ€μž 크기λ₯Ό λ³€κ²½ν•΄λ³΄μ„Έμš”</p>
<input type = "range" bind:value={size} min="10" max="100"/>
<p>κΈ€μž 크기: {size}px</p>
<div bind:clientWidth={w} bind:clientHeight={h}>
	<span style = "font-size: {size}px">κΈ€μž</span>
</div>

 

bind:this 바인딩

DOM μš”μ†Œμ— 직접 μ ‘κ·Όν•˜μ—¬ λ„€μ΄ν‹°λΈŒ λ©”μ„œλ“œλ₯Ό ν˜ΈμΆœν•˜κ±°λ‚˜ 속성을 μ‘°μž‘ν•  수 μžˆλ‹€.

λ¦¬μ•‘νŠΈμ˜ ref 같은 κΈ°λŠ₯. 포컀슀 μ„€μ •, 슀크둀 μœ„μΉ˜ μ‘°μ •, μΊ”λ²„μŠ€ μ‘°μž‘ λ“± 직접적인 DOM μ‘°μž‘μ΄ ν•„μš”ν•œ μƒν™©μ—μ„œ μ“Έ 수 μžˆλ‹€. bind:thisλ₯Ό μ‚¬μš©ν•˜λ©΄ λͺ…령이 λ°œμƒν•˜λŠ” μΈμŠ€ν„΄μŠ€μ—μ„œλ§Œ μž‘λ™ν•˜κ²Œ ν•΄ μ „μ—­μ—μ„œ μ²˜λ¦¬λ˜λŠ” λ¬Έμ œκ°€ λ°œμƒν•˜μ§€ μ•ŠλŠ”λ‹€. μ»΄ν¬λ„ŒνŠΈ 생λͺ…μ£ΌκΈ°λ₯Ό κ³ λ €ν•΄μ„œ μ‚¬μš©ν•΄μ•Ό 함

<script>
  let inputElement;
  let canvasElement;
  let ctx;

  function focusInput() {
    inputElement.focus();
  }

  function drawOnCanvas() {
    if (canvasElement) {
      ctx = canvasElement.getContext('2d');
      ctx.fillStyle = 'red';
      ctx.fillRect(10, 10, 100, 100);
    }
  }
</script>

<input bind:this={inputElement} placeholder="ν΄λ¦­ν•˜μ—¬ 포컀슀" />
<button on:click={focusInput}>μž…λ ₯ ν•„λ“œ 포컀슀</button>

<canvas bind:this={canvasElement} width="200" height="200"></canvas>
<button on:click={drawOnCanvas}>μΊ”λ²„μŠ€μ— 그리기</button>

 

μ»΄ν¬λ„ŒνŠΈ 바인딩

μžμ‹ μ»΄ν¬λ„ŒνŠΈμ˜ λ³€μˆ˜λ‚˜ ν•¨μˆ˜λ₯Ό λΆ€λͺ¨ μ»΄ν¬λ„ŒνŠΈμ—μ„œ λ°”μΈλ”©ν•˜μ—¬ μ»΄ν¬λ„ŒνŠΈ κ°„ 톡신을 κ΅¬ν˜„ν•  수 μžˆλ‹€.

이전에 κ³΅λΆ€ν•œ propsλŠ” μžμ‹ μ»΄ν¬λ„ŒνŠΈκ°€ λΆ€λͺ¨ μ»΄ν¬λ„ŒνŠΈμ— 영ν–₯을 쀄 수 μ—†μ—ˆμ§€λ§Œ, μ»΄ν¬λ„ŒνŠΈ 바인딩 μ‹œ λΆ€λͺ¨μ™€ μžμ‹ μ»΄ν¬λ„ŒνŠΈ κ°„ μ–‘λ°©ν–₯ 톡신이 κ°€λŠ₯ν•΄μ§„λ‹€. μžμ‹ μ»΄ν¬λ„ŒνŠΈμ—μ„œ export둜 μ„ μ–Έλœ λ³€μˆ˜λ‚˜ ν•¨μˆ˜λ₯Ό λΆ€λͺ¨ μ»΄ν¬λ„ŒνŠΈμ—μ„œ 바인딩할 수 있고, 이λ₯Ό 톡해 μ»΄ν¬λ„ŒνŠΈ κ°„ μƒνƒœ 동기화와 λ©”μ„œλ“œ 호좜이 κ°€λŠ₯ν•˜λ‹€.

<!-- Child.svelte -->
<script>
  export let value = '';
  export let count = 0;
  
  export function reset() {
    value = '';
    count = 0;
  }
</script>

<input bind:value />
<button on:click={() => count++}>Count: {count}</button>

<!-- Parent.svelte -->
<script>
  import Child from './Child.svelte';
  
  let childValue = '';
  let childCount = 0;
  let childComponent;
</script>

<Child bind:value={childValue} bind:count={childCount} bind:this={childComponent} />

<p>μžμ‹ μ»΄ν¬λ„ŒνŠΈ κ°’: {childValue}</p>
<p>μžμ‹ μ»΄ν¬λ„ŒνŠΈ 카운트: {childCount}</p>
<button on:click={() => childComponent.reset()}>리셋</button>


🎰슀벨트 slot

slot은 μ»΄ν¬λ„ŒνŠΈ λ‚΄μš©(λ§ˆν¬μ—…)을 λ™μ μœΌλ‘œ μ£Όμž…ν•  수 μžˆλŠ” ν”Œλ ˆμ΄μŠ€ν™€λ” 역할을 ν•œλ‹€.

slot κΈ°λ³Έ μ‚¬μš©λ²•

slot은 React의 children props와 μœ μ‚¬ν•œ κΈ°λŠ₯으둜, μ»΄ν¬λ„ŒνŠΈλ₯Ό μž¬μ‚¬μš© κ°€λŠ₯ν•œ ν…œν”Œλ¦ΏμœΌλ‘œ λ§Œλ“€μ–΄μ€€λ‹€. λΆ€λͺ¨ μ»΄ν¬λ„ŒνŠΈμ—μ„œ μžμ‹ μ»΄ν¬λ„ŒνŠΈ νƒœκ·Έ 사이에 μž‘μ„±ν•œ λ‚΄μš©μ΄ slot μœ„μΉ˜μ— λ Œλ”λ§ λœλ‹€. slot을 μ‚¬μš©ν•˜μ—¬ λ ˆμ΄μ•„μ›ƒκ³Ό wrapper μ»΄ν°λ„ˆνŠΈλ₯Ό 효율적으둜 κ΅¬ν˜„ν•  수 μžˆλ‹€.

<!-- Card.svelte -->
<div class="card">
  <header>
    <h2>μΉ΄λ“œ 제λͺ©</h2>
  </header>
  <main>
    <slot></slot>
  </main>
  <footer>
    <p>μΉ΄λ“œ ν•˜λ‹¨</p>
  </footer>
</div>

<!-- App.svelte -->
<script>
  import Card from './Card.svelte';
</script>

<Card>
  <p>이 λ‚΄μš©μ΄ slot에 λ“€μ–΄κ°‘λ‹ˆλ‹€.</p>
  <button>μ•‘μ…˜ λ²„νŠΌ</button>
</Card>

  • <slot></slot>으둜 λ‚΄μš© μ‚½μž… μœ„μΉ˜λ₯Ό μ§€μ •ν•œλ‹€.
  • λΆ€λͺ¨ μ»΄ν¬λ„ŒνŠΈμ—μ„œ μžμ‹ νƒœκ·Έ 사이 λ‚΄μš©μ΄ slot에 λ Œλ”λ§λœλ‹€.

 

fallback slot

slot에 기본값을 μ œκ³΅ν•˜μ—¬ λ‚΄μš©μ΄ μ „λ‹¬λ˜μ§€ μ•Šμ„ λ•Œ ν‘œμ‹œλ  λŒ€μ²΄ 컨텐츠λ₯Ό μ§€μ •ν•  수 μžˆλ‹€.
<!-- Modal.svelte -->
<div class="modal">
  <div class="modal-content">
    <slot name="header">
      <h2>κΈ°λ³Έ 제λͺ©</h2>
    </slot>
    
    <slot>
      <p>λ‚΄μš©μ΄ μ—†μŠ΅λ‹ˆλ‹€.</p>
    </slot>
    
    <slot name="footer">
      <button>확인</button>
    </slot>
  </div>
</div>

<!-- App.svelte -->
<script>
  import Modal from './Modal.svelte';
</script>

<Modal>
  <p>λ‚΄μš©μ΄ μžˆμŠ΅λ‹ˆλ‹€.</p>
</Modal>

 

slot 이름 μ„€μ •

μ—¬λŸ¬κ°œμ˜ slot을 κ΅¬λΆ„ν•˜κΈ° μœ„ν•΄ name 속성을 μ‚¬μš©ν•΄ λͺ…λͺ…λœ slot을 λ§Œλ“€ 수 μžˆλ‹€.

λͺ…λͺ…λœ slot은 ν•˜λ‚˜μ˜ μ»΄ν¬λ„ŒνŠΈμ—μ„œ μ—¬λŸ¬ 개의 μ½˜ν…μΈ  μ˜μ—­μ„ μ •μ˜ν•  λ•Œ μ‚¬μš©λœλ‹€. 각 slot에 κ³ μœ ν•œ 이름을 λΆ€μ—¬ν•˜κ³ , λΆ€λͺ¨ μ»΄ν¬λ„ŒνŠΈμ—μ„œ slot 속성을 μ‚¬μš©ν•΄ νŠΉμ • slot에 λ‚΄μš©μ„ 전달할 수 μžˆλ‹€.

<!-- App.svelte -->
<script>
  import Layout from './Layout.svelte';
</script>

<Layout>
  <h1 slot="header">μ‚¬μ΄νŠΈ 제λͺ©</h1>
  <nav slot="sidebar">
    <a href="/">ν™ˆ</a>
    <a href="/tutorial">μ†Œκ°œ</a>
  </nav>
  <div>메인 μ½˜ν…μΈ </div>
  <p slot="footer">svelte</p>
</Layout>

<!-- Layout.svelte -->
<div class="layout">
  <header>
    <slot name="header"></slot>
  </header>
  
  <nav>
    <slot name="sidebar"></slot>
  </nav>
  
  <main>
    <slot></slot>
  </main>
  
  <footer>
    <slot name="footer"></slot>
  </footer>
</div>

 

slot props

slot에 데이터λ₯Ό μ „λ‹¬ν•˜μ—¬ λΆ€λͺ¨ μ»΄ν¬λ„ŒνŠΈμ—μ„œ μžμ‹ μ»΄ν¬λ„ŒνŠΈμ˜ 데이터λ₯Ό ν™œμš©ν•  수 μžˆλ‹€.

slot propsλŠ” μžμ‹ μ»΄ν¬λ„ŒνŠΈμ—μ„œ λΆ€λͺ¨ μ»΄ν¬λ„ŒνŠΈλ‘œ 데이터λ₯Ό μ „λ‹¬ν•˜λŠ” 방식이닀. μžμ‹ μ»΄ν¬λ„ŒνŠΈμ—μ„œ slot에 propsλ₯Ό μ „λ‹¬ν•˜λ©΄, λΆ€λͺ¨μ»΄ν¬λ„ŒνŠΈμ—μ„œ let:을 μ‚¬μš©ν•˜μ—¬ ν•΄λ‹Ή 데이터에 μ ‘κ·Όν•  수 μžˆλ‹€. 

<!-- ItemList.svelte -->
<script>
  export let items = [];
</script>

<div class="item-list">
  {#each items as item, index}
    <div class="item">
      <slot {item} {index} isFirst={index === 0} isLast={index === items.length - 1}>
        <p>{item.name}</p>
      </slot>
    </div>
  {/each}
</div>

<!-- App.svelte -->
<script>
  import ItemList from './ItemList.svelte';
  
  let items = [
    { name: 'ν•­λͺ© 1', price: 1000 },
    { name: 'ν•­λͺ© 2', price: 2000 },
    { name: 'ν•­λͺ© 3', price: 3000 }
  ];
</script>

<ItemList {items} let:item let:index let:isFirst let:isLast>
  <div class="custom-item" class:first={isFirst} class:last={isLast}>
    <h3>{item.name}</h3>
    <p>가격: {item.price}원</p>
    <p>μˆœμ„œ: {index + 1}</p>
  </div>
</ItemList>

 

쑰건 κ΄€λ ¨ slot

 μ‘°κ±΄λΆ€  slot은 νŠΉμ • μƒν™©μ—μ„œλ§Œ ν‘œμ‹œλ˜λŠ” slot을 κ΅¬ν˜„ν•˜κ±°λ‚˜, slot에 λ‚΄μš©μ΄ μ œκ³΅λ˜μ—ˆλŠ”μ§€ ν™•μΈν•˜μ—¬ λ ˆμ΄μ•„μ›ƒμ„ μ‘°μ •ν•  λ•Œ μ‚¬μš©λœλ‹€. $$slots 객체λ₯Ό 톡해 slot의 쑴재 μ—¬λΆ€λ₯Ό 확인할 수 μžˆλ‹€.


πŸŒ€λΌμ΄ν”„ 사이클

onMount ν•¨μˆ˜ 

μ»΄ν¬λ„ŒνŠΈκ°€ DOM에 마운트 된 ν›„ μ‹€ν–‰λ˜λŠ” ν•¨μˆ˜. μ΄ˆκΈ°ν™” μž‘μ—…μ„ μˆ˜ν–‰ν•  λ•Œ μ‚¬μš©ν•œλ‹€.

onMountλŠ” μ»΄ν¬λ„ŒνŠΈκ°€ 처음 DOM에 λ Œλ”λ§λœ ν›„ ν•œ 번만 μ‹€ν–‰λ˜λŠ” 라이프사이클 훅이닀. API 호좜, 이벀트 λ¦¬μŠ€λ„ˆ 등둝, 타이머 μ„€μ • λ“± μ»΄ν¬λ„ŒνŠΈ μ΄ˆκΈ°ν™”μ— ν•„μš”ν•œ μž‘μ—…μ„ μˆ˜ν–‰ν•  λ•Œ μ‚¬μš©λœλ‹€.

 

onDestroy ν•¨μˆ˜

μ»΄ν¬λ„ŒνŠΈκ°€ DOMμ—μ„œ 제거되기 μ „ μ‹€ν–‰λ˜λŠ” ν•¨μˆ˜λ‘œ, 정리 μž‘μ—…μ„ μˆ˜ν–‰ν•  λ•Œ μ‚¬μš©ν•œλ‹€.

onDestroyλŠ” μ»΄ν¬λ„ŒνŠΈκ°€ DOMμ—μ„œ 제거되기 직전에 μ‹€ν–‰λ˜λŠ” 라이프사이클 훅이닀. 이벀트 λ¦¬μŠ€λ„ˆ 제거, 타이머 정리, ꡬ독 ν•΄μ œ λ“± λ©”λͺ¨λ¦¬ λˆ„μˆ˜λ₯Ό λ°©μ§€ν•˜κ³  λ¦¬μ†ŒμŠ€λ₯Ό μ •λ¦¬ν•˜λŠ” μž‘μ—…μ— μ‚¬μš©λœλ‹€.

 

beforeUpdate/afterUpdate ν•¨μˆ˜

μ»΄ν¬λ„ŒνŠΈκ°€ μ—…λ°μ΄νŠΈ 되기 μ „, 후에 μ‹€ν•΄μ˜€λ””λŠ” ν•¨μˆ˜λ“€λ‘œ μ—…λ°μ΄νŠΈ 사이클을 μ œμ–΄ν•  λ•Œ μ‚¬μš©ν•œλ‹€.

beforeUpdateλŠ” μ»΄ν¬λ„ŒνŠΈμ˜ μƒνƒœκ°€ λ³€κ²½λ˜μ–΄ DOM이 μ—…λ°μ΄νŠΈλ˜κΈ° 직전에 μ‹€ν–‰λ˜κ³ , afterUpdateλŠ” DOM μ—…λ°μ΄νŠΈκ°€ μ™„λ£Œλœ 후에 μ‹€ν–‰λœλ‹€. 

 

tick ν•¨μˆ˜

λ‹€μŒ λ§ˆμ΄ν¬λ‘œνƒœμŠ€ν¬μ—μ„œ DOM이 μ—…λ°μ΄νŠΈ λ˜λ„λ‘ 보μž₯ν•˜λŠ” ν•¨μˆ˜. μƒνƒœ λ³€κ²½ ν›„ μ¦‰μ‹œ DOM에 μ ‘κ·Όν•  λ•Œ μ‚¬μš©ν•œλ‹€.

tick ν•¨μˆ˜λŠ” μƒνƒœ λ³€κ²½ ν›„ DOM μ—…λ°μ΄νŠΈκ°€ μ™„λ£Œλ  λ•ŒκΉŒμ§€ κΈ°λ‹€λ¦¬λŠ” Promiseλ₯Ό λ°˜ν™˜ν•œλ‹€. λ‹€λ₯Έ 라이프 사이클 ν•¨μˆ˜μ™€ 달리, μ–Έμ œλ“ μ§€ μ‚¬μš©ν•  수 μžˆλ‹€.


πŸ›©οΈContext API 

Context API 

μ»΄ν¬λ„ŒνŠΈ νŠΈλ¦¬μ—μ„œ propsλ₯Ό 일일이 μ „λ‹¬ν•˜μ§€ μ•Šκ³  데이터λ₯Ό κ³΅μœ ν•  수 μžˆλŠ” κΈ°λŠ₯

Context APIλŠ” λΆ€λͺ¨ μ»΄ν¬λ„ŒνŠΈμ—μ„œ μ„€μ •ν•œ 값을 μžμ† μ»΄ν¬λ„ŒνŠΈμ—μ„œ 직접 μ ‘κ·Όν•  수 있게 ν•˜λŠ” κΈ°λŠ₯이닀. 이λ₯Ό 톡해 props drilling 문제λ₯Ό ν•΄κ²°ν•˜κ³ , ν…Œλ§ˆ, μ‚¬μš©μž 정보, μ„€μ • λ“± μ „μ—­μ μœΌλ‘œ ν•„μš”ν•œ 데이터λ₯Ό 효율적으둜 관리할 수 μžˆλ‹€.

 

μƒμœ„ μ»΄ν¬λ„ŒνŠΈμ—μ„œ setComponentλ₯Ό μ‚¬μš©ν•˜μ—¬ 데이터λ₯Ό μ„€μ •ν•˜κ³ , ν•˜μœ„ μ»΄ν¬λ„ŒνŠΈμ—μ„œλŠ” getContextλ₯Ό μ‚¬μš©ν•˜μ—¬ ν•΄λ‹Ή 데이터λ₯Ό κ°€μ Έμ˜€λŠ” 것이 context API μ‚¬μš©μ˜ κΈ°λ³Έ νŒ¨ν„΄μ΄λ‹€.

 

dispatch

μžμ‹ μ»΄ν¬λ„ŒνŠΈμ—μ„œ λΆ€λͺ¨ μ»΄ν¬λ„ŒνŠΈλ‘œ 이벀트λ₯Ό μ „λ‹¬ν•˜λŠ” κΈ°λŠ₯

createEventDispatcher을 μ‚¬μš©ν•΄ μ»€μŠ€ν…€ 이벀트λ₯Ό μƒμ„±ν•˜κ³ , λΆ€λͺ¨ μ»΄ν¬λ„ŒνŠΈμ—κ²Œ 전달할 수 μžˆλ‹€. 

import {createEventDispatcher} from 'svelte';
const dispatch = createEventDispatcher();

const μ΄λ²€νŠΈν•¨μˆ˜ = () => {
	dispatch('λ””μŠ€νŒ¨μΉ˜λͺ…', {
    	value: 전달할 κ°’,
        message: '전달할 λ©”μ‹œμ§€'
    });
}

//λ§ˆν¬μ—…
<μ»΄ν¬λ„ŒνŠΈλͺ… on:λ””μŠ€νŒ¨μΉ˜λͺ… />

πŸͺμŠ€ν† μ–΄

μ „μ—­μ—μ„œ 데이터λ₯Ό 전달받고 μ‹Άκ±°λ‚˜, 데이터 변경을 μš”μ²­ν•  λ•Œ μ‚¬μš©

writable μŠ€ν† μ–΄

읽기, μ“°κΈ° λͺ¨λ‘ κ°€λŠ₯ν•œ λ°˜μ‘ν˜• μƒνƒœ μ €μž₯μ†Œ

writable μŠ€ν† μ–΄λŠ” svelte의 κ°€μž₯ 기본적인 μŠ€ν† μ–΄ νƒ€μž…μœΌλ‘œ, 값을 μ €μž₯ν•˜κ³  λ³€κ²½ν•  수 있고, 값이 변경될 λ•Œ κ΅¬λ…μžλ“€μ—κ²Œ μžλ™μœΌλ‘œ μ•Œλ¦Όμ„ 보낸닀.

import {writable} from 'svelte/store';
export const μŠ€ν† μ–΄λͺ… = writable(κΈ°λ³Έκ°’);

//λ§ˆν¬μ—…
{$μŠ€ν† μ–΄λͺ…}

 

readable μŠ€ν† μ–΄

읽기 μ „μš© μŠ€ν† μ–΄λ‘œ, μ™ΈλΆ€μ—μ„œ 값을 λ³€κ²½ν•  수 μ—†κ³  λ‚΄λΆ€ λ‘œμ§μ— μ˜ν•΄μ„œλ§Œ 값이 μ—…λ°μ΄νŠΈλœλ‹€.

readable μŠ€ν† μ–΄λŠ” μ‹œκ°„, 마우슀 μœ„μΉ˜, μ„œλ²„ μƒνƒœ λ“± μ™ΈλΆ€ μ‹œμŠ€ν…œμœΌλ‘œλΆ€ν„° μ˜€λŠ” 데이터λ₯Ό λ‹€λ£° λ•Œ μ‚¬μš©ν•œλ‹€. κ΅¬λ…μžκ°€ μžˆμ„ λ•Œλ§Œ ν™œμ„±ν™”λ˜λŠ” ꡬ쑰λ₯Ό κ°€μ§€κ³  μžˆλ‹€.

readable(μ΄ˆκΈ°κ°’, function start (set) {
	//초기 μŠ€ν† μ–΄κ°’ 호좜 μ‹œ μ½”λ“œ
    return function stop() {
    	//μŠ€ν† μ–΄κ°’ 제거 μ‹œ μ½”λ“œ
    };
});

 

derived μŠ€ν† μ–΄

ν•˜λ‚˜ μ΄μƒμ˜ μŠ€ν† μ–΄λ‘œλΆ€ν„° κ³„μ‚°λœ 값을 μ œκ³΅ν•˜λŠ” μŠ€ν† μ–΄

derived μŠ€ν† μ–΄λŠ” κΈ°μ‘΄ μŠ€ν† μ–΄μ˜ 값을 기반으둜 μƒˆλ‘œμš΄ 값을 κ³„μ‚°ν•˜λŠ” μŠ€ν† μ–΄μ΄λ‹€. 원본 μŠ€ν† μ–΄κ°€ 변경될 λ•Œ μžλ™μœΌλ‘œ μž¬κ³„μ‚°λœλ‹€.

import {λ‹€λ₯Έ μŠ€ν† μ–΄, derived} from 'svelte/store';

export const derivedλͺ… = derived(κΈ°μ‘΄ μŠ€ν† μ–΄λͺ…, $κΈ°μ‘΄ μŠ€ν† μ–΄λͺ… => $κΈ°μ‘΄ μŠ€ν† μ–΄λͺ…(λ³€κ²½ μ½”λ“œ λ°˜ν™˜));

 

μ»€μŠ€ν…€ μŠ€ν† μ–΄

writeable μŠ€ν† μ–΄λ₯Ό ν™•μž₯ν•˜μ—¬ νŠΉλ³„ν•œ λ©”μ„œλ“œλ₯Ό κ°€μ§„ μ‚¬μš©μž μ •μ˜ μŠ€ν† μ–΄λ₯Ό λ§Œλ“€ 수 μžˆλ‹€.

μ»€μŠ€ν…€ μŠ€ν† μ–΄λŠ” κΈ°λ³Έ μŠ€ν† μ–΄μ˜ set, update, subscribe λ©”μ„œλ“œ 외에 도메인 νŠΉν™”λœ λ©”μ„œλ“œλ₯Ό μΆ”κ°€ν•œ μŠ€ν† μ–΄μ΄λ‹€. μ»€μŠ€ν…€ μŠ€ν† μ–΄λ₯Ό 톡해 더 직관적이고 μž¬μ‚¬μš© κ°€λŠ₯ν•œ μƒνƒœ 관리 λ‘œμ§μ„ κ΅¬ν˜„ν•  수 μžˆλ‹€.

//store.js
import {writable} from 'svelte/store';

const createCount = () => {
	const {subscribe, set, update} = writable(0);
    
    return {
    	subscribe,
        increment: () => update(n => n + 1),
        decrement: () => update(n => n - 1),
        reset: () => set(0)
    };
 }
 
 export const count = createCount();
 
 <!--Custom.svelte-->
 <script>
 	import {count} from './store.js';
 </script>
 
 <h1>ν˜„μž¬ κ°’: {$count} </h1>
 <button on:click={count.increment}>+</button>
 <button on:click={count.decrement}>-</button>
 <button on:click={count.reset}>리셋</button>
 
 <!--App.svelte-->
  <script>
 	import Custom from './Custom.svelte';
 </script>
 
 <Custom />

 

μŠ€ν† μ–΄ 바인딩

μž…λ ₯ μš”μ†Œμ™€ μŠ€ν† μ–΄λ₯Ό 직접 λ°”μΈλ”©ν•˜μ—¬ μ–‘λ°©ν–₯ 데이터 흐름을 κ΅¬ν˜„ν•  수 μžˆλ‹€.

μŠ€ν† μ–΄ 바인딩은 μž…λ ₯ μš”μ†Œμ™€ μŠ€ν† μ–΄λ₯Ό 직접 μ—°κ²°ν•˜μ—¬ μ‚¬μš©μž μž…λ ₯이 μŠ€ν† μ–΄μ— μ¦‰μ‹œ λ°˜μ˜λ˜λ„λ‘ ν•˜λŠ” κΈ°λŠ₯이닀. μ „μ—­ μƒνƒœμ™€ UI μš”μ†Œ κ°„ 동기화λ₯Ό μ‰½κ²Œ κ΅¬ν˜„ν•  수 μž‡λ‹€. writable μŠ€ν† μ–΄λ₯Ό 써야 ν•˜κ³ , set ν•¨μˆ˜κ°€ ν•„μš”ν•˜λ‹€.

<!--store.js-->
import {writable, derived} from 'svelte/store';

export const name = writable('이름');
export const greeting = derived(
	name,
    $name => `μ•ˆλ…•~ ${$name}~`
);

<!--Binding.svelte-->
<script>
	import {name, greeting} from './store.js';
</script>

<h1>{$greeting}</h1>
<input bind:value={$name}>

<!--App.svelte-->
<script>
	import Binding from './Binding.svelte';
</script>

<Binding />


이번 μ£Όμ°¨λΆ€ν„°λŠ” μ‹€μŠ΅ 파트 λ“€μ–΄κ°ˆ 쀄 μ•Œμ•˜λŠ”λ°...ν•œμ°Έ λ‚¨μ•˜λ‹€. μΉ΄λ“œ λ‚˜λˆ„λŠ” 것 마λƒ₯ λŒ€κ°• 4λ“±λΆ„ ν•΄λ†¨λ”λ‹ˆ λ‹€μŒμ£Όμ— 이둠 + μ‹€μŠ΅κΉŒμ§€ ν• κ²Œ λ„ˆλ¬΄ λ§Žμ•„μ‘Œλ‹€..

 

μ˜€λŠ˜μ€ 바인딩뢀터 라이프 사이클, μŠ€ν† μ–΄κΉŒμ§€ μ’€ 심화적인 κ°œλ…μ„ κ³΅λΆ€ν–ˆλ‹€. μ™„μ „νžˆ μƒμ†Œν•œ κ°œλ…μ€ μ•„λ‹ˆμ–΄μ„œ μ΄ν•΄ν•˜λŠ”λ° μ–΄λ ΅μ§„ μ•Šμ•˜λŠ”λ°, 아직 μ–΄λ–»κ²Œ ν™œμš©ν• μ§€ μ• λ§€ν•œ λŠλ‚Œμ΄λ‹€πŸ™„λΉ¨λ¦¬ μ‹€μŠ΅ν•˜λ©΄μ„œ 감을 μ΅ν˜€λ΄μ•Όμ§€

'πŸ“šbook' μΉ΄ν…Œκ³ λ¦¬μ˜ λ‹€λ₯Έ κΈ€

[Luvit ν•œλ‹¬ μŠ€ν„°λ””] μƒˆλ‘œμš΄ μ›Ή 개발의 μ‹œμž‘ 슀벨트 #3  (1) 2025.07.20
[ν˜Όκ³΅ν•™μŠ΅λ‹¨ 14κΈ°] κ°•μ•„μ§€ 고양이 사진 λΆ„λ₯˜ μ‹€μŠ΅(AlexNet, VGGNet, ResNet)  (6) 2025.07.20
[ν˜Όκ³΅ν•™μŠ΅λ‹¨ 14κΈ°] LeNet μ‹€μŠ΅-Fashoin MNIST λΆ„λ₯˜ μ‹€μŠ΅  (3) 2025.07.13
[ν˜Όκ³΅ν•™μŠ΅λ‹¨ 14κΈ°] CNN ꡬ쑰와 λ™μž‘ μ›λ¦¬μ˜ 이해  (4) 2025.07.06
[Luvit ν•œλ‹¬ μŠ€ν„°λ””] μƒˆλ‘œμš΄ μ›Ή 개발의 μ‹œμž‘ 슀벨트 #1  (5) 2025.07.06
'πŸ“šbook' μΉ΄ν…Œκ³ λ¦¬μ˜ λ‹€λ₯Έ κΈ€
  • [ν˜Όκ³΅ν•™μŠ΅λ‹¨ 14κΈ°] κ°•μ•„μ§€ 고양이 사진 λΆ„λ₯˜ μ‹€μŠ΅(AlexNet, VGGNet, ResNet)
  • [ν˜Όκ³΅ν•™μŠ΅λ‹¨ 14κΈ°] LeNet μ‹€μŠ΅-Fashoin MNIST λΆ„λ₯˜ μ‹€μŠ΅
  • [ν˜Όκ³΅ν•™μŠ΅λ‹¨ 14κΈ°] CNN ꡬ쑰와 λ™μž‘ μ›λ¦¬μ˜ 이해
  • [Luvit ν•œλ‹¬ μŠ€ν„°λ””] μƒˆλ‘œμš΄ μ›Ή 개발의 μ‹œμž‘ 슀벨트 #1
ν‚ν‚μž‰
ν‚ν‚μž‰
뿌둠트 개발자(지망생)의 ν’€μŠ€νƒ 개발자 도전기
  • ν‚ν‚μž‰
    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 ν•œλ‹¬ μŠ€ν„°λ””] μƒˆλ‘œμš΄ μ›Ή 개발의 μ‹œμž‘ 슀벨트 #2
μƒλ‹¨μœΌλ‘œ

ν‹°μŠ€ν† λ¦¬νˆ΄λ°”