SvelteKit Load 함수 — 서버와 클라이언트에서 데이터 가져오기
Next.js의
getServerSideProps처럼, SvelteKit의load함수는 페이지가 렌더링되기 전에 데이터를 준비합니다.
개념 정의
load 함수 는 페이지나 레이아웃이 렌더링되기 전에 실행되어 데이터를 가져오는 함수입니다. +page.js(유니버설)와 +page.server.js(서버 전용) 두 가지 형태가 있습니다.
유니버설 load (+page.js)
서버와 클라이언트 모두에서 실행됩니다.
// 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로 접근
};
}
<!-- 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 접근이나 비밀 키 사용이 가능합니다.
// 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 함수 매개변수
export async function load({
params, // URL 매개변수 (/blog/[slug] → params.slug)
url, // URL 객체 (searchParams 등)
fetch, // 향상된 fetch (쿠키 자동 전달, 상대 경로 지원)
cookies, // 쿠키 읽기/쓰기 (서버 전용)
locals, // 미들웨어에서 설정한 데이터 (서버 전용)
parent, // 부모 레이아웃의 load 데이터
depends, // 캐시 무효화 키 등록
route, // 라우트 정보
}) {
// ...
}
레이아웃 load
// src/routes/+layout.server.js
export async function load({ cookies }) {
const sessionId = cookies.get('session');
const user = sessionId ? await getUser(sessionId) : null;
return { user };
}
<!-- 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()}
병렬 데이터 로딩
// 순차적 — 느림
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 };
}
데이터 무효화
// +page.js
export async function load({ fetch, depends }) {
depends('app:posts'); // 커스텀 키 등록
const posts = await fetch('/api/posts').then(r => r.json());
return { posts };
}
<script>
import { invalidate, invalidateAll } from '$app/navigation';
// 특정 키만 무효화
async function refresh() {
await invalidate('app:posts');
}
// 모든 load 함수 재실행
async function refreshAll() {
await invalidateAll();
}
</script>
에러 처리와 리다이렉트
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로 캐시를 관리하면 됩니다.
댓글 로딩 중...