폴더를 만들면 라우트가 생기고, 파일 이름이 곧 규칙입니다 — SvelteKit의 라우팅은 파일 시스템이 곧 라우터입니다.

개념 정의

SvelteKit의 파일 기반 라우팅 은 src/routes/ 디렉토리의 폴더 구조가 곧 URL 구조가 되는 시스템입니다. +page.svelte 파일이 있는 폴더가 하나의 라우트가 됩니다.

기본 라우트

PLAINTEXT
src/routes/
├── +page.svelte          → /
├── about/
│   └── +page.svelte      → /about
├── blog/
│   └── +page.svelte      → /blog
└── contact/
    └── +page.svelte      → /contact

동적 라우트

대괄호 []로 동적 매개변수를 정의합니다.

PLAINTEXT
src/routes/
├── blog/
│   ├── +page.svelte           → /blog
│   └── [slug]/
│       └── +page.svelte       → /blog/hello-world, /blog/my-post
├── users/
│   └── [id]/
│       ├── +page.svelte       → /users/1, /users/2
│       └── settings/
│           └── +page.svelte   → /users/1/settings
SVELTE
<!-- src/routes/blog/[slug]/+page.svelte -->
<script>
  let { data } = $props();
</script>

<h1>{data.post.title}</h1>
<div>{@html data.post.content}</div>
JAVASCRIPT
// src/routes/blog/[slug]/+page.js
export async function load({ params }) {
  // params.slug에 URL의 동적 부분이 들어옵니다
  const post = await fetchPost(params.slug);
  return { post };
}

나머지 매개변수 (Catch-all)

PLAINTEXT
src/routes/
└── docs/
    └── [...path]/
        └── +page.svelte   → /docs/a, /docs/a/b, /docs/a/b/c
JAVASCRIPT
// src/routes/docs/[...path]/+page.js
export async function load({ params }) {
  // params.path = 'a/b/c' (문자열)
  const segments = params.path.split('/');
  return { segments };
}

선택적 매개변수

PLAINTEXT
src/routes/
└── [[lang]]/
    └── +page.svelte   → / 또는 /ko 또는 /en

라우트 그룹

괄호 ()로 URL에 영향을 주지 않는 그룹을 만들 수 있습니다.

PLAINTEXT
src/routes/
├── (marketing)/          # URL에 포함되지 않음
│   ├── +layout.svelte    # 마케팅 전용 레이아웃
│   ├── about/
│   │   └── +page.svelte  → /about
│   └── pricing/
│       └── +page.svelte  → /pricing
├── (app)/                # URL에 포함되지 않음
│   ├── +layout.svelte    # 앱 전용 레이아웃 (사이드바 등)
│   ├── dashboard/
│   │   └── +page.svelte  → /dashboard
│   └── settings/
│       └── +page.svelte  → /settings

레이아웃

SVELTE
<!-- src/routes/+layout.svelte — 루트 레이아웃 -->
<script>
  let { children } = $props();
</script>

<nav>전역 네비게이션</nav>
{@render children()}
<footer>전역 푸터</footer>
SVELTE
<!-- src/routes/blog/+layout.svelte — 블로그 전용 레이아웃 -->
<script>
  let { children } = $props();
</script>

<div class="blog-layout">
  <aside>블로그 사이드바</aside>
  <article>{@render children()}</article>
</div>

레이아웃은 중첩됩니다: 루트 레이아웃 > 블로그 레이아웃 > 페이지

레이아웃 리셋

상위 레이아웃을 건너뛰고 싶을 때 @ 접미사를 사용합니다.

PLAINTEXT
src/routes/
├── +layout.svelte           # 루트 레이아웃 (A)
├── blog/
│   ├── +layout.svelte       # 블로그 레이아웃 (B)
│   ├── +page.svelte         # A + B 적용
│   └── embed/
│       └── +page@.svelte    # 모든 레이아웃 리셋 — 레이아웃 없음

네비게이션

SVELTE
<script>
  import { goto, beforeNavigate, afterNavigate } from '$app/navigation';
  import { page } from '$app/state';

  // 현재 URL 정보
  // page.url, page.params, page.route

  // 프로그래밍 방식 네비게이션
  function goToBlog() {
    goto('/blog');
  }

  // 네비게이션 가드
  beforeNavigate(({ cancel, to }) => {
    if (hasUnsavedChanges) {
      if (!confirm('저장하지 않은 변경사항이 있습니다.')) {
        cancel();
      }
    }
  });

  afterNavigate(({ from, to }) => {
    console.log(`${from?.url} → ${to?.url}`);
  });
</script>

<!-- a 태그는 자동으로 클라이언트 사이드 네비게이션 -->
<a href="/blog">블로그</a>

<!-- 현재 경로 하이라이트 -->
<a href="/about" class:active={page.url.pathname === '/about'}>소개</a>

<button onclick={goToBlog}>블로그로 이동</button>

에러 처리

SVELTE
<!-- src/routes/+error.svelte -->
<script>
  import { page } from '$app/state';
</script>

<h1>{page.status}</h1>
<p>{page.error?.message}</p>

면접 포인트

  • "파일 기반 라우팅의 장점은?": 파일 구조가 곧 URL 구조이므로 프로젝트 구조만 봐도 앱의 라우트를 파악할 수 있습니다. 별도의 라우터 설정 파일이 필요 없습니다.
  • "라우트 그룹은 언제 쓰나요?": 다른 레이아웃을 적용해야 하지만 URL 구조에는 영향을 주고 싶지 않을 때 사용합니다. 마케팅 페이지와 앱 페이지가 다른 레이아웃을 쓰는 것이 대표적 예시입니다.

정리

SvelteKit의 라우팅은 "폴더 구조 = URL 구조"라는 직관적인 원칙을 따릅니다. 동적 라우트, 그룹, 레이아웃 중첩, 에러 처리까지 모두 파일 시스템의 규칙으로 표현되니, 복잡한 설정 없이도 정교한 라우팅을 구현할 수 있습니다.

댓글 로딩 중...