컴포넌트 재귀 호출(self)

이번 시간에는 svelte의 특별한 요소인 self에 대해 알아본다. 아래 예제를 보자

App.svelte

<script>
  import Address from "./Address.svelte";

	let address = {
    label: "대한민국",
    children: [
      { label: "경기도", children: [{ label: "수원" }, { label: "성남" }] },
      { label: "강원도", children: [{ label: "속초" }, { label: "강릉" }] },
    ],
  };
</script>

<Address {address} />

Address.svelte

<script>
  export let address;
</script>

<ul>
  <li>
    {address.label}
    {#if address.children}
      {#each address.children as address}
        <svelte:self {address} />
      {/each}
    {/if}
  </li>
</ul>

App 컴포넌트에서 address 변수의 주소 객체가 담겨있고 이를 Address 컴포넌트로 데이터를 내려주고 있다. Address 컴포넌트는 전달받은 address 데이터로 데이터를 렌더링 하는데, 이를 svelte의 self 요소를 사용하는 컴포넌트에 렌더링 한다.

스크린샷 2022-08-19 오후 6.29.35.png

이 self 요소는 재귀(resursion) 호출을 의미하는데, 재귀는 자기 내부에서 자기 자신을 호출하는 것을 의미함. 즉 svelte:self란 Address 컴포넌트를 재귀적으로 자기 자신을 호출한다는 의미이다. 재귀 호출은 반드시 종료 조건이 있어야 하며, address.children이 있을 때에만 재귀 호출이 일어나도록 처리한다는 로직이 제한 조건임을 알 수 있다.

스벨트의 컴포넌트는 동적 렌더링이 가능하다. 아래 코드를 보며 자세히 살펴보자.

동적 컴포넌트 렌더링(component)

App.svelte

<script>
  import Jinny from "./Jinny.svelte";
  import Wonny from "./Wonny.svelte";

  let components = [{ name: "Jinny" }, { name: "Wonny" }];
  let selected;
</script>

{#each components as { name } (name)}
  <label>
    <input type="radio" value={name} bind:group={selected} />
    {name}
  </label>
{/each}

{#if selected === "Jinny"}
  <Jinny />
{:else if selected === "Wonny"}
  <Wonny />
{/if}

Jinny.svelte

<h2>Jinny!</h2>

Wonny.svelte

<h2>Wonny?</h2>

App 컴포넌트는 components 라는 데이터를 바탕으로 각 radio 인풋 데이터를 노출하도록 구성되어있다. 선택된 결과에 따라 Jinny 혹은 Wonny 컴포넌트를 렌더링하도록 되어있는 구조인데, 만약 해당 데이터가 늘어난다면 위와 같이 같은 반복적인 컴포넌트를 모두 만들고, 이를 if 분기문에서 모두 체크하도록 구현하는 방법이 최선일까?

아님. 스벨트의 요소(태그)를 만들면 쉽게 동적 렌더링 구현이 가능하다.

App.svelte