티스토리 뷰
SvelteKit으로 시작하는 SSR 백엔드-프론트 기초 100단계
6단계 — +layout.server.ts로 공통 SSR 데이터 관리하기
(로그인 상태·공통 설정을 “한 번만” 서버에서 주입하는 법)
5단계까지 오면 이제 이런 요구가 자연스럽게 생깁니다.
“모든 페이지에서 공통으로 쓰는 데이터는 어디서 처리하지?”
“매 페이지마다 load에 로그인 상태 넣어야 하나?”
“헤더에 항상 사용자 정보를 보여주고 싶은데?”
이때 등장하는 게 **+layout.server.ts**입니다.
페이지마다 중복되는 서버 로직을 ‘상위 레이아웃’에서 한 번만 처리하는 자리죠.
6단계 목표
- +layout.server.ts의 역할을 정확히 이해한다
- 모든 페이지에 공통 SSR 데이터를 주입한다
- 로그인 전/후 UI 분기를 레이아웃 기준으로 만든다
- 이후 인증(7~8단계)을 붙일 확장 포인트를 확보한다
먼저 개념 한 번에 정리
지금까지 우리가 한 것
- +page.server.ts → 해당 페이지 전용 서버 로직
이번에 추가할 것
- +layout.server.ts → 하위 모든 페이지에 공통 적용되는 서버 로직
구조를 그림으로 보면 이렇습니다.
/src/routes
├─ +layout.server.ts ← 공통 서버 load
├─ +layout.svelte ← 공통 UI (헤더/푸터)
└─ +page.server.ts ← 페이지 전용 서버 load
👉 레이아웃의 load는 항상 먼저 실행되고
👉 그 결과가 모든 페이지의 data에 합쳐집니다
Step 6-1. 공통 레이아웃 파일 만들기
1️⃣ 서버 레이아웃 생성
src/routes/+layout.server.ts
import type { LayoutServerLoad } from './$types';
export const load: LayoutServerLoad = async ({ cookies }) => {
// 확장 포인트: 나중에 여기서 로그인 세션 확인
const userId = cookies.get('user_id') ?? null;
return {
appName: 'SvelteKit SSR 100',
isLoggedIn: Boolean(userId),
userId
};
};
여기서 중요한 점
- LayoutServerLoad → 레이아웃 전용 타입
- cookies 접근 가능 → 서버 전용
- 아직 로그인 구현은 안 했지만
👉 자리부터 잡아두는 게 핵심
Step 6-2. 레이아웃 UI에서 공통 데이터 사용하기
이제 서버에서 내려준 데이터를 모든 페이지에 보이게 만듭니다.
src/routes/+layout.svelte
<script lang="ts">
export let data: {
appName: string;
isLoggedIn: boolean;
userId: string | null;
};
</script>
<header style="border-bottom: 1px solid #ddd; padding: 1rem;">
<h2>{data.appName}</h2>
{#if data.isLoggedIn}
<p>로그인 상태 (user: {data.userId})</p>
{:else}
<p>로그인 안 됨</p>
{/if}
<nav>
<a href="/">Home</a>
</nav>
</header>
<main style="padding: 1rem;">
<slot />
</main>
포인트
- <slot /> → 하위 페이지가 여기 들어옴
- 이 헤더는 모든 페이지에서 자동 렌더링
Step 6-3. 기존 페이지 코드, 수정 필요 없음
지금 상태에서:
- src/routes/+page.server.ts
- src/routes/+page.svelte
👉 한 줄도 수정하지 않아도
레이아웃 데이터가 자동으로 합쳐집니다.
실제로 합쳐지는 data 구조 (개념)
data = {
// layout.server.ts
appName,
isLoggedIn,
userId,
// page.server.ts
posts,
error?,
success?
}
👉 페이지 입장에선
“data에 뭐가 더 들어왔네?” 정도의 느낌입니다.
Step 6-4. 실제 동작 확인 포인트
브라우저에서 확인하세요.
1️⃣ 어떤 페이지를 가도
- 상단에 SvelteKit SSR 100
- 로그인 상태 표시
2️⃣ 쿠키를 임의로 넣어보면
(개발자도구 → Application → Cookies)
user_id=123
→ 새로고침하면
“로그인 상태 (user: 123)” 로 표시됨
👉 아직 인증 구현 전인데도
레이아웃 구조는 이미 준비 완료
Step 6-5. 왜 이게 “실무 구조”인가
주니어들이 흔히 하는 실수:
- 모든 페이지 load에서
- 로그인 체크
- 설정 로딩
- 공통 데이터 중복
이러면 나중에:
- 페이지 늘어날수록 코드 중복
- 수정 포인트 폭발
레이아웃 서버 로드의 장점
- 공통 로직 한 곳
- 페이지는 비즈니스에만 집중
- 인증/권한/설정/피처 플래그까지 확장 가능
지금 구조에서 “확장 포인트” 딱 짚어주기
곧 할 것들이 여기로 들어옵니다.
// +layout.server.ts (미래)
export const load = async ({ cookies, locals }) => {
const session = await getSession(cookies);
const user = session ? await getUser(session.userId) : null;
return {
user,
isLoggedIn: Boolean(user),
featureFlags: { ... }
};
};
👉 페이지/컴포넌트는
data.user만 보고 판단
흔한 실수 TOP 3
❌ 페이지마다 로그인 체크
- 레이아웃으로 끌어올리면 해결
❌ 레이아웃에 비즈니스 로직 과다
- 레이아웃은 공통 정보만
❌ +layout.ts와 +layout.server.ts 혼동
- 서버 데이터 필요 → server
- 클라 전용 로직 → 일반 layout
오늘 단계에서 꼭 가져가야 할 감각
- 공통 서버 데이터는 레이아웃에서
- 페이지는 자기 일만 하게
- 인증/권한은 구조부터가 반
이 감각이 잡히면
다음 단계에서 로그인/세션 붙일 때
“어디에 뭘 둬야 하는지”가 명확해집니다.
다음 글 예고 (7단계)
7단계 — hooks.server.ts로 요청 생명주기 이해하기 (인증의 진짜 시작)
- 모든 요청이 거치는 관문
- 쿠키 → locals → layout → page 흐름
- “왜 인증은 hooks에서 하라 하는지” 완전 정리
이제부터 진짜 백엔드 영역으로 들어갑니다.
SvelteKit,SSR,LayoutServerLoad,공통데이터,주니어개발자,백엔드기초,풀스택,웹개발,사이드프로젝트,아키텍처
'study > 백엔드' 카테고리의 다른 글
| SvelteKit으로 시작하는 SSR 백엔드-프론트 기초 100단계 (0) | 2026.02.25 |
|---|---|
| SvelteKit으로 시작하는 SSR 백엔드-프론트 기초 100단계 (0) | 2026.02.09 |
| SvelteKit으로 시작하는 SSR 백엔드-프론트 기초 100단계 (0) | 2026.01.28 |
| SvelteKit으로 시작하는 SSR 백엔드-프론트 기초 100단계 (0) | 2026.01.27 |
| SvelteKit으로 시작하는 SSR 백엔드-프론트 기초 100단계 (0) | 2026.01.27 |
- Total
- Today
- Yesterday
- rag
- JWT
- seo 최적화 10개
- 쿠버네티스
- node.js
- CI/CD
- 백엔드개발
- flax
- 압박면접
- 개발블로그
- ai철학
- 딥러닝
- nextJS
- NestJS
- PostgreSQL
- SEO최적화
- JAX
- 웹개발
- Express
- Next.js
- llm
- Python
- DevOps
- kotlin
- REACT
- Docker
- Prisma
- Redis
- fastapi
- LangChain
| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | |||
| 5 | 6 | 7 | 8 | 9 | 10 | 11 |
| 12 | 13 | 14 | 15 | 16 | 17 | 18 |
| 19 | 20 | 21 | 22 | 23 | 24 | 25 |
| 26 | 27 | 28 | 29 | 30 |
