Svelte에서 Melt UI로 접을 수 있는 컴포넌트 만들기

발행: (2026년 1월 6일 오후 05:50 GMT+9)
10 min read
원문: Dev.to

Source: Dev.to

Melt UI Collapsible 가이드

Melt UI는 WAI‑ARIA 가이드라인을 따르는 Svelte용 헤드리스이며 접근 가능한 컴포넌트 빌더를 제공합니다. Collapsible 빌더를 사용하면 기본 제공되는 전체 키보드 내비게이션 및 스크린 리더 지원과 함께 확장/축소 가능한 콘텐츠 섹션을 만들 수 있습니다.

이 가이드는 Melt UI의 createCollapsible 빌더를 사용한 실용적이고 프로덕션 준비가 된 콜래퍼시블 컴포넌트 구현 과정을 단계별로 안내합니다. 추상화가 아닌 실제 사용 패턴에 초점을 맞춥니다.

왜 Svelte와 함께 @melt-ui/svelte (Melt UI)를 사용해야 할까요?

Svelte 애플리케이션은 FAQ, 아코디언, 네비게이션 메뉴, 상세 뷰 등에서 확장 가능한 콘텐츠 섹션이 자주 필요합니다. Melt UI의 Collapsible 빌더는 다음과 같은 이유로 이 생태계에 자연스럽게 맞습니다:

  • 완전한 WAI‑ARIA 준수를 통한 접근성 보장
  • 헤드리스 디자인 (스타일은 직접 제어)
  • 뛰어난 타입 안전성을 제공하는 TypeScript 지원
  • 간단하고 선언적인 API
  • 내장된 키보드 내비게이션
  • Svelte 외에 외부 의존성 없음

빌더 패턴을 사용하면 원하는 어떤 요소에도 collapsible 동작을 연결할 수 있어 마크업과 스타일을 완전히 제어할 수 있습니다.

요구 사항

시작하기 전에, 다음을 준비하세요:

  • Svelte 프로젝트 (SvelteKit 또는 독립형 Svelte)
  • Node.js 16+ 및 npm/pnpm/yarn
  • Svelte 컴포넌트와 스토어에 대한 기본적인 친숙함

설치

Install Melt UI using your preferred package manager:

npm install @melt-ui/svelte
# or
pnpm add @melt-ui/svelte
# or
yarn add @melt-ui/svelte

The package includes all builders and their TypeScript definitions.

구성

추가 설정이 필요하지 않습니다. Melt UI는 Svelte와 바로 사용할 수 있습니다. TypeScript를 사용 중이라면 tsconfig.json에 올바른 모듈 해석이 포함되어 있는지 확인하십시오:

{
  "compilerOptions": {
    "moduleResolution": "bundler",
    "target": "ES2020"
  }
}

기본 사용법

가장 간단한 방법은 createCollapsible 빌더를 사용하는 것입니다:

<script>
  import { createCollapsible, melt } from '@melt-ui/svelte';

  const {
    elements: { root, content, trigger },
    states: { open }
  } = createCollapsible();
</script>

<div use:melt={root}>
  <button use:melt={trigger}>
    {$open ? 'Close' : 'Open'}
  </button>

  <div use:melt={content}>
    This content can be expanded and collapsed.
  </div>
</div>

createCollapsible()가 반환하는 것

  • elementsroot, content, trigger 요소에 대한 Svelte 스토어.
  • states – 접힌 상태를 추적하는 open 같은 반응형 스토어.

melt 액션을 사용하여 빌더의 동작을 요소에 연결합니다. open 스토어는 반응형이며, 접힌 상태가 변경될 때 자동으로 업데이트됩니다.

Source:

고급 기능

Tailwind CSS로 스타일링

Melt UI는 헤드리스이기 때문에 스타일링을 완전히 제어할 수 있습니다:

<script>
  import { createCollapsible, melt } from '@melt-ui/svelte';

  const {
    elements: { root, content, trigger },
    states: { open }
  } = createCollapsible();
</script>

<div use:melt={root} class="border rounded">
  <button use:melt={trigger} class="px-4 py-2 bg-gray-200">
    Toggle Content <span class="ml-2">▼</span>
  </button>

  <div use:melt={content} class="p-4">
    This is the collapsible content area.
  </div>
</div>

제어된 상태

외부에서 콜랩시블 상태를 제어하려면 writable 스토어를 전달합니다:

<script>
  import { createCollapsible, melt } from '@melt-ui/svelte';
  import { writable } from 'svelte/store';

  const isOpen = writable(false);

  const {
    elements: { root, content, trigger },
    states: { open }
  } = createCollapsible({ open: isOpen });

  function toggle() {
    isOpen.update(n => !n);
  }
</script>

<div use:melt={root}>
  <button use:melt={trigger} on:click={toggle}>
    {$open ? 'Close' : 'Open'}
  </button>

  <div use:melt={content}>
    Controlled content
  </div>
</div>

아코디언 만들기

여러 콜랩시블 상태를 관리하여 아코디언을 구축합니다:

<script>
  import { createCollapsible, melt } from '@melt-ui/svelte';
  import { writable } from 'svelte/store';

  const openIndex = writable(null);

  const items = [
    { id: 1, title: 'Item 1', content: 'Content for item 1' },
    { id: 2, title: 'Item 2', content: 'Content for item 2' },
    { id: 3, title: 'Item 3', content: 'Content for item 3' }
  ];

  function createItemCollapsible(index) {
    const isOpen = writable(openIndex.get() === index);

    const unsubscribe = openIndex.subscribe(value => {
      isOpen.set(value === index);
    });

    return {
      collapsible: createCollapsible({ open: isOpen }),
      unsubscribe
    };
  }
</script>

{#each items as item, index}
  {@const { collapsible, unsubscribe } = createItemCollapsible(index)}
  {@const { elements: { root, content, trigger }, states: { open } } = collapsible}

  <div use:melt={root} class="border-b">
    <button
      use:melt={trigger}
      on:click={() => openIndex.set($open ? null : index)}
      class="w-full px-4 py-2 text-left"
    >
      {item.title}
    </button>

    {#if $open}
      <div use:melt={content} class="p-4">
        {item.content}
      </div>
    {/if}
  </div>
{/each}

커스텀 애니메이션

Svelte의 전환 지시자를 사용해 애니메이션을 추가합니다:

<script>
  import { createCollapsible, melt } from '@melt-ui/svelte';
  import { slide } from 'svelte/transition';

  const {
    elements: { root, content, trigger },
    states: { open }
  } = createCollapsible();
</script>

<div use:melt={root}>
  <button use:melt={trigger}>
    {$open ? 'Hide' : 'Show'} details
  </button>

  {#if $open}
    <div use:melt={content} transition:slide>
      Animated collapsible content.
    </div>
  {/if}
</div>

결론

Melt UI의 헤드리스이며 접근 가능한 Collapsible 빌더는 Svelte에서 완전히 맞춤화된 ARIA‑준수 확장 섹션을 만들 수 있는 유연성을 제공합니다. 빌더 패턴을 활용함으로써 마크업, 스타일링 및 상태 관리에 대한 완전한 제어를 유지하면서 내장된 접근성 및 키보드 지원의 혜택을 누릴 수 있습니다. 즐거운 코딩 되세요!

<script>
  import { createCollapsible, melt } from '@melt-ui/svelte';
  import { slide } from 'svelte/transition';

  const {
    elements: { root, content, trigger },
    states: { open }
  } = createCollapsible();
</script>

<div use:melt={root}>
  <button use:melt={trigger}>Toggle</button>

  {#if $open}
    <div use:melt={content} transition:slide>
      This content slides in and out.
    </div>
  {/if}
</div>

전체 화면 제어

  • 전체 화면 모드 진입
  • 전체 화면 모드 종료

일반적인 문제 / 트러블슈팅

Collapsible doesn’t toggle

  • melt 액션이 세 요소 모두(root, trigger, content)에 적용되었는지 확인하세요.
  • 스토어에 접근할 때 $ 접두사를 사용했는지 확인하세요: $open.
  • 빌더가 컴포넌트 초기화 시 한 번만 호출되는지 확인하세요(조건부로 호출되지 않도록).

Accessibility attributes missing

  • melt 액션이 요소에 적용되어 있고 조건부 렌더링으로 인해 제거되지 않았는지 확인하세요.
  • ARIA 속성을 수동으로 추가하지 마세요 – 빌더가 자동으로 처리합니다.

TypeScript errors

  • 필요할 때 @melt-ui/svelte에서 타입을 가져오세요.
  • 최상의 TypeScript 지원을 위해 Svelte **v4+**를 사용하세요.

Content not animating

  • {#if} 조건부 렌더링을 사용할 경우 melt 액션이 계속 적용되어 있는지 확인하세요.
  • Svelte 전환(transition:slide 등)은 content 요소에 적용하고, root 요소에는 적용하지 마세요.

프로덕션 모범 사례

  • 접근성을 보장하기 위해 모든 빌더 요소melt 액션을 항상 사용하세요.
  • 키보드 탐색(Tab, Enter, Space, Escape)을 테스트하세요.
  • 스크린 리더로 ARIA 속성을 확인하세요.
  • 스타일링은 로직과 분리하세요 – Melt UI는 동작을 처리하고, 여러분은 외관을 담당합니다.
  • 더 나은 성능을 위해 JavaScript 애니메이션보다 CSS 전환을 선호하세요.
  • 아코디언에서는 UX 향상을 위해 한 번에 하나의 항목만 열 수 있도록 하세요.
  • 메모리 누수를 방지하기 위해 컴포넌트가 파괴될 때 구독을 정리하세요.

최종 메모

Melt UI의 Collapsible 빌더는 최소한의 설정으로 확장 가능한 콘텐츠에 대한 견고한 기반을 제공합니다. 헤드리스 접근 방식 덕분에 접근성 준수를 유지하면서 스타일을 완전히 제어할 수 있습니다.

Collapsible이 정상적으로 작동하면 일반적인 다음 단계는 다음과 같습니다:

  • 공유 상태를 가진 accordion 컴포넌트 구축.
  • 사용자 정의 애니메이션 및 전환 추가.
  • 확장 가능한 네비게이션 메뉴를 위한 라우팅 통합.
  • Collapsible 섹션이 포함된 상세 뷰 생성.
Back to Blog

관련 글

더 보기 »

실무에서의 접근성

♿ 초기 가이드 디지털 접근성은 기술 규칙을 준수하는 것을 훨씬 넘어섭니다. 이는 사람들을 포용하고, 자율성을 보장하며, 모두가 …