Svelte

🌟 Svelte의 Context, Store 개념 완벽 가이드! 🌟

JANNNNNN 2024. 10. 26. 15:28

안녕하세요! 오늘은 Svelte에서 상태 관리를 어떻게 하는지에 대해 이야기해볼 거예요. Svelte의 스토어는 여러 컴포넌트에서 데이터를 공유하고 관리하는 데 매우 유용한 도구랍니다. 그럼 하나씩 알아볼까요? 😊

1. 부모 컴포넌트에서 자식 컴포넌트로 값 전달하기

부모 컴포넌트의 데이터를 자식 컴포넌트와 공유하고 싶을 때는 setContext와 getContext를 사용해요. 이 두 함수를 사용하면 아주 쉽게 데이터를 전달할 수 있어요.

1.1. setContext와 getContext 사용하기

  • setContext(key, value): 이 함수는 부모 컴포넌트에서 사용할 데이터와 키를 설정해요. 이때 key는 데이터에 접근하기 위한 고유한 식별자 역할을 하고, value는 공유하고자 하는 데이터입니다.
  • getContext(key): 자식 컴포넌트에서 호출하여 부모에서 설정한 값을 가져올 수 있어요. key를 통해 해당 값을 접근할 수 있어요.

예제

부모 컴포넌트 (Parent.svelte)

<script>
  import { setContext } from "svelte";
  // 'name'이라는 키로 '이름1'이라는 값을 설정
  setContext('name', '이름1');
</script>

<h1>부모 컴포넌트</h1>
<Child /> <!-- 자식 컴포넌트 호출 -->
  • 위 코드에서 setContext('name', '이름1')을 사용하여 부모 컴포넌트에서 'name'이라는 키로 '이름1'이라는 값을 설정했어요. 이제 자식 컴포넌트에서 이 값을 가져올 수 있습니다.

자식 컴포넌트 (Child.svelte)

<script>
  import { getContext } from "svelte";
  // 부모에서 설정한 'name' 값을 가져옴
  const name = getContext('name');
</script>

<h2>자식 컴포넌트에서 받은 이름: {name}</h2>

 

  • 자식 컴포넌트에서는 getContext('name')을 호출하여 부모에서 설정한 값을 가져옵니다. 이렇게 해서 name 변수에 '이름1'이라는 값이 할당되죠. 이제 {name}을 사용해 HTML에 출력할 수 있어요!

⭐부모에서 정의한 값을 자식에서도 공유하고 싶을때 사용하면 됩니다!

 

2. Svelte의 스토어 개념 이해하기

2.1. Writable Store

writable 스토어는 데이터를 읽고 쓸 수 있는 스토어예요. 상태를 쉽게 관리할 수 있도록 도와줍니다.

  • writable(initialValue): 초기값을 전달하여 스토어를 생성합니다. 이 스토어는 .subscribe(), .set(), .update() 메서드를 통해 상태를 변경할 수 있습니다.

예제

<script>
  import { writable } from "svelte/store";

  // count라는 writable 스토어를 생성하고 초기값을 0으로 설정
  const count = writable(0);

  function updateCount() {
    count.update(n => n + 1); // count의 값을 1 증가시키는 함수
  }

  // 스토어의 값이 변경될 때마다 알림을 표시
  count.subscribe(value => {
    alert(value);
  });

  count.set(12); // 스토어의 값을 12로 설정
</script>

<button type="button" on:click={updateCount}>Count Up!</button>

 

  • 위 코드에서는 count라는 스토어를 만들고, 버튼 클릭 시 updateCount 함수를 호출하여 count 값을 1 증가시키도록 했어요.
  • count.subscribe(value => {...})를 통해 스토어의 값이 변경될 때마다 알림을 표시합니다.
  • count.set(12)를 통해 스토어의 값을 직접 설정할 수도 있어요. 이렇게 하면 스토어의 상태가 변화하고, 구독하고 있는 모든 컴포넌트에 알림이 가게 됩니다!

