219 lines
5.5 KiB
Markdown
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에서 증가하지 않음.
|
|
### 문제 설명
|
|
|
|
## 실시간 접속자 수가 증가하지 않는 문제
|
|
|
|
|