# ๐Ÿค– Cloudflare Workers ํ…”๋ ˆ๊ทธ๋žจ AI ๋ด‡ > **Cloudflare Workers + D1 + OpenAI**๋ฅผ ํ™œ์šฉํ•œ ์„œ๋ฒ„๋ฆฌ์Šค ์•„ํ‚คํ…์ฒ˜ ๊ธฐ๋ฐ˜์˜ ์ง€๋Šฅํ˜• ํ…”๋ ˆ๊ทธ๋žจ ๋ด‡์ž…๋‹ˆ๋‹ค. > ์‚ฌ์šฉ์ž๋ณ„ ํ”„๋กœํ•„์„ ์ž๋™์œผ๋กœ ์ƒ์„ฑํ•˜๊ณ  ๊ธฐ์–ตํ•˜๋ฉฐ, ์˜ˆ์น˜๊ธˆ ๊ด€๋ฆฌ ๋ฐ ๋„๋ฉ”์ธ ๋“ฑ๋ก ๋“ฑ์˜ ๋ณต์žกํ•œ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ![License](https://img.shields.io/badge/license-MIT-blue.svg) ![TypeScript](https://img.shields.io/badge/TypeScript-5.0-blue) ![Cloudflare Workers](https://img.shields.io/badge/Cloudflare-Workers-orange) ## ๐Ÿ“š ๋ฌธ์„œ ์•ˆ๋‚ด - **[์‚ฌ์šฉ์ž ๊ฐ€์ด๋“œ (User Guide)](./docs/USER_GUIDE.md)**: ๋ด‡ ์‚ฌ์šฉ๋ฒ•, ๋ช…๋ น์–ด, ์˜ˆ์น˜๊ธˆ/๋„๋ฉ”์ธ ๊ธฐ๋Šฅ ์„ค๋ช… - **[์‹œ์Šคํ…œ ์•„ํ‚คํ…์ฒ˜ (Architecture)](./docs/ARCHITECTURE.md)**: ๊ธฐ์ˆ  ๊ตฌ์กฐ, ๋ฐ์ดํ„ฐ ํ๋ฆ„, ํ”„๋กœํ•„ ์‹œ์Šคํ…œ ์ƒ์„ธ - **[๊ฐœ๋ฐœ์ž ๊ฐ€์ด๋“œ (Dev Guide)](./CLAUDE.md)**: ๊ฐœ๋ฐœ ํ™˜๊ฒฝ ์„ค์ •, ์ปจ๋ฒค์…˜, ํŠธ๋Ÿฌ๋ธ”์ŠˆํŒ… --- ## โœจ ์ฃผ์š” ๊ธฐ๋Šฅ * ๐Ÿง  **AI ๊ธฐ๋ฐ˜ ๊ฐœ์ธํ™”**: ๋Œ€ํ™” ๋‚ด์šฉ์„ ๋ถ„์„ํ•˜์—ฌ ์‚ฌ์šฉ์ž์˜ ๊ด€์‹ฌ์‚ฌ์™€ ๋งฅ๋ฝ์„ ๊ธฐ์–ตํ•˜๋Š” **๋™์  ํ”„๋กœํ•„ ์‹œ์Šคํ…œ** * ๐Ÿ›  **Function Calling**: ๋‚ ์”จ, ๊ฒ€์ƒ‰, ๊ณ„์‚ฐ, ์‹œ๊ฐ„ ๋“ฑ ๋‹ค์–‘ํ•œ ๋„๊ตฌ๋ฅผ ์ž์—ฐ์–ด๋กœ ํ˜ธ์ถœ * ๐Ÿ’ฐ **์˜ˆ์น˜๊ธˆ ์‹œ์Šคํ…œ**: ์€ํ–‰ SMS ์ž๋™ ํŒŒ์‹ฑ(AI ํด๋ฐฑ ์ง€์›) ๋ฐ ์–‘๋ฐฉํ–ฅ ๋งค์นญ์„ ํ†ตํ•œ ์ž๋™ ์ถฉ์ „ * ๐ŸŒ **๋„๋ฉ”์ธ ๊ด€๋ฆฌ**: ๋„๋ฉ”์ธ ๊ฒ€์ƒ‰, ์ถ”์ฒœ(AI), ๊ฐ€๊ฒฉ ์กฐํšŒ, ๋“ฑ๋ก, DNS ๊ด€๋ฆฌ ํ†ตํ•ฉ * โšก **์„œ๋ฒ„๋ฆฌ์Šค**: Cloudflare Workers ์œ„์—์„œ ๋™์ž‘ํ•˜์—ฌ ๋ณ„๋„์˜ ์„œ๋ฒ„ ๊ด€๋ฆฌ ๋ถˆํ•„์š” ### ๐Ÿš€ ์„ฑ๋Šฅ ์ตœ์ ํ™” * **N+1 ์ฟผ๋ฆฌ ์ œ๊ฑฐ**: Cron ์ž‘์—… 99% ์ฟผ๋ฆฌ ๊ฐ์†Œ (100๊ฑด: 101 โ†’ 1 ์ฟผ๋ฆฌ) * **๋ณ‘๋ ฌ API ํ˜ธ์ถœ**: ๋„๋ฉ”์ธ ์ถ”์ฒœ 80% ์†๋„ ํ–ฅ์ƒ * **KV ์บ์‹ฑ**: TLD ๊ฐ€๊ฒฉ 1์‹œ๊ฐ„ ์บ์‹ฑ์œผ๋กœ ์ค‘๋ณต ์กฐํšŒ ๋ฐฉ์ง€ * **Circuit Breaker**: OpenAI API ์žฅ์•  ์‹œ ์ž๋™ ์ฐจ๋‹จ ๋ฐ ๋ณต๊ตฌ * **Retry ๋กœ์ง**: 15๊ฐœ ์™ธ๋ถ€ API์— ์ง€์ˆ˜ ๋ฐฑ์˜คํ”„ + ์ง€ํ„ฐ ์ ์šฉ --- ## ๐Ÿš€ ๋น ๋ฅธ ์‹œ์ž‘ (๋ฐฐํฌ ๊ฐ€์ด๋“œ) ### 1. ํ™˜๊ฒฝ ์„ค์ • ```bash # ์˜์กด์„ฑ ์„ค์น˜ npm install # Wrangler ๋กœ๊ทธ์ธ npx wrangler login ``` ### 2. ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ƒ์„ฑ ```bash npx wrangler d1 create telegram-conversations npx wrangler d1 execute telegram-conversations --file=schema.sql ``` *์ƒ์„ฑ๋œ `database_id`๋ฅผ `wrangler.toml`์— ๋ฐ˜์˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.* ### 3. KV Namespace ์ƒ์„ฑ ```bash # Rate Limiting์šฉ KV Namespace ์ƒ์„ฑ (ํ•„์ˆ˜) npx wrangler kv:namespace create RATE_LIMIT_KV # ์ถœ๋ ฅ๋œ id๋ฅผ wrangler.toml์˜ [[kv_namespaces]] ์„น์…˜์— ์ž…๋ ฅ ``` ### 4. ํ™˜๊ฒฝ๋ณ€์ˆ˜ ์„ค์ • #### ํ•„์ˆ˜ Secrets ```bash # Telegram Bot ์„ค์ • npx wrangler secret put BOT_TOKEN # @BotFather์—์„œ ๋ฐœ๊ธ‰ npx wrangler secret put WEBHOOK_SECRET # ์ž„์˜์˜ ๊ฐ•๋ ฅํ•œ ๋ฌธ์ž์—ด (ํ•„์ˆ˜!) # OpenAI API npx wrangler secret put OPENAI_API_KEY # OpenAI API ํ‚ค ``` #### ์„ ํƒ์  Secrets (๊ธฐ๋Šฅ๋ณ„) ```bash # ๋„๋ฉ”์ธ ๊ด€๋ จ (๋„๋ฉ”์ธ ๊ธฐ๋Šฅ ์‚ฌ์šฉ ์‹œ) npx wrangler secret put NAMECHEAP_API_KEY # namecheap-api ๋ž˜ํผ ์ธ์ฆ npx wrangler secret put NAMECHEAP_API_KEY_INTERNAL # Namecheap ์‹ค์ œ API ํ‚ค # ๊ฒ€์ƒ‰ (์›น ๊ฒ€์ƒ‰ ๊ธฐ๋Šฅ ์‚ฌ์šฉ ์‹œ) npx wrangler secret put BRAVE_API_KEY # Brave Search API ํ‚ค # ์˜ˆ์น˜๊ธˆ API (namecheap-api ์—ฐ๋™ ์‹œ) npx wrangler secret put DEPOSIT_API_SECRET # ์™ธ๋ถ€ ์„œ๋น„์Šค ์—ฐ๋™์šฉ ``` #### ํ™˜๊ฒฝ๋ณ„ ์„ค์ • (์„ ํƒ) `wrangler.toml`์˜ ํ™˜๊ฒฝ๋ณ€์ˆ˜๋Š” ๊ธฐ๋ณธ๊ฐ’์ด ์„ค์ •๋˜์–ด ์žˆ์–ด ์ƒ๋žต ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. ํ™˜๊ฒฝ๋ณ„๋กœ ๋‹ค๋ฅธ ์—”๋“œํฌ์ธํŠธ๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๋ฉด overrideํ•˜์„ธ์š”: ```toml [vars] OPENAI_API_BASE = "https://your-custom-gateway.com/openai" NAMECHEAP_API_URL = "https://your-api.example.com" ``` **์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ํ™˜๊ฒฝ๋ณ€์ˆ˜:** - `OPENAI_API_BASE` - OpenAI API Gateway - `NAMECHEAP_API_URL` - Namecheap API ๋ž˜ํผ - `WHOIS_API_URL` - WHOIS ์กฐํšŒ ์„œ๋น„์Šค - `CONTEXT7_API_BASE` - ๋ฌธ์„œ ์กฐํšŒ API - `BRAVE_API_BASE` - ๊ฒ€์ƒ‰ API - `WTTR_IN_URL` - ๋‚ ์”จ API - `HOSTING_SITE_URL` - ๊ณต์‹ ์›น์‚ฌ์ดํŠธ ### 5. ๋ฐฐํฌ #### ๋ฐฐํฌ ์ „ ์ฒดํฌ๋ฆฌ์ŠคํŠธ ```bash # 1. ๋กœ์ปฌ ํ…Œ์ŠคํŠธ npm run dev # 2. TypeScript ์ปดํŒŒ์ผ ํ™•์ธ npx tsc --noEmit # 3. ํ™˜๊ฒฝ๋ณ€์ˆ˜ ํ™•์ธ npx wrangler secret list # 4. KV Namespace ํ™•์ธ npx wrangler kv:namespace list ``` #### ๋ฐฐํฌ ์‹คํ–‰ ```bash npm run deploy ``` #### ๋ฐฐํฌ ํ›„ ํ™•์ธ ```bash # Health check curl https://telegram-summary-bot.kappa-d8e.workers.dev/health # Webhook ์ƒํƒœ curl https://telegram-summary-bot.kappa-d8e.workers.dev/webhook-info # ์‹ค์‹œ๊ฐ„ ๋กœ๊ทธ npm run tail ``` ### 6. Webhook ์—ฐ๊ฒฐ ```bash # ์›นํ›… ์„ค์ • (๋ฐฐํฌ๋œ URL ์‚ฌ์šฉ) curl https:///setup-webhook ``` #### โš ๏ธ ์ฃผ์˜์‚ฌํ•ญ - **WEBHOOK_SECRET ํ•„์ˆ˜**: ๋ฏธ์„ค์ • ์‹œ ๋ชจ๋“  webhook ์š”์ฒญ์ด ๊ฑฐ๋ถ€๋ฉ๋‹ˆ๋‹ค. - **KV Namespace ํ•„์ˆ˜**: ๋ฏธ์ƒ์„ฑ ์‹œ Rate Limiting์ด ๋น„ํ™œ์„ฑํ™”๋˜์–ด DoS ๊ณต๊ฒฉ์— ์ทจ์•ฝํ•ฉ๋‹ˆ๋‹ค. - **ํ™˜๊ฒฝ๋ณ€์ˆ˜ ๊ธฐ๋ณธ๊ฐ’**: ๋Œ€๋ถ€๋ถ„์˜ ์™ธ๋ถ€ API URL์€ ๊ธฐ๋ณธ๊ฐ’์ด ์„ค์ •๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. ํ”„๋กœ๋•์…˜ ํ™˜๊ฒฝ์—์„œ๋Š” ๊ธฐ๋ณธ๊ฐ’์„ ๊ทธ๋Œ€๋กœ ์‚ฌ์šฉํ•˜๊ฑฐ๋‚˜, ํ•„์š”์‹œ์—๋งŒ overrideํ•˜์„ธ์š”. --- ## ๐Ÿ“ก API Documentation ๋ณธ ํ”„๋กœ์ ํŠธ๋Š” ์™ธ๋ถ€ ์„œ๋น„์Šค ์—ฐ๋™์„ ์œ„ํ•œ REST API๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. **์™„์ „ํ•œ OpenAPI ๋ฌธ์„œ**: [`openapi.yaml`](./openapi.yaml) ### ์ฃผ์š” ์—”๋“œํฌ์ธํŠธ | ์—”๋“œํฌ์ธํŠธ | ๋ฉ”์„œ๋“œ | ์ธ์ฆ | ์šฉ๋„ | |-----------|--------|------|------| | `/health` | GET | None | Health check | | `/api/contact` | POST | CORS | ์›น์‚ฌ์ดํŠธ ๋ฌธ์˜ ํผ | | `/api/deposit/balance` | GET | API Key | ์ž”์•ก ์กฐํšŒ (Internal) | | `/api/deposit/deduct` | POST | API Key | ์ž”์•ก ์ฐจ๊ฐ (Internal) | | `/api/metrics` | GET | Bearer | ์‹œ์Šคํ…œ ๋ชจ๋‹ˆํ„ฐ๋ง | ### ์ธ์ฆ ๋ฐฉ์‹ - **API Key**: `X-API-Key` ํ—ค๋” (Deposit API) - **Bearer Token**: `Authorization: Bearer {token}` (Metrics API) - **CORS**: `hosting.anvil.it.com`๋งŒ ํ—ˆ์šฉ (Contact Form) ### ๋ฌธ์„œ ๋ณด๊ธฐ ```bash # Swagger UI (๋กœ์ปฌ) npx swagger-ui-watcher openapi.yaml # HTML ๋ฌธ์„œ ์ƒ์„ฑ npx redoc-cli bundle openapi.yaml -o docs/api.html # ์ŠคํŽ™ ๊ฒ€์ฆ npx @apidevtools/swagger-cli validate openapi.yaml ``` ### External Consumers - **namecheap-api**: ๋„๋ฉ”์ธ ๋“ฑ๋ก ์‹œ ์˜ˆ์น˜๊ธˆ ์กฐํšŒ/์ฐจ๊ฐ - **hosting.anvil.it.com**: ์›น์‚ฌ์ดํŠธ ๋ฌธ์˜ ํผ ์ œ์ถœ - **Monitoring Tools**: Circuit Breaker ์ƒํƒœ ์กฐํšŒ ์ž์„ธํ•œ ๋‚ด์šฉ์€ [OpenAPI Specification](./openapi.yaml)์„ ์ฐธ์กฐํ•˜์„ธ์š”. --- ## ๐Ÿงช ํ…Œ์ŠคํŠธ ### ์ž๋™ํ™”๋œ ๋‹จ์œ„ ํ…Œ์ŠคํŠธ ํ”„๋กœ์ ํŠธ๋Š” **Vitest**์™€ **Miniflare**๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ Cloudflare Workers ํ™˜๊ฒฝ์—์„œ ๋‹จ์œ„ ํ…Œ์ŠคํŠธ๋ฅผ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค. #### ํ…Œ์ŠคํŠธ ์‹คํ–‰ ```bash # ์˜์กด์„ฑ ์„ค์น˜ npm install # ๋ชจ๋“  ํ…Œ์ŠคํŠธ ์‹คํ–‰ npm test # Watch ๋ชจ๋“œ (๊ฐœ๋ฐœ ์ค‘) npm run test:watch # ์ปค๋ฒ„๋ฆฌ์ง€ ๋ฆฌํฌํŠธ npm run test:coverage ``` #### ํ…Œ์ŠคํŠธ ๋ฒ”์œ„ **deposit-agent.ts** (์˜ˆ์น˜๊ธˆ ์‹œ์Šคํ…œ): - โœ… ์Œ์ˆ˜/0์› ๊ธˆ์•ก ๊ฑฐ๋ถ€ - โœ… ๋™์‹œ์„ฑ ์ฒ˜๋ฆฌ ์•ˆ์ „์„ฑ - โœ… Batch ๋ถ€๋ถ„ ์‹คํŒจ ์ฒ˜๋ฆฌ - โœ… ์ž…๊ธˆ์ž๋ช… 7๊ธ€์ž ๋งค์นญ ๋กœ์ง - โœ… ๊ด€๋ฆฌ์ž ๊ถŒํ•œ ๊ฒ€์ฆ - โœ… ๊ฑฐ๋ž˜ ์ƒํƒœ ๊ฒ€์ฆ **ํ…Œ์ŠคํŠธ ํŒŒ์ผ ์œ„์น˜**: - `tests/deposit-agent.test.ts` - ์˜ˆ์น˜๊ธˆ ์‹œ์Šคํ…œ ํ…Œ์ŠคํŠธ (50+ test cases) - `vitest.config.ts` - Vitest ์„ค์ • (Miniflare ํ™˜๊ฒฝ) - `tests/setup.ts` - D1 Database ์ดˆ๊ธฐํ™” ๋ฐ ํ—ฌํผ ํ•จ์ˆ˜ #### ํ…Œ์ŠคํŠธ ์•„ํ‚คํ…์ฒ˜ - **ํ™˜๊ฒฝ**: Miniflare (in-memory SQLite) - **๋ชจํ‚น**: D1 Database, KV Namespace, ํ™˜๊ฒฝ ๋ณ€์ˆ˜ - **์ปค๋ฒ„๋ฆฌ์ง€**: V8 Coverage Provider - **์‹คํ–‰ ์‹œ๊ฐ„**: <10์ดˆ (์ „์ฒด ํ…Œ์ŠคํŠธ ์Šค์œ„ํŠธ) #### ์ˆ˜๋™ ํ…Œ์ŠคํŠธ ์ž๋™ํ™”๋˜์ง€ ์•Š์€ ๊ธฐ๋Šฅ์˜ ์ˆ˜๋™ ํ…Œ์ŠคํŠธ ์˜ˆ์ œ: - `src/services/__test__/notification.test.ts` - ๊ด€๋ฆฌ์ž ์•Œ๋ฆผ ์‹œ์Šคํ…œ - `src/utils/__test__/logger.test.ts` - ๊ตฌ์กฐํ™”๋œ ๋กœ๊น… --- ## ๐Ÿ›  ๊ธฐ์ˆ  ์Šคํƒ | ๋ถ„๋ฅ˜ | ๊ธฐ์ˆ  | ๋น„๊ณ  | |------|------|------| | **Runtime** | Cloudflare Workers | Serverless | | **DB** | Cloudflare D1 | SQLite | | **Cache** | Cloudflare KV | Rate Limiting | | **AI** | OpenAI GPT-4o-mini | Logic & Tools | | **Fallback** | Workers AI (Llama 3) | Backup AI | | **Testing** | Vitest + Miniflare | Unit Tests | --- ## ๐Ÿค ๊ธฐ์—ฌ ๋ฐ ๋ฌธ์˜ ๋ฒ„๊ทธ ์‹ ๊ณ ๋‚˜ ๊ธฐ๋Šฅ ์ œ์•ˆ์€ Issue๋ฅผ ๋“ฑ๋กํ•ด์ฃผ์„ธ์š”. ์†Œ์Šค ์ฝ”๋“œ๋Š” **[Gitea](https://gitea.anvil.it.com/kaffa/telegram-bot-workers)**์—์„œ ๊ด€๋ฆฌ๋ฉ๋‹ˆ๋‹ค.