2.2. 스토어를 별도 파일로 분리하기

실무에서는 보통 stores.js 파일을 따로 만들어서 스토어를 관리해요. 이렇게 하면 코드가 깔끔해지고 재사용이 쉬워진답니다.

예제

stores.js

import { writable } from "svelte/store";

export const count = writable(0); // count라는 writable 스토어를 생성

 

다른 컴포넌트에서 사용하기 (SomeComponent.svelte)

<script>
  import { count } from "./stores.js"; // stores.js에서 count 스토어를 가져옴

  function updateCount() {
    count.update(n => n + 1); // 스토어의 값을 1 증가
  }

  count.subscribe(value => {
    alert(value); // 값이 변경될 때마다 알림
  });
</script>

<button type="button" on:click={updateCount}>Count Up!</button>
  • stores.js에서 count 스토어를 정의하고, 다른 컴포넌트에서 import하여 사용합니다. 이렇게 하면 스토어의 상태를 다른 컴포넌트에서도 쉽게 관리하고 사용할 수 있어요. 🔄

2.3. 메모리 관리: 구독 해제

컴포넌트가 파괴될 때는 구독을 해제해주는 것이 중요해요. 이렇게 해야 메모리 누수를 방지할 수 있답니다!

예제

<script>
  import { onDestroy } from "svelte";
  import { count } from "./stores.js";

  function updateCount() {
    count.update(n => n + 1);
  }

  const unsub = count.subscribe(value => {
    alert(value);
  });

  onDestroy(unsub); // 컴포넌트가 파괴될 때 구독 해제
</script>

<button type="button" on:click={updateCount}>Count Up!</button>
  • onDestroy(unsub)을 사용하여 컴포넌트가 사라질 때 구독을 해제합니다. 이렇게 하면 스토어에 대한 구독이 해제되어 메모리 누수를 방지할 수 있어요. 📉

3. Readable Store

Readable Store란?

readable 스토어는 외부 데이터 소스와 연결하여 데이터를 제공합니다. 예를 들어, 현재 시간을 가져오는 스토어를 만들 수 있어요. 이 스토어는 자동으로 값을 업데이트하며, 구독을 통해 값의 변화를 감지할 수 있습니다.

3.1. Readable Store 사용하기

  • readable(initialValue, start): 초기값을 설정하고, 데이터가 변경될 때 실행할 함수를 제공하여 스토어를 생성합니다.

예제

stores.js

import { readable } from "svelte/store";

// 새로운 Date 객체를 초기값으로 하는 readable 스토어 생성
export const time = readable(new Date(), function start(set) {
  const interval = setInterval(() => {
    set(new Date()); // 1초마다 현재 시간을 업데이트
  }, 1000);

  return function stop() {
    clearInterval(interval); // 타이머 정리
  };
});

 

  • 위의 코드는 time이라는 readable 스토어를 생성합니다. 초기값으로 현재 시간을 설정하고, 1초마다 현재 시간을 업데이트합니다.
  • set 함수는 스토어의 값을 설정하는 데 사용되며, stop 함수는 스토어가 더 이상 필요하지 않을 때 타이머를 정리합니다.

3.2. Readable Store 사용하기

스토어의 값을 컴포넌트에서 쉽게 사용할 수 있습니다.

SomeComponent.svelte

<script>
  import { time } from "./stores.js"; // stores.js에서 time 스토어를 가져옴
</script>

<h2>현재 시간: {$time}</h2> <!-- 시간 값을 바인딩하여 출력 -->

 

  • 위의 예제에서는 time 스토어에서 현재 시간을 가져와서 화면에 출력합니다. $time을 사용하여 스토어의 값을 바인딩하고, 값이 변경될 때마다 자동으로 업데이트됩니다.

+ Writable Stroe vs Readable Store

