스벨트(Svelte) 팀이 10월 1일(현지시간) 공식 애플리케이션 프레임워크 SvelteKit의 3.0 버전을 정식 출시했다.
8월 13일 릴리스 후보(RC)를 낸 지 약 7주 만이다. 팀은 "같은 프레임워크에 다듬기를 조금 더하고, 타입 안전성을 조금 더하고, 잡동사니를 조금 덜어냈다"고 소개했다. 하지만 설정 파일 위치, 경로 별칭, 최소 의존성 버전이 모두 바뀌는 메이저 업그레이드라 기존 프로젝트는 손이 간다.
- SvelteKit 3.0이 10월 1일 정식 출시됐다. svelte.config.js는 더 이상 지원되지 않고 설정은 vite.config.ts의 sveltekit() 플러그인으로 옮긴다.
- $lib 별칭은 Node 표준 서브패스 import인 #lib로 바뀌며, 확장자까지 명시해야 한다. $app/stores와 $service-worker 모듈은 제거됐다.
- 최소 요구 버전은 Node 22.17, TypeScript 6, Svelte 5.57.1, Vite 8.0.12. npx sv migrate sveltekit-3로 자동 이전하고 나머지는 TODO 목록으로 받는다.
PART 01무슨 일이 있었나
스벨트 팀은 블로그에서 SvelteKit 3을 "써 본 사람이라면 모든 게 익숙하게 느껴질 것"이라고 설명했다. 큰 철학 변화보다는 SvelteKit 2 시절 Svelte 4 호환 때문에 남겨 둔 구조를 걷어내는 성격이 강하다. 3.0은 Svelte 5를 필수로 요구하고, 그 덕분에 에러 바운더리와 세밀한 상태 기반 API로 정리할 수 있게 됐다.
마이그레이션은 sv CLI가 맡는다. npx sv migrate sveltekit-3 --tasks all --confirm을 실행하면 가능한 만큼 코드를 자동으로 바꾸고, 사람이 처리해야 할 항목은 TODO 목록으로 만들어 준다. 팀은 "에이전트를 좋아한다면 로봇 친구들이 금방 처리할 것"이라고 덧붙였다. 공식 마이그레이션 가이드는 3.0으로 올리기 전에 먼저 2.x 최신 버전으로 업그레이드해 경고 메시지를 확인하라고 권한다.
# 기존 프로젝트 이전 (먼저 2.x 최신으로 올린 뒤 실행 권장)
npx sv migrate sveltekit-3 --tasks all --confirm
# 새 프로젝트 생성
npx sv create my-new-appPART 02핵심 변경 사항
설정을 Vite 쪽으로 옮긴 이유에 대해 팀은 Vite 플러그인이 설정에 즉시 접근할 수 있어야 하는데, 별도 파일을 비동기로 읽어 오는 구조가 제약이 됐다고 설명했다. Vitest처럼 작업 디렉터리가 프로젝트 루트가 아닌 채로 도는 도구도 있어서 설정 해석이 꼬였다. 기존 config.kit.* 아래 있던 옵션은 sveltekit() 플러그인의 최상위 옵션이 되고, SvelteKit이 모르는 옵션은 vite-plugin-svelte로 그대로 넘어간다. vite.config에서 설정하는 기능 자체는 2.62부터 들어와 있었다.
$lib가 #lib로 바뀌는 건 Node의 서브패스 import(package.json의 imports 필드)라는 표준 기능을 쓰기 위해서다. Vite와 TypeScript가 기본 지원하므로 둘 사이를 맞추던 별도 코드를 지울 수 있게 됐다. 다만 Node와 TypeScript는 서브패스 import가 모호하지 않기를 요구하므로 #lib/foo 대신 #lib/foo.ts나 #lib/foo/index.ts처럼 써야 한다. 대형 프로젝트라면 이 부분이 가장 많은 diff를 만들 것이다.
PART 03보안·에러 처리에서 달라지는 점
에러 처리는 크게 나아졌다. SvelteKit 2는 에러 바운더리가 없는 Svelte 4를 지원해야 했기 때문에 +error.svelte를 load 중 에러에만 보여 줄 수 있었다. 3.0에서는 렌더링 중 에러도 처리되고, error(...)로 의도적으로 던진 에러까지 포함해 모든 에러가 handleError를 거친다. 스택 트레이스에는 소스맵이 적용된다. 다만 팀은 모든 어댑터가 프로덕션에서 소스맵이 적용된 스택 트레이스를 제대로 보여 주기까지는 시간이 걸린다고 밝혔다.
보안 기본값도 엄격해졌다. CSRF 보호를 끄던 csrf.checkOrigin 옵션은 제거됐고, 대신 csrf.trustedOrigins로 신뢰할 출처를 지정한다. Content-Type 헤더 없이 들어오는 교차 출처 변경 요청은 CSRF로 간주해 거부한다. 외부 URL로 redirect하려면 external 옵션을 명시해야 하며, true를 주더라도 javascript: URL은 계속 막힌다. 개발 서버가 모든 정적 자산에 access-control-allow-origin: *를 붙이던 동작도 없어지고 CORS는 Vite 미들웨어가 맡는다.
PART 04아직 남은 것 — 원격 함수
스벨트 팀이 "가장 신나 있는" 기능인 원격 함수(remote functions)는 3.0에서도 실험 플래그 뒤에 남았다. 클라이언트와 서버 사이 통신을 안전하고 타입 안전하게 처리하는 유틸리티 묶음으로, 팀은 RC 공지에서 이것이 기존 load 함수와 form action을 투박해 보이게 만든다고까지 표현했다. 원격 함수는 비동기 Svelte(Async Svelte)를 필요로 하는데 이 역시 아직 실험 플래그가 필요하다. 팀은 정식 블로그에서 원격 함수 안정화가 최우선 과제라고 밝혔다.
빌드 쪽에서는 Vite 8이 필수가 되면서 Rolldown 기반의 더 빠른 빌드를 얻는다. SvelteKit 3은 Vite 환경 API(Environment API)를 채택해 빌드 로직을 단순화했지만, FetchableDevEnvironment는 프레임워크가 떠안는 복잡도가 너무 크다며 지원하지 않기로 했다. 이 때문에 로컬 개발 중 클라우드플레어 워커스 바인딩에 접근하는 문제는 다른 방식으로 해결을 모색 중이라고 했다.
PART 05개발자가 지금 할 일
스벨트 팀은 11월 19~20일 슬로베니아 류블랴나에서 오프라인 행사 Svelte Summit을 열고 스벨트 10주년을 기념한다고 함께 알렸다.
자주 묻는 질문
SvelteKit 3으로 업그레이드하려면 무엇이 필요한가?
Node 22.17, TypeScript 6, Svelte 5.57.1, Vite 8.0.12, vite-plugin-svelte 7 이상이 필요하다. 그 뒤 npx sv migrate sveltekit-3를 실행하면 자동 변환과 함께 수동 처리 항목 목록을 받을 수 있다.
SvelteKit 3에서 svelte.config.js는 어떻게 되나?
더 이상 지원되지 않는다. 설정은 vite.config.ts에서 sveltekit() 플러그인에 넘기며, 기존 config.kit.* 옵션은 플러그인의 최상위 옵션이 된다.
$lib 대신 #lib를 쓸 때 주의할 점은?
#lib는 Node 서브패스 import라 경로가 모호하면 안 된다. #lib/foo가 아니라 #lib/foo.ts 또는 #lib/foo/index.ts처럼 파일 확장자까지 써야 한다.
SvelteKit 3에서 원격 함수(remote functions)를 쓸 수 있나?
아직 실험 플래그가 필요하다. 원격 함수는 비동기 Svelte를 요구하는데 이것도 실험 단계이며, 스벨트 팀은 안정화를 최우선 과제로 삼고 있다고 밝혔다.

댓글 0