본문으로 바로가기

[Svelte 시리즈] 컴포넌트와 스토어

category Front-End 2022. 2. 19. 00:58
반응형

이 포스트는 HEROPY 님 유튜브 Svelte 강좌를 보고 공부한 내용을 정리한 포스트입니다.

컴포넌트

Svelte에서는 Single File Component를 정의하고 사용할 수 있다.

  • Name.svelte
    • 컴포넌트 사용할 때 전달받을 데이터 (props)는 export 구문을 통해 선언한다
<script>
export let name
</script>

<h1>{name}</h1>
  • App.svelte
    • 사용 측에서 import 하여 컴포넌트를 가져온다.
    • props는 해당 컴포넌트 attribute를 통해 전달한다. (컴포넌트에서 export된 이름에 맞춤)
    • 전달하려는 prop의 이름과 데이터 변수명이 같다면 생략하여 작성할 수도 있다.
<script>
import Name from './Name.svelte';
let names = ['Tom', 'Mike', 'Elsa'];
let name = 'Another Tom';
</script>

{#each names as name}
<Name name={name} />
{/each}

<Name {name} />

컴포넌트내에서 데이터를 가공할 땐 원본 데이터에 영향이 없도록 작성하는 것이 중요하다.

만약 컴포넌트 내에서 데이터를 변경해야한다면 bind 키워드를 사용해 양방향 바인딩을 해주면 전달받은 prop을 변경할 수 있다.


스토어

만약 아래와 같은 상황을 가정해보자

  • App.svelte
<script>
import Parent from './Parent.svelte';
let name = 'Tom';
</script>

<Parent name={name} />
  • Parent.svelte
<script>
import Child from './Child.svelte';
export let name;
</script>

<div>
  Parent
</div>
<Child name={name} />
  • Child.svelte
<script>
export let name;
</script>

<div>
  Child {name}
</div>

App > Parent > Child 순으로 컴포넌트가 배치되어 있고, App에서 Child 컴포넌트로 데이터를 전달해야한다. 그럼 아래와 같은 코드가 되는데, 이 때 Parent 컴포넌트에서는 Child로 데이터 (name)을 전달하기 위해 본인은 사용하지않는 데이터를 선언해두고 받아서 전달하는 매개체 같은 역할을 해주어야한다.

이 정도 뎁스면 크게 다행이지만 컴포넌트 뎁스가 깊어지면 꽤나 큰 문제가 될 것 이다.

스토어는 이러한 문제점을 해결하기 위해 애플리케이션에서 사용되는 데이터를 한 곳에서 관리할 수 있도록 도와주는 데이터 저장소이다.

이 부분을 해결하기 위해 먼저 Svelte에서 제공하는 Store를 활용해 스토어를 작성해보자.

  • store.js
    • 스토어에서 export될 때의 이름으로 외부에서 참조할 수 있다.
    • 외부에서 값 변경이 가능하게 하려면 writable 함수를 사용해주어야한다.
    • writable 함수를 사용하고 초기값을 주면 name은 외부에서 값 참조, 변경이 가능한 스토어 객체가 된다.
    • Store가 외부라이브러리로 구성되어있는 타 프레임워크와 다르게 Svelte는 내장되어 있기 때문에 별도 의존성을 설치할 필요 없다.
import { writable } from 'svelte/store';
export let name = writable('');

위에서 export된 name은 writable함수에 의해 스토어 객체로 Wrapping된다.

스토어 객체는 set update subscribe 3가지 함수를 갖고 있고 이를 통해 값을 변경하고 사용할 수 있다.

set 함수는 스토어 객체에 값을 할당하는 함수이다.

update함수는 함수를 통해 스토어 객체의 값을 현재 값을 변경하는 함수이다.

subscribe는 현재 스토어의 값을 사용하는 함수 전달받아를 소비(consumer)시켜주는 함수이다.

<script>
import { name } from './store.js';

let nameValue;
// name 스토어의 값을 현재 컴포넌트의 nameValue에 할당시킴
name.subscribe(value => {
  nameValue = value;
});

// name 스토어의 값에 Hello World 문자열을 할당한다.
name.set('Hello World');

// name 스토어의 현재값에 !! 문자열을 붙힌다.
name.update(value => value + '!!');
</script>

<h1>{ nameValue }</h1>

위와 같은 함수들을 사용할 수 있지만 다소 불편한 부분이 있다.

Svelte에선 $ 키워드를 통해 스토어 데이터를 쉽게 다룰수 있다.

위 예시를 스토어를 사용한 코드로 변경해보자.

  • App.svelte
    • 스토어의 변수를 참조할 땐 스토어 파일의 export된 이름으로 참조한다.
    • 상술했듯 name은 일반 자료형 데이터가 아닌 스토어 객체이고 set, update, subscribe 함수를 사용해야하지만 $키워드를 통해 일반 변수처럼 사용할 수도 있다.
    • 이를 Svelte에선 Auto-Subscribe라고 부른다.
    • 이 때문에 Svelte에서는 변수앞에 $가 붙어있으면 스토에어 의해 관리되고 있는 데이터라는 의미이다.
<script>
import { name } from './store.js';
import Parent from './Parent.svelte';

$name = 'Tom';

</script>

<Parent />
  • Parent.svelte
    • 기존 코드에서 App에서 데이터를 받아 Child로 전달해주는 코드가 없어졌다.
<script>
import Child from './Child.svelte';
</script>

<div>
  Parent
</div>
<Child />
  • Child.svelte
    • props을 선언하는 코드 대신, 스토어에서 name 객체를 가져온다.
    • $name 으로 필요한 곳에 사용한다.
반응형