1. Writable Store

  • 정의: writable 스토어는 외부에서 값을 읽고 쓸 수 있는 스토어입니다.
  • 값 설정: set() 메소드를 사용하여 값을 직접 설정할 수 있고, update() 메소드를 사용하여 현재 값에 기반해 값을 변경할 수 있습니다.
  • 사용 예: 주로 컴포넌트 간에 상태를 공유하거나, 사용자의 입력에 따라 값을 동적으로 변경해야 할 때 사용합니다.
import { writable } from "svelte/store";

export const count = writable(0); // 초기값 0인 writable 스토어 생성

function increment() {
  count.update(n => n + 1); // 값 증가
}

2. Readable Store

  • 정의: readable 스토어는 외부에서 값을 읽을 수만 있고, 값을 직접 쓸 수는 없는 스토어입니다. 일반적으로 외부 데이터 소스(예: API, 타이머)에서 가져온 데이터를 관리할 때 사용합니다.
  • 값 설정: set() 메소드가 제공되지만, 주로 내부에서 사용됩니다. 즉, 외부에서 이 스토어의 값을 변경할 수는 없습니다.
  • 사용 예: 데이터가 주기적으로 업데이트되는 경우(예: 현재 시간, API 응답) 주로 사용됩니다.
import { readable } from "svelte/store";

export const time = readable(new Date(), function start(set) {
  const interval = setInterval(() => {
    set(new Date()); // 1초마다 현재 시간을 업데이트
  }, 1000);

  return function stop() {
    clearInterval(interval); // 타이머 정리
  };
});

 

  • Writable Store는 상태 변경이 필요한 경우에 유용합니다. 예를 들어, 사용자 상호작용(버튼 클릭 등)에 따라 카운트를 변경할 수 있습니다.
  • Readable Store는 외부 데이터(예: 현재 시간)를 읽기만 할 때 적합합니다. 데이터가 자동으로 업데이트되므로 사용자가 직접 변경할 수 없고, 이를 통해 실시간 정보를 제공할 수 있습니다.

 

➡️ Writable Store는 데이터를 외부에서 직접 변경할 수 있는 경우에 사용하고, Readable Store는 외부에서 값을 읽기만 하고 변경할 수 없는 경우에 적합합니다. 이 두 스토어를 적절히 활용하여 Svelte 애플리케이션의 상태 관리를 효과적으로 할 수 있어요! 😊

4. Derived Store

Derived Store란?

derived 스토어는 기존의 스토어에서 파생된 새로운 스토어입니다. 예를 들어, 특정 시간의 경과 시간을 계산하는 스토어를 만들 수 있어요. 이 스토어는 원본 스토어의 값이 변경될 때마다 자동으로 업데이트됩니다.

4.1. Derived Store 사용하기

  • derived(store, callback): 하나의 스토어를 기반으로 새로운 스토어를 생성합니다. 첫 번째 인자로는 파생될 스토어를, 두 번째 인자로는 콜백 함수를 전달합니다.

예제

stores.js

import { derived } from "svelte/store";
import { time } from "./stores.js"; // 기존 time 스토어를 가져옴

const start = new Date();

// time 스토어를 기반으로 한 derived 스토어
export const elapsed = derived(time, $time => Math.round(($time.getTime() - start.getTime()) / 1000));
  • 위의 코드는 time 스토어를 기반으로 elapsed라는 derived 스토어를 생성합니다. 이 스토어는 time 스토어의 값이 변경될 때마다 경과 시간을 초 단위로 계산하여 제공합니다.

4.2. Derived Store 사용하기

이제 derived 스토어의 값을 컴포넌트에서 쉽게 사용할 수 있습니다.

AnotherComponent.svelte

<script>
  import { elapsed } from "./stores.js"; // stores.js에서 elapsed 스토어를 가져옴
</script>

<h2>경과 시간: {$elapsed}초</h2> <!-- 경과 시간을 바인딩하여 출력 -->
  • 위의 예제에서는 elapsed 스토어의 값을 가져와서 화면에 경과 시간을 출력합니다. $elapsed를 사용하여 스토어의 값을 바인딩하고, 값이 변경될 때마다 자동으로 업데이트됩니다.