# 문제 해결 가이드 - [SvelteKit](https://kit.svelte.dev/) - [WebSocket Hibernation](https://developers.cloudflare.com/durable-objects/best-practices/websockets/) - [Cloudflare Durable Objects](https://developers.cloudflare.com/durable-objects/) 4. **문서 참고**: 3. **Cloudflare Dashboard**: Workers & Pages에서 배포 상태 확인 2. **브라우저 콘솔**: F12를 눌러 JavaScript 오류 확인 1. **로그 확인**: `pnpm cf:tail`로 실시간 로그 확인 ## 도움이 필요하신가요? --- ``` pnpm build pnpm install rm -rf .svelte-kit node_modules ```bash ### 빌드 캐시 문제 ``` # 브라우저에서 Cloudflare 로그인 npx wrangler login ```bash ### Wrangler 인증 문제 ``` pnpm add -D @cloudflare/workers-types ```bash 그리고: ``` } } "types": ["@cloudflare/workers-types"] "compilerOptions": { { // tsconfig.json ```json **해결:** ``` Cannot find module 'cloudflare:workers' ``` ### TypeScript 타입 오류 ## 기타 문제 --- ``` const id = platform?.env.COUNTER.idFromName('global-counter'); // +server.ts ```typescript 3. **다른 Durable Object ID**: 같은 ID를 사용하는지 확인 2. **배포 환경**: 실제 Cloudflare에서는 영구 저장됨 1. **로컬 개발**: Wrangler의 로컬 storage는 임시적일 수 있음 이미 구현되어 있습니다! 만약 작동하지 않는다면: ### 해결 방법 ``` } }); } this.count = stored; if (stored !== undefined) { const stored = await this.ctx.storage.get('count'); // ✅ 복원 this.ctx.blockConcurrencyWhile(async () => { // ... constructor(ctx: DurableObjectState, env: Env) { } } this.broadcast(); await this.ctx.storage.put('count', this.count); // ✅ 저장 this.count++; if (data && data.type === 'increment') { async webSocketMessage(ws: WebSocket, message: ArrayBuffer | string) { // counter-do.ts ```typescript Durable Object Storage에 제대로 저장되고 있는지 확인: ### 확인 사항 페이지를 새로고침하거나 모든 클라이언트가 연결을 끊으면 카운트가 초기화됨. ### 문제 설명 ## 카운트가 저장되지 않는 문제 --- - Migration이 완료되었는지 확인 - Cloudflare Dashboard에서 Durable Objects 바인딩 확인 **배포 후:** - Wrangler가 Durable Objects를 에뮬레이션 - `pnpm dev` 대신 `pnpm cf:dev` 사용 **로컬 개발 시:** ### 해결 방법 ``` pnpm cf:tail # 다른 터미널에서 ```bash 4. **Wrangler 로그 확인** ``` // WebSocket 연결 로그 확인 // F12 → Console 탭에서 확인 ```javascript 3. **브라우저 콘솔 확인** - 배포: `wss://your-worker.workers.dev/api/counter` - 로컬: `ws://localhost:8787/api/counter` 2. **올바른 URL인지 확인** ``` pnpm cf:dev ```bash 1. **Wrangler Dev 실행 중인지 확인** ### 확인 사항 - 브라우저 콘솔에 WebSocket 오류 - "연결하기" 버튼 클릭 후 연결되지 않음 ### 문제 증상 ## WebSocket 연결 실패 --- 이제 `pnpm build`를 실행하면 자동으로 Worker가 패치됩니다. ``` } } "build": "vite build && node scripts/patch-worker.js" "scripts": { { ```json **package.json:** Post-build 스크립트 `scripts/patch-worker.js`를 사용하여 빌드 후 자동으로 Worker 파일에 Durable Object을 export하도록 패치합니다. ### 해결 방법 SvelteKit adapter-cloudflare가 생성하는 `_worker.js`에는 자동으로 Durable Object export가 포함되지 않습니다. ### 원인 ``` which are not exported in your entrypoint file: CounterDurableObject. ERROR: Your Worker depends on the following Durable Objects, ``` ### 문제 설명 ## 빌드 후 Durable Object Export 문제 --- 5. 첫 번째 탭에서도 접속자 수 2로 업데이트됨 4. "연결하기" 클릭 → 접속자 수: 2 (이제 정상 작동!) 3. 새 탭에서 같은 페이지 열기 2. "연결하기" 클릭 → 접속자 수: 1 1. 브라우저에서 첫 번째 탭 열기 ### 테스트 방법 4. **정확한 카운트**: `this.ctx.getWebSockets()`는 Cloudflare가 관리하는 실제 연결된 WebSocket 목록을 반환합니다 3. **WebSocket 연결은 유지**: 하지만 WebSocket 연결 자체는 Cloudflare가 유지하고 있습니다 2. **State 초기화**: Hibernation 후 재활성화될 때 `constructor`가 다시 실행되어 `this.sessions`가 빈 Map으로 초기화됩니다 1. **WebSocket Hibernation API**: Durable Object이 일정 시간 활동이 없으면 메모리에서 제거됩니다 ### 왜 이렇게 해야 하나요? ``` } // ... }); lastUpdate: this.lastUpdate online: connectedWebSockets.length, // ✅ 올바른 방법 count: this.count, const message = JSON.stringify({ const connectedWebSockets = this.ctx.getWebSockets(); private broadcast() { ```typescript **수정 후:** ``` } // ... }); lastUpdate: this.lastUpdate online: this.sessions.size, // ❌ 잘못된 방법 count: this.count, const message = JSON.stringify({ private broadcast() { ```typescript **수정 전:** `this.ctx.getWebSockets()`를 사용하여 실제 연결된 WebSocket 개수를 확인해야 합니다. ### 해결 방법 WebSocket Hibernation API를 사용할 때, Durable Object의 in-memory state (`this.sessions` Map)는 hibernation 후 초기화됩니다. 따라서 `this.sessions.size`는 정확한 접속자 수를 반영하지 못합니다. ### 원인 여러 클라이언트가 연결되어도 "실시간 접속자 수"가 1에서 증가하지 않음. ### 문제 설명 ## 실시간 접속자 수가 증가하지 않는 문제