(초안) SvelteKit
SvelteKit은 Svelte 프레임워크로, 서버 사이드 렌더링(SSR) 기반의 빠른 빌드 속도와 간편한 라우팅 시스템을 제공하며, SEO 최적화 등 성능 향상을 위한 여러 기능을 제공합니다.
2021년, Svelte의 창시자인 Rich Harris가 Vercel 팀에 합류하면서 더욱 Vercel 친화적으로 쉬운 사용성을 갖추게 되었습니다.
# 설치 및 구성
다음 명령으로 SvelteKit 프로젝트를 설치합니다.
TypeScript와 ESLint 그리고 Prettier를 사용합니다.
123456# npm create svelte@latest sveltekit-project # npm create svelte@latest . npm create svelte@latest <경로|프로젝트이름> ✔ Which Svelte app template? - SvelteKit demo app ✔ Add type checking with TypeScript? - Yes, using TypeScript syntax ✔ Select additional options (use arrow keys/space bar) - Select all
# SCSS
SCSS를 사용하기 위해 다음 패키지를 설치합니다.
설치 후 바로 *.scss
파일을 사용할 수 있습니다.
1npm i -D sass
123456html { --color-font: #333; body { color: var(--color-font); } }
1234<script lang="ts"> // ... import '../app.scss' </script>
# 경로 별칭
새로운 경로 별칭이 필요하면, 다음과 같이 alias
옵션을 사용할 수 있습니다.
1234567891011121314// ... const config = { kit: { alias: { // $lib: './src/lib', $components: './src/components', $store: './src/store' }, files: { lib: './src/lib' } } } export default config
1234<script lang="ts"> import TextField from '$components/TextField.svelte' import { scrollPaddingTop } from '$store/page' </script>
# 환경변수
1234CREDENTIALS=1234 API_KEY=5678 PUBLIC_CLIENT_URL=https://heropy.dev PUBLIC_DATABASE_ANON_KEY=abcd
환경변수는 기본적으로 서버 측에서만 사용할 수 있습니다.$env/static/private
모듈에서 가져옵니다.
1import { CREDENTIALS, API_KEY } from '$env/static/private'
클라이언트에서 사용할 환경변수는, PUBLIC_
접두사를 붙여야 합니다.
이는 해당 환경변수가 클라이언트에서 노출되어도 문제가 없다는 것을 명시적으로 표현하기 위함입니다.$env/static/public
모듈에서 가져옵니다.
1import { PUBLIC_CLIENT_URL, PUBLIC_DATABASE_ANON_KEY } from '$env/static/public'
필요하면, 원하는 접두사를 추가하거나 수정할 수 있습니다.
12345678910// ... const config = { kit: { env: { publicPrefix: 'PUBLIC_', // 기본값! privatePrefix: 'SECRET_' } } } export default config
1234SECRET_CREDENTIALS=1234 SECRET_API_KEY=5678 PUBLIC_CLIENT_URL=https://heropy.dev PUBLIC_DATABASE_ANON_KEY=abcd
12import { SECRET_CREDENTIALS, SECRET_API_KEY } from '$env/static/private' import { PUBLIC_CLIENT_URL, PUBLIC_DATABASE_ANON_KEY } from '$env/static/public'
# 폰트 미리로드
font-display: swap
을 사용해 폰트를 출력하지 못하는 상황(FOIT, Flash Of Invisible Text)을 방지할 수 있지만, 폰트 로드 후 시스템 폰트가 교체되는 현상(FOUT, Flash Of Unstyled Text)이 발생하므로, 다음과 같이 설치한 폰트를 가져와 미리로드 경로로 지정할 수 있습니다.
1234567891011<script lang="ts"> import pretendard from '$lib/font/PretendardVariable.woff2' import '$lib/font/pretendardvariable.css' </script> <link rel="preload" href={pretendard} as="font" type="font/woff2" crossorigin="anonymous" />
폰트 사용을 잊지 마세요!
12345body { font-family: 'Pretendard Variable', Pretendard, -apple-system, BlinkMacSystemFont, system-ui, Roboto, 'Helvetica Neue', 'Segoe UI', 'Apple SD Gothic Neo', 'Noto Sans KR', 'Malgun Gothic', 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', sans-serif; }
# 페이지의 데이터 로드 및 전달
페이지(+page.svelte
)를 렌더링하기 전에 필요한 데이터를 로드하는 방법으로 load
함수를 내보내는 +page.server.ts
와 +page.ts
파일을 사용할 수 있습니다.
각 파일은 +page.server.ts
, +page.ts
, +page.svelte
순으로 실행되며, 만약 모두 사용하는 경우 다음과 같이 +page.server.ts
에서 +page.ts
파일로 데이터를 전달해야 합니다.
12345export async function load() { return { pageServerData: 'Hello, Server Data!' } }
123456export async function load({ data }) { return { ...data, // pageServerData: 'Hello, Server Data!' pageData: 'Hello, Hydration Data!' } }
123456789<script lang="ts"> import type { PageData } from './$types' export let data: PageData const { pageServerData, pageData } = data console.log(pageServerData) // 'Hello, Server Data!' console.log(pageData) // 'Hello, Hydration Data!' </script>
# TanStack Query 사용
루트 레이아웃의 load
함수에서 쿼리 클라이언트를 생성해 반환합니다.
그리고 서버에서 불필요하게 실행되지 않도록 클라이언트(브라우저)에서만 쿼리를 활성화합니다.
12345678910111213import { browser } from '$app/environment' import { QueryClient } from '@tanstack/svelte-query' export async function load() { const queryClient = new QueryClient({ defaultOptions: { queries: { enabled: browser // 브라우저에서만 활성화 } } }) return { queryClient } }
생성한 쿼리 클라이언트를 가져와 연결합니다.
12345678910<script lang="ts"> import { QueryClientProvider } from '@tanstack/svelte-query' import type { LayoutData } from './$types' export let data: LayoutData </script> <QueryClientProvider client={data.queryClient}> <slot /> </QueryClientProvider>
각 페이지에 접근할 때, prefetchQuery
메소드로 사용할 데이터를 미리 가져옵니다.
페이지에 다시 방문해도 캐시 데이터를 사용할 수 있습니다.
12345678910export async function load({ parent, fetch, params }) { const { queryClient } = await parent() // 상위 레이아웃(+layout.ts)에서 반환하는 데이터 접근 const { postId } = params await queryClient.prefetchQuery({ queryKey: ['analytics', postId], queryFn: async () => (await fetch(`/api/posts/${postId}`)).json(), staleTime: 1000 * 60 * 60 * 24 // 24시간! }) }
각 페이지 컴포넌트에서 createQuery
함수를 사용해 쿼리를 생성합니다.createQuery
함수는 Svelte 스토어 객체를 반환합니다.
123456789101112131415161718<script lang="ts"> import { createQuery } from '@tanstack/svelte-query' import { browser } from '$app/environment' import { page } from '$app/stores' const { postId } = $page.params const query = createQuery<ResponseValue>({ queryKey: ['analytics', postId], queryFn: async () => (await fetch(`/api/posts/${postId}`)).json(), staleTime: 1000 * 60 * 60 * 24 // 24시간! }) query.subscribe(async ({ isFetching, data }) => { // 브라우저가 아니거나 데이터를 가져오는 중이면 실행하지 않음 if (!browser || isFetching) return console.log(data) }) </script>
끝까지 읽어주셔서 감사합니다.
좋아요와 응원 댓글은 블로그 운영에 큰 힘이 됩니다!