From 347a5cc598a0347c141f0e0029b675f2d4ab4cde Mon Sep 17 00:00:00 2001 From: kappa Date: Fri, 23 Jan 2026 12:50:54 +0900 Subject: [PATCH] refactor: remove unused launcher code - Remove old Server Launcher Modal from index.html (210 lines) - Remove launcher state variables and methods from app.js - Remove unused constants: LAUNCHER_PRICES, PLAN_SPECS, REGIONS, OS_LIST, PAYMENT_METHODS, DEPLOY_TIMING - Remove deprecated API methods for deleted functions - Preserve: wizard, pricing table, dashboard functionality Total reduction: ~440+ lines of unused code Co-Authored-By: Claude Opus 4.5 --- app.js | 427 +---------------------------------------------------- index.html | 211 -------------------------- 2 files changed, 6 insertions(+), 632 deletions(-) diff --git a/app.js b/app.js index 32793fb..6c790a3 100644 --- a/app.js +++ b/app.js @@ -51,66 +51,8 @@ const ApiService = { } }, - /** - * Health Check - 서버 상태 확인 - */ - async health() { - console.log('[API] Health check...'); - return this.request('/health'); - }, - - /** - * Instances 조회 - 클라우드 인스턴스 목록 - */ - async getInstances(params = {}) { - console.log('[API] Fetching instances...', params); - const query = new URLSearchParams(); - - // 파라미터 설정 - if (params.provider) query.set('provider', params.provider); - if (params.region) query.set('region', params.region); - if (params.min_vcpu) query.set('min_vcpu', params.min_vcpu); - if (params.max_vcpu) query.set('max_vcpu', params.max_vcpu); - if (params.min_memory_gb) query.set('min_memory_gb', params.min_memory_gb); - if (params.max_memory_gb) query.set('max_memory_gb', params.max_memory_gb); - if (params.max_price) query.set('max_price', params.max_price); - if (params.instance_family) query.set('instance_family', params.instance_family); - if (params.has_gpu !== undefined) query.set('has_gpu', params.has_gpu); - if (params.sort_by) query.set('sort_by', params.sort_by); - if (params.order) query.set('order', params.order); - if (params.limit) query.set('limit', params.limit); - if (params.offset) query.set('offset', params.offset); - - const queryString = query.toString(); - return this.request(`/instances${queryString ? '?' + queryString : ''}`); - }, - - /** - * Recommend - 기술 스택 기반 인스턴스 추천 - */ - async recommend(stack, scale = 'medium', budgetMax = null) { - console.log('[API] Getting recommendations...', { stack, scale, budgetMax }); - const body = { stack, scale }; - if (budgetMax) body.budget_max = budgetMax; - - return this.request('/recommend', { - method: 'POST', - body: JSON.stringify(body) - }); - }, - - /** - * Sync 트리거 - 프로바이더 데이터 동기화 (관리자용) - */ - async sync(provider = null) { - console.log('[API] Triggering sync...', { provider }); - const body = provider ? { provider } : {}; - - return this.request('/sync', { - method: 'POST', - body: JSON.stringify(body) - }); - } + // Removed: health(), getInstances(), recommend(), sync() + // These methods referenced deleted API functions (health.ts, instances.ts, recommend.ts) }; // 텔레그램 봇 URL 상수 @@ -133,48 +75,8 @@ const PRICING_DATA = { ] }; -// 런처 모달용 가격 - PRICING_DATA에서 파생 -const LAUNCHER_PRICES = Object.fromEntries( - PRICING_DATA.global.map(p => [p.plan, { - base: p.price, - seoul: PRICING_DATA.seoul.find(s => s.plan === p.plan)?.price || p.price - }]) -); - -// 플랜별 스펙 정보 - PRICING_DATA에서 파생 -const PLAN_SPECS = Object.fromEntries( - PRICING_DATA.global.map(p => [p.plan, `${p.vcpu} / ${p.ram} RAM`]) -); - -// 리전 정보 -const REGIONS = [ - { id: 'Seoul', flag: '🇰🇷', name: '서울', ping: '2ms' }, - { id: 'Tokyo', flag: '🇯🇵', name: '도쿄', ping: '35ms' }, - { id: 'Singapore', flag: '🇸🇬', name: '싱가포르', ping: '65ms' }, - { id: 'HongKong', flag: '🇭🇰', name: '홍콩', ping: '45ms' } -]; - -// OS 정보 -const OS_LIST = [ - { id: 'Debian 12', icon: '🐧', name: 'Debian 12' }, - { id: 'Ubuntu 24.04', icon: '🟠', name: 'Ubuntu 24.04' }, - { id: 'CentOS 9', icon: '🔵', name: 'CentOS 9' }, - { id: 'Alpine', icon: '🏔️', name: 'Alpine' } -]; - -// 결제 방식 -const PAYMENT_METHODS = [ - { id: 'monthly', name: '월간 결제', desc: '매월 자동 결제', discount: 0 }, - { id: 'yearly', name: '연간 결제', desc: '2개월 무료 (17% 할인)', discount: 17 } -]; - -// 배포 시뮬레이션 타이밍 상수 -const DEPLOY_TIMING = { - IMAGE_READY: 1500, - CONTAINER_CREATED: 3000, - NETWORK_CONFIGURED: 4500, - COMPLETE: 6000 -}; +// Removed: Old launcher constants (LAUNCHER_PRICES, PLAN_SPECS, REGIONS, OS_LIST, PAYMENT_METHODS, DEPLOY_TIMING) +// These were only used by the deprecated Server Launcher Modal // Mock 데이터 (API 없이 UI 테스트용) const MOCK_SERVERS = [ @@ -367,12 +269,6 @@ function calculateRecommendation(selectedStacks, scale) { */ function anvilApp() { return { - // 모달 상태 - launcherOpen: false, - launching: false, - wizardStep: 0, // 0: region, 1: plan, 2: os, 3: payment, 4: confirm, 5+: deploying - deployStep: 0, - // ============================================================ // 서버 추천 마법사 상태 // ============================================================ @@ -519,15 +415,6 @@ function anvilApp() { return this.telegram.user || this.webUser; }, - // 서버 구성 - config: { - region: null, - plan: null, - os: null, - payment: null, - telegram_id: null - }, - // 서버 목록 servers: [], loadingServers: false, @@ -548,22 +435,6 @@ function anvilApp() { apiLoading: false, apiError: null, - // 대화 메시지 - messages: [], - - // 배포 로그 - logs: [], - - // 데이터 접근자 - regions: REGIONS, - osList: OS_LIST, - paymentMethods: PAYMENT_METHODS, - - // 플랜 목록 (리전에 따라 다름) - get plans() { - return ['Micro', 'Starter', 'Pro', 'Business']; - }, - // 초기화 (텔레그램 연동 + 대시보드) init() { if (window.Telegram?.WebApp) { @@ -866,294 +737,8 @@ function anvilApp() { console.log('[Dashboard] View switched to:', view); }, - // 가격 조회 - getPrice(plan) { - const prices = LAUNCHER_PRICES[plan]; - if (!prices) return '0'; - const price = this.config.region === 'Seoul' ? prices.seoul : prices.base; - return price.toLocaleString('ko-KR'); - }, - - // 월간 가격 (할인 적용) - getFinalPrice() { - const prices = LAUNCHER_PRICES[this.config.plan]; - if (!prices) return 0; - let price = this.config.region === 'Seoul' ? prices.seoul : prices.base; - if (this.config.payment === 'yearly') { - price = Math.round(price * 0.83); // 17% 할인 - } - return price; - }, - - // 플랜 스펙 조회 - getPlanSpec(plan) { - return PLAN_SPECS[plan] || ''; - }, - - // 리전 선택 - selectRegion(region) { - this.config.region = region.id; - this.addMessage('user', `${region.flag} ${region.name}`); - this.wizardStep = 1; - setTimeout(() => this.addMessage('bot', '어떤 사양이 필요하신가요?'), 300); - }, - - // 플랜 선택 - selectPlan(plan) { - this.config.plan = plan; - this.addMessage('user', `${plan} (${this.getPlanSpec(plan)})`); - this.wizardStep = 2; - setTimeout(() => this.addMessage('bot', '어떤 운영체제를 설치할까요?'), 300); - }, - - // OS 선택 - selectOS(os) { - this.config.os = os.id; - this.addMessage('user', `${os.icon} ${os.name}`); - this.wizardStep = 3; - setTimeout(() => this.addMessage('bot', '결제 방식을 선택해주세요.'), 300); - }, - - // 결제 방식 선택 - selectPayment(payment) { - this.config.payment = payment.id; - this.addMessage('user', payment.name); - this.wizardStep = 4; - setTimeout(() => this.addMessage('bot', '구성을 확인하고 서버를 생성해주세요! 🚀'), 300); - }, - - // 메시지 추가 - addMessage(type, text) { - this.messages.push({ type, text, time: new Date() }); - // 스크롤 하단으로 - this.$nextTick(() => { - const container = document.getElementById('chat-container'); - if (container) container.scrollTop = container.scrollHeight; - }); - }, - - // 이전 단계로 - goBack() { - if (this.wizardStep > 0 && !this.launching) { - // 마지막 2개 메시지 제거 (사용자 선택 + 봇 질문) - this.messages.pop(); - this.messages.pop(); - this.wizardStep--; - - // 선택 초기화 - if (this.wizardStep === 0) this.config.region = null; - else if (this.wizardStep === 1) this.config.plan = null; - else if (this.wizardStep === 2) this.config.os = null; - else if (this.wizardStep === 3) this.config.payment = null; - } - }, - - // 서버 배포 시작 - startLaunch() { - // 텔레그램 사용자 ID 추가 - if (this.telegram.user) { - this.config.telegram_id = this.telegram.user.id; - } - - this.launching = true; - this.wizardStep = 5; - this.deployStep = 1; - this.logs = [ - '🔄 배포를 시작합니다...', - `📍 ${this.config.region} 리전 노드 선택 중...`, - `📦 ${this.config.os} 이미지 준비 중...` - ]; - - // 디버그: config 출력 - console.log('[Server Launch] Config:', this.config); - - setTimeout(() => { - this.logs.push('✅ 이미지 준비 완료'); - this.logs.push('🔧 컨테이너 인스턴스 생성 중...'); - this.deployStep = 2; - }, DEPLOY_TIMING.IMAGE_READY); - - setTimeout(() => { - this.logs.push('✅ 컨테이너 생성 완료'); - this.logs.push('🌐 네트워크 및 방화벽 구성 중...'); - this.deployStep = 3; - }, DEPLOY_TIMING.CONTAINER_CREATED); - - setTimeout(() => { - const randomIP = Math.floor(Math.random() * 254 + 1); - this.logs.push(`✅ IP 할당 완료: 45.12.89.${randomIP}`); - this.logs.push('⚙️ 시스템 서비스 시작 중...'); - this.deployStep = 4; - }, DEPLOY_TIMING.NETWORK_CONFIGURED); - - setTimeout(() => { - this.launching = false; - this.deployStep = 5; - this.logs.push('🎉 서버가 활성화되었습니다!'); - - // 대시보드 모드에서는 서버 목록 새로고침 - if (this.dashboardMode) { - setTimeout(() => { - this.fetchServers(); - this.fetchStats(); - }, 1000); - } - }, DEPLOY_TIMING.COMPLETE); - }, - - // 런처 열기 (대시보드용 추가 기능) - openLauncher() { - this.launcherOpen = true; - this.messages = [{ type: 'bot', text: '어느 리전에 서버를 생성할까요?', time: new Date() }]; - - // 대시보드 모드에서는 서버 생성 후 목록 새로고침 - if (this.dashboardMode) { - console.log('[Dashboard] Launcher opened from dashboard'); - } - }, - - // 런처 초기화 - resetLauncher() { - this.launcherOpen = false; - this.launching = false; - this.wizardStep = 0; - this.deployStep = 0; - this.config = { region: null, plan: null, os: null, payment: null, telegram_id: null }; - this.messages = []; - this.logs = []; - }, - - // ESC 키로 모달 닫기 - handleKeydown(event) { - if (event.key === 'Escape' && this.launcherOpen && !this.launching) { - this.resetLauncher(); - } - }, - - // ============================================================ - // API 연동 메서드 - // ============================================================ - - // API 테스트 결과 - apiTestResult: null, - apiTestLoading: false, - - // API 인스턴스 데이터 - cloudInstances: [], - cloudInstancesLoading: false, - cloudInstancesError: null, - cloudInstancesFilter: { - provider: '', - min_vcpu: '', - max_price: '', - sort_by: 'monthly_price', - order: 'asc', - limit: 20 - }, - - // API Health Check 테스트 - async testApiHealth() { - console.log('[App] Testing API health...'); - this.apiTestLoading = true; - this.apiTestResult = null; - - try { - const result = await ApiService.health(); - this.apiTestResult = { - success: true, - data: result, - message: `API 정상 (${result.status})` - }; - console.log('[App] API health check success:', result); - } catch (error) { - this.apiTestResult = { - success: false, - error: error.message, - message: `API 오류: ${error.message}` - }; - console.error('[App] API health check failed:', error); - } finally { - this.apiTestLoading = false; - } - }, - - // 클라우드 인스턴스 목록 조회 - async fetchCloudInstances() { - console.log('[App] Fetching cloud instances...'); - this.cloudInstancesLoading = true; - this.cloudInstancesError = null; - - try { - const params = {}; - if (this.cloudInstancesFilter.provider) params.provider = this.cloudInstancesFilter.provider; - if (this.cloudInstancesFilter.min_vcpu) params.min_vcpu = parseInt(this.cloudInstancesFilter.min_vcpu); - if (this.cloudInstancesFilter.max_price) params.max_price = parseFloat(this.cloudInstancesFilter.max_price); - if (this.cloudInstancesFilter.sort_by) params.sort_by = this.cloudInstancesFilter.sort_by; - if (this.cloudInstancesFilter.order) params.order = this.cloudInstancesFilter.order; - params.limit = this.cloudInstancesFilter.limit || 20; - - const result = await ApiService.getInstances(params); - - if (result.success && result.data) { - this.cloudInstances = result.data.instances || []; - console.log('[App] Cloud instances loaded:', this.cloudInstances.length); - } else { - throw new Error(result.error?.message || 'Unknown error'); - } - } catch (error) { - this.cloudInstancesError = error.message; - console.error('[App] Failed to fetch cloud instances:', error); - } finally { - this.cloudInstancesLoading = false; - } - }, - - // 추천 인스턴스 조회 - recommendResult: null, - recommendLoading: false, - recommendStack: ['nginx', 'nodejs'], - recommendScale: 'medium', - - async getRecommendation() { - console.log('[App] Getting recommendation...'); - this.recommendLoading = true; - this.recommendResult = null; - - try { - const result = await ApiService.recommend(this.recommendStack, this.recommendScale); - - if (result.success !== false) { - this.recommendResult = { - success: true, - data: result - }; - console.log('[App] Recommendation received:', result); - } else { - throw new Error(result.error?.message || 'Recommendation failed'); - } - } catch (error) { - this.recommendResult = { - success: false, - error: error.message - }; - console.error('[App] Recommendation failed:', error); - } finally { - this.recommendLoading = false; - } - }, - - // 메모리 포맷팅 (MB to GB) - formatMemory(mb) { - if (mb >= 1024) { - return (mb / 1024).toFixed(1) + ' GB'; - } - return mb + ' MB'; - }, - - // 가격 포맷팅 (USD) - formatUsd(price) { - return '$' + price.toFixed(2); - } + // Removed: API test methods (testApiHealth, fetchCloudInstances, getRecommendation) + // These referenced deleted API functions }; } diff --git a/index.html b/index.html index 717a6c1..30547d0 100644 --- a/index.html +++ b/index.html @@ -1042,217 +1042,6 @@ - - - -