파일 시스템 기반 라우팅
- sveltekit의 핵심은 파일 시스템 기반 라우팅이다. 앱의 경로, 즉 사용자가 액세스 할 수 있는 경로는
/src/routes안의 코드 베이스의 디렉터리에 의해 정의 된다. - 각 경로 디렉토리에는 접두사(
+)로 식별 할 수 있는 하나 이상의 경로 파일이 포함되어 있어야 한다.- 모든 파일은 서버에서 실행 될 수 있다.
+server파일을 제외한 모든 파일은 클라이언트에서 실행된다.+layout,+error파일은 해당 파일이 있는 디렉토리 뿐만 아니라 하위 디렉토리에서도 적용된다.
`+page`
`+page.svelte`
+page.svelte파일은 앱의 페이지를 정의한다. 기본적으로 페이지는 최초 요청 시에는 서버(SSR)에서 렌더링 되고, 이후 탐색 시에는 브라우저(CSR)에서 렌더링 된다.
<!-- src/routes/+page.svelte -->
<h1>main page</h1>
<a href="/about">about</a><!-- src/routes/about/+page.svelte -->
<h1>about page</h1>
<p>contents</p>
<a href="/">main</a>- sveltekit은
<Link>구성 요소가 아닌<a>태그를 사용하여 경로간 탐색을 한다.
`+page.ts`
- 페이지가 렌더링 되기 전에 데이터를 로드 해야 경우에는
+page.ts모듈에서load함수를 사용한다.
import { error } from '@sveltejs/kit';
import type { PageLoad } from './$types';
export const load: PageLoad = ({ params }) => {
if (params.slug === 'hello-world') {
return {
title: 'Hello world!',
content: 'Welcome to our blog. Lorem ipsum dolor sit amet...'
};
}
error(404, 'Not found');
};- 이 함수는
+page.svelte와 함께 실행된다. SSR 시에는 서버에서 실행되고, CSR 시에는 브라우저에서 실행된다. - 또한
load,+page.ts의 동작을 구성하는 값을 내보낼 수 있다.export const prerender = true (false, 'auto')export const ssr = true (false)export const csr = true (false)
`+page.server.ts`
+page.ts와 역할은 동일하지만 브라우저에는 코드가 전송되지 않고 오직 서버에서만 실행된다.- 직접적인 데이터 베이스 접근이나 서버의 파일시스템 접근, 비공개 키값 사용 등 보안이 중요한 작업 수행을 작성한다.
import { error } from '@sveltejs/kit';
import type { PageServerLoad } from './$types';
export const load: PageServerLoad = async ({ params }) => {
const post = await getPostFromDatabase(params.slug);
if (post) {
return post;
}
error(404, 'Not found');
};`+error`
`+error.svelte`
load함수 수행중 오류가 발생하면 sveltekit은 기본 오류 페이지를 렌더링한다. 하지만+error.svelte파일을 추가하여 경로 별로 이 오류페이지를 사용자가 지정할 수 있다.
<script lang="ts">
import { page } from '$app/state';
</script>
<h1>{page.status}: {page.error.message}</h1>`+layout`
+layout은 여러 페이지에 걸쳐 공통적으로 사용되는 템플릿을 정의한다. 여러 페이지에 동일한 헤더, 네비게이션 바, 푸터 등을 표시하고자 할 때+layout에 작성한다.
`+layout.svelte`
- 모든 페이지에 적용되는 레이아웃을 만들려면
src/routes/+layout.svelte파일을 생성하고 기본 레이아웃을 작성한다.
<!-- +layout.svelte -->
<!-- 작성된 레이아웃이 없을 경우 sveltekit의 기본 레이아웃 내용 -->
<script>
let { children } = $props();
</script>
{@render children()}- 하위 페이지에만 따로 layout을 적용하고 싶다면 하위 디렉토리에 추가 적인
+layout.svelte파일을 작성한다.
<!-- src/routes/settings/+layout.svelte -->
<script lang="ts">
import type { LayoutProps } from './$types';
let { data, children }: LayoutProps = $props();
</script>
<h1>Settings</h1>
<div class="submenu">
{#each data.sections as section}
<a href="/settings/{section.slug}">{section.title}</a>
{/each}
</div>
{@render children()}`+layout.ts`
+page.ts를 통해+page.svelte에서 데이터를 로드하는 것과 마찬가지로+layout.svelte는+layout.ts의load함수를 통해 데이터를 로드 할수 있다.+layout.ts가 페이지 옵션(프리렌더, SSR 및 CSR)을 내보내면 하위 페이지의 기본값으로 사용된다.
import type { LayoutLoad } from './$types';
export const load: LayoutLoad = () => {
return {
sections: [
{ slug: 'profile', title: 'Profile' },
{ slug: 'notifications', title: 'Notifications' }
]
};
};`+layout.server.ts`
+page.server.ts와 역할이 동일하다. 단 데이터 사용을 위해선LayoutServerLoad로 형식을 변경해야 한다.
`+server.ts`
+server.ts파일은 커스텀 API 앤드포인트를 만드는 데 사용된다.+server.ts파일은 서버에서만 작동하며 svelte 컴포넌트를 렌더링하는 대신, HTTP 요청(Request)을 직접 처리하고 응답(Response)을 반환하는 서버 사이드 로직을 작성한다.+page.server.ts가 특정 페이지를 위한 데이터를 준비한다면,+server.ts는 페이지와 독립적인 재사용 가능한 API 라우트를 생성한다.- 파일 안에서
GET,POST,POST,PATCH,DELETE등 HTTP 메소드 이름으로 함수를 export 하면, 해당 메소드의 요청을 처리하는 핸들러가 된다. - 파일의 위치가 곧 API URL 경로가 되는 파일 기반 라우팅 기능을 지원한다.
src/routes/api/posts/+server.ts=>/api/postssrc/routes/api/posts/[id]/+server.ts=>/api/posts/[id]
+server.ts는 sveltekit 프로젝트 내에서 완전한 기능의 백엔드 API 서버를 구축할 수 있는 강력한 기능 도구 이다. 페이지 렌더링과 무관하게 순수한 데이터나 로직을 HTTP를 통해 제공하고 싶을 떄 사용된다.
import { error } from '@sveltejs/kit';
import type { RequestHandler } from './$types';
export const GET: RequestHandler = ({ url }) => {
const min = Number(url.searchParams.get('min') ?? '0');
const max = Number(url.searchParams.get('max') ?? '1');
const d = max - min;
if (isNaN(d) || d < 0) {
error(400, 'min and max must be numbers, and min must be less than max');
}
const random = min + Math.random() * d;
return new Response(String(random));
};
export const POST: RequestHandler = async ({ request }) => {
const { a, b } = await request.json();
return json(a + b);
};
export const fallback: RequestHandler = async ({ request }) => {
return text(`I caught your ${request.method} request!`);
};Fallback method handler
- API 요청 메소드에 해당되는 작성된 핸들러가 없다면
fallback메서드가 처리하게 된다.
경로 충돌
+server.ts파일은+page파일과 동일한 경로에 배치 될 수 있으며, 이를 통해 동일한 경로가 페이지 로드 또는 API 앤드 포인트가 될수 있다. sveltekit은 다음과 같은 규칙으로 어떤 경로를 사용할지 정한다.PUT,PATCH,DELETE,OPTIONS요청은 페이지 로딩에 적용되지 않으므로+server.ts경로가 선택된다.- 요청이
text/html일 경우(브라우저 페이지 요청)는 페이지 로드 요청이 선택되고, 그렇지 않을 경우+server.ts경로가 선택된다. GET요청에 대한 응답에는 브라우저가 HTML/JSON을 선택할 수 있도록Vary: Accept헤더가 포함된다.
`$types`
괄호 라우팅
- sveltekit에서는 폴더명 이나 파일명을 괄호로 묶어 라우팅을 제어하거나 파라미터 입력을 받는 기능을 제공한다.
동적 라우트 -
[파라미터_이름]- 가장 흔하게 사용되는 형태로, URL 일부를 변수(파라미터)로 만들고 싶을때 사용한다.
- 예시
- 파일 경로 : src/routes/shop/products/[id]/+page.svelte
- 매칭 URL : /shop/products/123 , /shop/products/abc
- load 함수의 params.id은 123, abc
라우트 그룹 -
(그룹_이름)- 폴더명을 일반 괄호로 감사면, 관련 라우트 들을 그룹으로 묶을 수 있지만 URL 경로에는 영향을 주지 않는다.
- 예시1
- 파일 경로 : src/routes/(marketing)/about/+page.svelte
- 매칭 URL : /about
- (marketing)은 무시됨
- 예시2
- 파일 경로 : src/routes/(app)/dashboard/+page.svelte
- 매칭 URL : /dashboard
- (app)은 무시됨
선택적 파라미터 -
[[]]- 동적 라우트 세그먼트가 있어도 되고 없어도 되는 경우에 사용한다.
- 예시1
- 파일 경로 : src/routes/[[lang]]/contact/+page.svelte
- 매칭 URL1 : /contact
- load 함수에서 params.lang은 undefined
- 매칭 URL2 : /en/contact
- load 함수에서 params.lang은 'en'
나머지 파라미터 -
[... ]- 특정 지점 부터 나머지 모든 URL 경로를 하나의 파라미터로 잡을 때 사용한다.
- 예시
- 파일 경로 : src/routes/docs/[...slug]/+page.svelte
- 매칭 URL : /docs/a/b/c
- load 함수에서 params.slug의 값은 'a/b/c'