Skip to main content
Glama
revenue-simulation.ts10.2 kB
// 매출 시뮬레이션 Tool // 업종별, 지역별, 시간대별 예상 매출 시뮬레이션 // 출처: 소상공인마당, 통계청, 업종별 평균 데이터 기반 import { DISCLAIMERS } from "../constants.js"; import type { ApiResult } from "../types.js"; import { normalizeBusinessType, normalizeRegion, REGIONAL_MULTIPLIER } from "../data/startup-cost-data.js"; // 업종별 기본 일 매출 (15평, 1인 운영 기준, 단위: 만원) const BASE_DAILY_REVENUE: Record<string, { min: number; avg: number; max: number; avgCustomers: number; avgPrice: number }> = { 카페: { min: 30, avg: 50, max: 80, avgCustomers: 80, avgPrice: 6000 }, 음식점: { min: 40, avg: 70, max: 120, avgCustomers: 50, avgPrice: 12000 }, 편의점: { min: 80, avg: 120, max: 180, avgCustomers: 200, avgPrice: 6000 }, 미용실: { min: 20, avg: 40, max: 70, avgCustomers: 8, avgPrice: 50000 }, 치킨: { min: 50, avg: 80, max: 130, avgCustomers: 40, avgPrice: 20000 }, 호프: { min: 40, avg: 70, max: 120, avgCustomers: 30, avgPrice: 25000 }, 분식: { min: 25, avg: 45, max: 70, avgCustomers: 60, avgPrice: 7000 }, 베이커리: { min: 35, avg: 60, max: 100, avgCustomers: 70, avgPrice: 8000 }, 무인매장: { min: 15, avg: 25, max: 40, avgCustomers: 50, avgPrice: 5000 }, 스터디카페: { min: 20, avg: 35, max: 55, avgCustomers: 40, avgPrice: 8000 }, 네일샵: { min: 15, avg: 30, max: 50, avgCustomers: 6, avgPrice: 50000 }, 반려동물: { min: 25, avg: 45, max: 75, avgCustomers: 15, avgPrice: 30000 }, }; // 계절별 매출 배수 const SEASON_MULTIPLIER: Record<string, Record<string, number>> = { 카페: { 봄: 1.0, 여름: 1.2, 가을: 1.0, 겨울: 0.9 }, 음식점: { 봄: 1.0, 여름: 0.9, 가을: 1.1, 겨울: 1.1 }, 편의점: { 봄: 1.0, 여름: 1.1, 가을: 1.0, 겨울: 1.0 }, 치킨: { 봄: 1.0, 여름: 1.2, 가을: 1.0, 겨울: 1.0 }, 호프: { 봄: 1.0, 여름: 1.3, 가을: 1.0, 겨울: 0.9 }, default: { 봄: 1.0, 여름: 1.0, 가을: 1.0, 겨울: 1.0 }, }; // 매출 시뮬레이션 결과 타입 export interface RevenueSimulation { businessType: string; region: string; conditions: { size: number; staffCount: number; operatingHours: number; }; dailyRevenue: { min: number; average: number; max: number; }; monthlyRevenue: { min: number; average: number; max: number; }; yearlyRevenue: { min: number; average: number; max: number; }; customerAnalysis: { dailyCustomers: number; averagePrice: number; peakHours: string; peakDays: string; }; seasonalVariation: { spring: number; summer: number; fall: number; winter: number; }; profitEstimate: { monthlyProfit: number; profitMargin: number; note: string; }; insights: string[]; } // 현재 계절 계산 function getCurrentSeason(): string { const month = new Date().getMonth() + 1; if (month >= 3 && month <= 5) return "봄"; if (month >= 6 && month <= 8) return "여름"; if (month >= 9 && month <= 11) return "가을"; return "겨울"; } export async function simulateRevenue( businessType: string, region: string, size: number = 15, staffCount: number = 1, operatingHours: number = 12 ): Promise<ApiResult<RevenueSimulation>> { try { // 1. 업종 및 지역 정규화 const normalizedType = normalizeBusinessType(businessType); const normalizedRegion = normalizeRegion(region); // 2. 기본 매출 데이터 조회 const baseRevenue = BASE_DAILY_REVENUE[normalizedType]; if (!baseRevenue) { return { success: false, error: { code: "UNKNOWN_BUSINESS_TYPE", message: `알 수 없는 업종입니다: ${businessType}`, suggestion: "카페, 음식점, 편의점, 미용실, 치킨, 호프, 분식, 베이커리, 무인매장, 스터디카페, 네일샵, 반려동물 중 선택해주세요.", }, }; } // 3. 지역 배수 적용 const regionData = REGIONAL_MULTIPLIER[normalizedRegion]; const regionMultiplier = regionData ? regionData.multiplier : 0.8; // 4. 규모 배수 (15평 기준) const sizeMultiplier = Math.sqrt(size / 15); // 5. 인력 배수 (좌석 회전율 증가) const staffMultiplier = 1 + (staffCount - 1) * 0.3; // 6. 운영시간 배수 (12시간 기준) const hoursMultiplier = operatingHours / 12; // 7. 일 매출 계산 const totalMultiplier = regionMultiplier * sizeMultiplier * staffMultiplier * hoursMultiplier; const dailyMin = Math.round(baseRevenue.min * totalMultiplier); const dailyAvg = Math.round(baseRevenue.avg * totalMultiplier); const dailyMax = Math.round(baseRevenue.max * totalMultiplier); // 8. 월 매출 (일 매출 × 26일, 주 1일 휴무 가정) const monthlyMin = dailyMin * 26; const monthlyAvg = dailyAvg * 26; const monthlyMax = dailyMax * 26; // 9. 연 매출 const yearlyMin = monthlyMin * 12; const yearlyAvg = monthlyAvg * 12; const yearlyMax = monthlyMax * 12; // 10. 고객 분석 const dailyCustomers = Math.round(baseRevenue.avgCustomers * sizeMultiplier * staffMultiplier); const averagePrice = baseRevenue.avgPrice; // 11. 피크 시간/요일 const peakHours = normalizedType === "카페" ? "오전 8-10시, 오후 2-4시" : normalizedType === "음식점" ? "점심 12-1시, 저녁 6-8시" : normalizedType === "호프" ? "저녁 7-11시" : normalizedType === "편의점" ? "오전 7-9시, 저녁 6-10시" : "점심 12-2시, 저녁 6-9시"; const peakDays = normalizedType === "호프" || normalizedType === "치킨" ? "금요일, 토요일" : "토요일, 일요일"; // 12. 계절별 변동 const seasonMult = SEASON_MULTIPLIER[normalizedType] || SEASON_MULTIPLIER.default; const seasonalVariation = { spring: Math.round(monthlyAvg * seasonMult.봄), summer: Math.round(monthlyAvg * seasonMult.여름), fall: Math.round(monthlyAvg * seasonMult.가을), winter: Math.round(monthlyAvg * seasonMult.겨울), }; // 13. 수익 추정 (업종별 평균 마진율 적용) const marginRates: Record<string, number> = { 카페: 0.35, 음식점: 0.25, 편의점: 0.20, 미용실: 0.45, 치킨: 0.25, 호프: 0.30, 분식: 0.30, 베이커리: 0.35, 무인매장: 0.40, 스터디카페: 0.45, 네일샵: 0.50, 반려동물: 0.35, }; const profitMargin = marginRates[normalizedType] || 0.30; const monthlyProfit = Math.round(monthlyAvg * profitMargin); // 14. 인사이트 생성 const insights: string[] = []; const currentSeason = getCurrentSeason(); const currentSeasonMult = seasonMult[currentSeason as keyof typeof seasonMult] || 1.0; insights.push(`💰 예상 월 순이익: 약 ${monthlyProfit.toLocaleString()}만원 (마진율 ${(profitMargin * 100).toFixed(0)}%)`); if (currentSeasonMult > 1.0) { insights.push(`📈 현재 ${currentSeason}철은 ${normalizedType} 업종 성수기입니다. 매출 ${((currentSeasonMult - 1) * 100).toFixed(0)}% 상승 예상.`); } else if (currentSeasonMult < 1.0) { insights.push(`📉 현재 ${currentSeason}철은 ${normalizedType} 업종 비수기입니다. 매출 ${((1 - currentSeasonMult) * 100).toFixed(0)}% 하락 예상.`); } if (normalizedRegion.includes("강남") || normalizedRegion.includes("홍대")) { insights.push(`🏙️ ${normalizedRegion}은 유동인구가 많아 매출이 높은 편입니다.`); } if (staffCount >= 2) { insights.push(`👥 ${staffCount}인 운영으로 고객 회전율이 높아집니다. 인건비 대비 매출 증가를 계산하세요.`); } if (operatingHours < 10) { insights.push(`⏰ 운영시간이 ${operatingHours}시간으로 짧습니다. 피크 시간대 집중 운영을 권장합니다.`); } // 손익분기 관점 const breakEvenDaily = dailyAvg * (1 - profitMargin); insights.push(`📊 손익분기를 넘으려면 일 매출 ${Math.round(breakEvenDaily)}만원 이상이 필요합니다.`); const profitNote = monthlyProfit > 300 ? "월 순이익 300만원 이상으로 양호한 수준입니다." : monthlyProfit > 200 ? "월 순이익 200만원 이상으로 적정 수준입니다." : "월 순이익이 낮습니다. 비용 절감 또는 매출 증대 방안을 검토하세요."; return { success: true, data: { businessType: normalizedType, region: normalizedRegion, conditions: { size, staffCount, operatingHours, }, dailyRevenue: { min: dailyMin, average: dailyAvg, max: dailyMax, }, monthlyRevenue: { min: monthlyMin, average: monthlyAvg, max: monthlyMax, }, yearlyRevenue: { min: yearlyMin, average: yearlyAvg, max: yearlyMax, }, customerAnalysis: { dailyCustomers, averagePrice, peakHours, peakDays, }, seasonalVariation, profitEstimate: { monthlyProfit, profitMargin: Math.round(profitMargin * 100), note: profitNote, }, insights, }, meta: { source: "소상공인마당, 통계청, 업종별 평균 데이터 기반 추정", timestamp: new Date().toISOString(), dataNote: `${size}평, ${staffCount}인 운영, ${operatingHours}시간 기준. 🟡 신뢰도: 중간 (통계 기반 추정치). ${DISCLAIMERS.REVENUE_ESTIMATE}`, }, }; } catch (error) { console.error("매출 시뮬레이션 실패:", error); return { success: false, error: { code: "SIMULATION_FAILED", message: `매출 시뮬레이션 중 오류가 발생했습니다: ${error instanceof Error ? error.message : "Unknown error"}`, suggestion: "입력값을 확인하고 다시 시도해주세요.", }, }; } }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/re171113-byte/startup-helper-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server