dd/TROUBLESHOOTING.md

219 lines
5.5 KiB
Markdown

# 문제 해결 가이드
- [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<number>('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에서 증가하지 않음.
### 문제 설명
## 실시간 접속자 수가 증가하지 않는 문제