앞에서 배운 패턴을 한 화면에 모아 학습 관리 대시보드를 중간 점검 버전으로 정리합니다.
시작 전에 정리하기
- 무엇을 만든다: 사이드바·본문·하단 로그가 동시에 보이는
/dashboard화면과 과제 카드 CRUD 흐름. - 왜 중요한가: 미니 대시보드는 상태, 레이아웃, 폼, 애니메이션이 어떻게 맞물리는지 한눈에 보여 주는 중간 점검판입니다.
- 주의할 점: 슬롯 레이아웃 구조를 먼저 고정하고
depends/invalidate키를 다시 확인해야 전체 화면이 동시에 갱신됩니다.
이번 글에서 새로 나오는 용어
- 대시보드: 여러 지표 카드와 폼이 동시에 보이는 현황판 화면으로, 팀 상황을 한눈에 보여 줍니다.
- 슬롯 레이아웃: 사이드바·본문·하단 등 위치를 고정해두고 콘텐츠만 교체하는 레이아웃 구조입니다.
개념
대시보드(dashboard, 현황판)는 여러 데이터 카드가 동시에 보이는 화면입니다. 레이아웃(layout, 배치)과 슬롯(slot, 자리)을 사용하면 사이드바·본문·하단 로그 같은 영역을 고정한 채 페이지를 늘릴 수 있습니다. 데이터 스토어와 load 함수는 초기 데이터를 공급합니다. 폼 액션과 낙관적 UI는 사용자의 입력을 즉시 반영합니다. 전환과 spring 모션(spring motion, 탄성 애니메이션)은 상태 변화를 부드럽게 전달해 집중도를 지켜 줍니다. 이번 편을 시리즈의 중간 결산으로 삼고, 이후 인증·파일·실시간 편에서 더 깊은 기능을 얹게 됩니다.
코드
루트 레이아웃, 페이지 데이터, 카드 리스트, 폼을 한꺼번에 살펴봅니다.
<!-- src/routes/(app)/+layout.svelte -->
<AppShell>
<svelte:fragment slot="sidebar">
<SubjectSidebar />
</svelte:fragment>
<slot />
<svelte:fragment slot="bottom-panel">
<ActivityLog />
</svelte:fragment>
</AppShell>
// src/routes/(app)/dashboard/+page.server.ts
export const load = async ({ fetch, depends }) => {
depends('data:tasks');
const [subjects, tasks] = await Promise.all([
fetch('/api/subjects').then((r) => r.json()),
fetch('/api/tasks').then((r) => r.json())
]);
return { subjects, tasks };
};
<!-- 카드 리스트 -->
<section class="grid" animate:flip>
{#if filtered.length === 0}
<EmptyState in:fade={{ duration: 120 }} />
{:else}
{#each filtered as task (task.id)}
<TaskCard {task} transition:scale={{ duration: 120 }} on:toggle />
{/each}
{/if}
</section>
<form method="POST" action="?/create"
use:enhance={({ result }) => {
if (result.type === 'success') invalidate('data:tasks');
}}>
<input name="title" placeholder="새 과제" required />
<select name="subjectId">
{#each subjects as subject}
<option value={subject.id}>{subject.name}</option>
{/each}
</select>
<button>등록</button>
</form>
카드를 토글할 때는 11편에서 만든 낙관적 패턴으로 즉시 상태를 바꾸고, 실패 시에는 스냅샷으로 롤백합니다.
💬 댓글
이 글에 대한 의견을 남겨주세요