Next.js의 getServerSideProps처럼, SvelteKit의 load 함수는 페이지가 렌더링되기 전에 데이터를 준비합니다.

개념 정의

load 함수 는 페이지나 레이아웃이 렌더링되기 전에 실행되어 데이터를 가져오는 함수입니다. +page.js(유니버설)와 +page.server.js(서버 전용) 두 가지 형태가 있습니다.

유니버설 load (+page.js)

서버와 클라이언트 모두에서 실행됩니다.

JAVASCRIPT
// src/routes/blog/+page.js
export async function load({ fetch }) {
  // SvelteKit의 fetch는 SSR 시 서버에서, CSR 시 클라이언트에서 실행
  const res = await fetch('/api/posts');
  const posts = await res.json();

  return {
    posts  // 페이지 컴포넌트에서 data.posts로 접근
  };
}
SVELTE
<!-- src/routes/blog/+page.svelte -->
<script>
  let { data } = $props();
</script>

<h1>블로그</h1>
{#each data.posts as post}
  <article>
    <h2><a href="/blog/{post.slug}">{post.title}</a></h2>
    <p>{post.summary}</p>
  </article>
{/each}

서버 전용 load (+page.server.js)

서버에서만 실행되며, DB 접근이나 비밀 키 사용이 가능합니다.

JAVASCRIPT
// src/routes/blog/[slug]/+page.server.js
import { error } from '@sveltejs/kit';
import { db } from '$lib/server/database';

export async function load({ params }) {
  const post = await db.post.findUnique({
    where: { slug: params.slug }
  });

  if (!post) {
    error(404, '포스트를 찾을 수 없습니다');
  }

  return { post };
}

유니버설 vs 서버 전용

특성+page.js+page.server.js
실행 환경서버 + 클라이언트서버만
DB 직접 접근불가가능
비밀 키 사용불가가능
반환값 제한직렬화 가능한 데이터만직렬화 가능한 데이터만
용도공개 API 호출DB 쿼리, 인증 체크

load 함수 매개변수

JAVASCRIPT
export async function load({
  params,      // URL 매개변수 (/blog/[slug] → params.slug)
  url,         // URL 객체 (searchParams 등)
  fetch,       // 향상된 fetch (쿠키 자동 전달, 상대 경로 지원)
  cookies,     // 쿠키 읽기/쓰기 (서버 전용)
  locals,      // 미들웨어에서 설정한 데이터 (서버 전용)
  parent,      // 부모 레이아웃의 load 데이터
  depends,     // 캐시 무효화 키 등록
  route,       // 라우트 정보
}) {
  // ...
}

레이아웃 load

JAVASCRIPT
// src/routes/+layout.server.js
export async function load({ cookies }) {
  const sessionId = cookies.get('session');
  const user = sessionId ? await getUser(sessionId) : null;

  return { user };
}
SVELTE
<!-- src/routes/+layout.svelte -->
<script>
  let { data, children } = $props();
</script>

{#if data.user}
  <p>{data.user.name}님 환영합니다</p>
{:else}
  <a href="/login">로그인</a>
{/if}

{@render children()}

병렬 데이터 로딩

JAVASCRIPT
// 순차적 — 느림
export async function load({ fetch }) {
  const posts = await fetch('/api/posts').then(r => r.json());
  const categories = await fetch('/api/categories').then(r => r.json());
  return { posts, categories };
}

// 병렬 — 빠름!
export async function load({ fetch }) {
  const [posts, categories] = await Promise.all([
    fetch('/api/posts').then(r => r.json()),
    fetch('/api/categories').then(r => r.json()),
  ]);
  return { posts, categories };
}

데이터 무효화

JAVASCRIPT
// +page.js
export async function load({ fetch, depends }) {
  depends('app:posts');  // 커스텀 키 등록

  const posts = await fetch('/api/posts').then(r => r.json());
  return { posts };
}
SVELTE
<script>
  import { invalidate, invalidateAll } from '$app/navigation';

  // 특정 키만 무효화
  async function refresh() {
    await invalidate('app:posts');
  }

  // 모든 load 함수 재실행
  async function refreshAll() {
    await invalidateAll();
  }
</script>

에러 처리와 리다이렉트

JAVASCRIPT
import { error, redirect } from '@sveltejs/kit';

export async function load({ params, locals }) {
  // 인증 체크 후 리다이렉트
  if (!locals.user) {
    redirect(302, '/login');
  }

  const post = await getPost(params.slug);

  if (!post) {
    error(404, { message: '포스트를 찾을 수 없습니다' });
  }

  return { post };
}

면접 포인트

  • "load 함수는 언제 다시 실행되나요?": 해당 라우트로 네비게이션할 때, 또는 invalidate()를 호출할 때 재실행됩니다. URL 매개변수가 바뀌면 해당 load 함수만 재실행됩니다.
  • "+page.js와 +page.server.js를 동시에 쓸 수 있나요?": 가능합니다. 서버 load가 먼저 실행되고, 그 결과를 유니버설 load에서 data 매개변수로 받을 수 있습니다.

정리

load 함수는 SvelteKit 데이터 흐름의 핵심입니다. "어디서 데이터를 가져올까?"에 따라 +page.js+page.server.js를 선택하고, Promise.all로 병렬 로딩을 하며, invalidate로 캐시를 관리하면 됩니다.

댓글 로딩 중...