dd/PROJECT_STRUCTURE.md

210 lines
6.2 KiB
Markdown

# 프로젝트 구조 및 설명
```
dd/
├── src/
│ ├── lib/
│ │ └── counter-do.ts # Durable Object 구현체
│ ├── routes/
│ │ ├── api/counter/
│ │ │ └── +server.ts # WebSocket 엔드포인트 (API Route)
│ │ ├── +layout.svelte # 전역 레이아웃
│ │ └── +page.svelte # 메인 페이지 (실시간 카운터 UI)
│ ├── app.d.ts # TypeScript 전역 타입 정의
│ ├── app.css # Tailwind CSS 글로벌 스타일
│ ├── app.html # HTML 템플릿
│ └── hooks.server.ts # SvelteKit 서버 훅 (Durable Object export)
├── static/
│ └── robots.txt # SEO용 robots.txt
├── .svelte-kit/ # SvelteKit 빌드 출력
│ ├── cloudflare/
│ │ ├── _worker.js # 생성된 Worker 파일
│ │ └── _app/ # 클라이언트 자산
│ └── output/
│ ├── client/ # 클라이언트 빌드
│ └── server/ # 서버 빌드
├── wrangler.jsonc # Cloudflare Workers 설정
├── svelte.config.js # SvelteKit 설정
├── vite.config.ts # Vite 설정
├── tailwind.config.ts # Tailwind CSS 설정
├── tsconfig.json # TypeScript 설정
├── package.json # 프로젝트 의존성
├── README.md # 프로젝트 문서
├── QUICKSTART.md # 빠른 시작 가이드
└── DEPLOYMENT.md # 배포 가이드
```
## 주요 파일 설명
### 1. `src/lib/counter-do.ts` - Durable Object
Cloudflare Durable Objects 클래스로, 다음을 담당합니다:
- WebSocket 연결 관리
- 카운터 상태 저장 및 업데이트
- 모든 클라이언트에 상태 브로드캐스트
- 영구 저장소(Durable Objects Storage)에 데이터 저장
```typescript
export class CounterDurableObject {
// WebSocket 세션 관리
// 카운트 상태 관리
// fetch() - WebSocket 업그레이드 처리
// webSocketMessage() - 클라이언트 메시지 처리
// webSocketClose() - 연결 종료 처리
// broadcast() - 모든 클라이언트에 상태 전송
}
```
### 2. `src/routes/api/counter/+server.ts` - API 라우트
SvelteKit API 엔드포인트로 WebSocket 연결 요청을 Durable Object로 전달합니다:
```typescript
export const GET: RequestHandler = async ({ request, platform }) => {
const id = platform?.env.COUNTER.idFromName('global-counter');
const stub = platform.env.COUNTER.get(id);
return stub.fetch(request);
};
```
### 3. `src/routes/+page.svelte` - 클라이언트 UI
실시간 카운터 UI를 렌더링하고 WebSocket을 통해 서버와 통신합니다:
```svelte
<script lang="ts">
let count = $state(0);
let online = $state(0);
let ws = $state<WebSocket | null>(null);
function connectWebSocket() { /* ... */ }
function incrementCount() { /* ... */ }
function resetCount() { /* ... */ }
</script>
```
### 4. `src/hooks.server.ts` - 서버 훅
Durable Object을 Worker에서 사용할 수 있도록 export합니다:
```typescript
export { CounterDurableObject } from '$lib/counter-do';
```
### 5. `wrangler.jsonc` - Cloudflare 설정
Worker 및 Durable Objects 바인딩을 설정합니다:
```jsonc
{
"durable_objects": {
"bindings": [{
"name": "COUNTER",
"class_name": "CounterDurableObject"
}]
},
"migrations": [...]
}
```
## 데이터 흐름
### WebSocket 연결 흐름
```
클라이언트 브라우저
↓ (WebSocket 연결 요청)
/api/counter (+server.ts)
↓ (Durable Object ID 생성)
Durable Object Stub
↓ (fetch() 호출)
CounterDurableObject
↓ (WebSocket 페어 생성)
클라이언트 ← → 서버 (양방향 통신)
```
### 카운트 증가 흐름
```
클라이언트: 버튼 클릭
↓ (WebSocket 메시지)
Durable Object: webSocketMessage()
↓ (카운트 증가)
Durable Object Storage: 저장
↓ (broadcast())
모든 연결된 클라이언트: 실시간 업데이트
```
## 기술 스택
### 프론트엔드
- **Svelte 5**: 최신 Svelte 5의 Runes API 사용
- **Tailwind CSS 4**: 유틸리티 우선 CSS 프레임워크
- **TypeScript**: 타입 안전성
### 백엔드
- **SvelteKit**: 풀스택 웹 프레임워크
- **Cloudflare Workers**: 서버리스 엣지 컴퓨팅
- **Durable Objects**: 상태 저장 및 협업
- **WebSocket Hibernation API**: 저비용 실시간 통신
### 빌드 & 배포
- **Vite**: 빠른 빌드 도구
- **Wrangler**: Cloudflare Workers CLI
- **@sveltejs/adapter-cloudflare**: SvelteKit → Cloudflare 어댑터
## 개발 워크플로우
### 로컬 개발
```bash
pnpm dev # Vite 개발 서버
pnpm build # 프로덕션 빌드
pnpm cf:dev # Wrangler 로컬 서버
```
### 배포
```bash
pnpm deploy # Cloudflare에 배포
pnpm cf:tail # 실시간 로그
```
### 테스트
```bash
pnpm check # TypeScript 및 Svelte 체크
pnpm format # Prettier 포맷팅
pnpm lint # 린팅 체크
```
## 환경 변수
현재 프로젝트는 환경 변수를 사용하지 않습니다. 모든 설정은 `wrangler.jsonc`에 있습니다.
필요한 경우 `.env` 파일을 추가하고 다음과 같이 사용할 수 있습니다:
```env
# .env
VITE_API_URL=https://your-api.com
```
```typescript
// 사용
import { env } from '$env/dynamic/public';
console.log(env.VITE_API_URL);
```
## 확장 아이디어
1. **여러 카운터 룸**
- URL 파라미터로 룸 ID 전달
- 각 룸마다 독립적인 Durable Object 인스턴스
2. **사용자 인증**
- Cloudflare Access 통합
- 사용자별 권한 관리
3. **영속적 히스토리**
- SQLite (D1) 통합
- 카운트 변경 로그
4. **실시간 채팅**
- WebSocket을 활용한 채팅 기능
- 메시지 브로드캐스팅
5. **분석 및 모니터링**
- Cloudflare Analytics 통합
- 커스텀 메트릭 수집