โ† ๋ฉ”์ธ์œผ๋กœ ๋Œ์•„๊ฐ€๊ธฐ

๐Ÿ’ฐ AWS ML๋กœ AWS ๋น„์šฉ ์˜ˆ์ธกํ•˜๊ธฐ ํ”„๋กœ์ ํŠธ

๋จธ์‹ ๋Ÿฌ๋‹ ๋ชจ๋ธ ๊ตฌ์ถ• ๊ณผ์ • ๋ถ„์„ - ์˜ˆ์ธก ์ •ํ™•๋„ ๊ฐœ์„  ์‹œ๋„์™€ ํ•œ๊ณ„์  ๋„์ถœ

๐Ÿ“‹ ์ฐธ๊ณ ์‚ฌํ•ญ: ์‹ค์ œ ๋น„์šฉ ์ •๋ณด๋Š” ๋ณด์•ˆ์ƒ ๋งˆ์Šคํ‚น ์ฒ˜๋ฆฌ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ํ•™์Šต ๋ชฉ์ ์œผ๋กœ ํŒจํ„ด๊ณผ ์˜ค์ฐจ์œจ์€ ์‹ค์ œ ๋ฐ์ดํ„ฐ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•ฉ๋‹ˆ๋‹ค.

๐Ÿ“š ๋ชฉ์ฐจ

๐ŸŽฏ ํ”„๋กœ์ ํŠธ ๊ฐœ์š”

๋ชฉํ‘œ ์„ค์ •

๋ฐ์ดํ„ฐ ์ถฉ๋ถ„์„ฑ ํ‰๊ฐ€

๐Ÿ“Š ๋ฐ์ดํ„ฐ ํ˜„ํ™ฉ
  • ๋ฐ์ดํ„ฐ ๊ธฐ๊ฐ„: 2023๋…„ ~ 2025๋…„ (3๋…„๊ฐ„)
  • ๋ฐ์ดํ„ฐ ํ’ˆ์งˆ: ์‹ค์ œ ์šด์˜ ํ™˜๊ฒฝ์˜ ์›”๋ณ„ ๋น„์šฉ ๋ฐ์ดํ„ฐ
  • ๋ฐ์ดํ„ฐ ์–‘: 36๊ฐœ์›” ์ด์ƒ์˜ ์—ฐ์† ๋ฐ์ดํ„ฐ
  • ํ‰๊ฐ€: ML ๋ชจ๋ธ ํ•™์Šต์— ์ถฉ๋ถ„ํ•œ ์–‘์งˆ์˜ ๋ฐ์ดํ„ฐ๋กœ ํŒ๋‹จ

๊ฒ€์ฆ ์‹œ๋‚˜๋ฆฌ์˜ค ์„ค๊ณ„

# ์‹œ๋‚˜๋ฆฌ์˜ค 1: 2023๋…„ ํ•™์Šต โ†’ 2024๋…„ ์˜ˆ์ธก
- ํ•™์Šต ๋ฐ์ดํ„ฐ: 2023๋…„ 12๊ฐœ์›”
- ์˜ˆ์ธก ๋Œ€์ƒ: 2024๋…„ 12๊ฐœ์›”
- ๊ฒ€์ฆ ๋ฐฉ๋ฒ•: 2024๋…„ ์‹ค์ œ ๋ฐ์ดํ„ฐ์™€ ๋น„๊ต (ํ˜„์žฌ ๊ฐ€๋Šฅ)

# ์‹œ๋‚˜๋ฆฌ์˜ค 2: 2023-2024๋…„ ํ•™์Šต โ†’ 2025๋…„ ์˜ˆ์ธก
- ํ•™์Šต ๋ฐ์ดํ„ฐ: 2023-2024๋…„ 24๊ฐœ์›”
- ์˜ˆ์ธก ๋Œ€์ƒ: 2025๋…„ 12๊ฐœ์›”
- ๊ฒ€์ฆ ๋ฐฉ๋ฒ•: 2025๋…„ ์‹ค์ œ ๋ฐ์ดํ„ฐ์™€ ๋น„๊ต (์ง„ํ–‰ ์ค‘)

์ดˆ๊ธฐ ์ ‘๊ทผ ๋ฐฉ๋ฒ•

# ๊ธฐ๋ณธ ๊ฐ€์ •
- 3๋…„๊ฐ„์˜ ๋ฐ์ดํ„ฐ๋Š” ํŒจํ„ด ํ•™์Šต์— ์ถฉ๋ถ„
- ๊ณผ๊ฑฐ ๋ฐ์ดํ„ฐ ํŒจํ„ด์ด ๋ฏธ๋ž˜ ์˜ˆ์ธก์— ์œ ํšจ
- ๋จธ์‹ ๋Ÿฌ๋‹ ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ํ†ตํ•œ ์ •ํ™•๋„ ํ–ฅ์ƒ ๊ฐ€๋Šฅ
- ๋‹ค์ค‘ ์‹œ๋‚˜๋ฆฌ์˜ค ๊ฒ€์ฆ์„ ํ†ตํ•œ ๋ชจ๋ธ ์‹ ๋ขฐ์„ฑ ํ™•๋ณด
๐Ÿ“Š ํ”„๋กœ์ ํŠธ ๋ฒ”์œ„: 3๋…„๊ฐ„ ์ถ•์ ๋œ ๋ฐ์ดํ„ฐ ๊ธฐ๋ฐ˜ ๋‹ค์ค‘ ์‹œ๋‚˜๋ฆฌ์˜ค ์˜ˆ์ธก ๋ฐ ๊ฒ€์ฆ

ํ”„๋กœ์ ํŠธ ์ „์ฒด ํ๋ฆ„๋„ (Prophet ์‹คํ—˜ ํ›„ ์—…๋ฐ์ดํŠธ)

๐Ÿ“Š ๋ฐ์ดํ„ฐ ์ˆ˜์ง‘
Athena โ†’ QuickSight CSM Dataset
(2023-2025๋…„, 36๊ฐœ์›” ๋ฐ์ดํ„ฐ)
โ†“
๐Ÿ”ง ๋ฐ์ดํ„ฐ ์ „์ฒ˜๋ฆฌ
์›”๋ณ„ ์ง‘๊ณ„ โ†’ ์‹œ๊ณ„์—ด ๋ณ€ํ™˜
๊ฒฐ์ธก์น˜ ์ฒ˜๋ฆฌ โ†’ ์ •๊ทœํ™”
โ†“

โŒ ๊ธฐ์กด ์ ‘๊ทผ๋ฒ•

ํŠน์„ฑ ์—”์ง€๋‹ˆ์–ด๋ง
19๊ฐœ ๋ณต์žกํ•œ ํŠน์„ฑ ์ƒ์„ฑ
โ†“
RF
GB
LR
โ†“
35.2% ์˜ค์ฐจ
์‹ค๋ฌด ๊ธฐ์ค€ ๋ฏธ๋‹ฌ

โœ… ๊ฐœ์„ ๋œ ์ ‘๊ทผ๋ฒ•

์‹œ๊ณ„์—ด ์ „์šฉ ๋ชจ๋ธ
์ตœ์ ํ™”๋œ Prophet (๋‹จ์ˆœ ๊ตฌ์กฐ)
โ†“
ํ•ต์‹ฌ ํŠน์„ฑ 2๊ฐœ
is_year_end, is_q1
โ†“
14.6% ์˜ค์ฐจ
๐Ÿ† ์‹ค๋ฌด ๊ธฐ์ค€ ๋‹ฌ์„ฑ
โ†“
๐Ÿ“‹ ์„ฑ๋Šฅ ๊ฒ€์ฆ
์‹ค์ œ vs ์˜ˆ์ธก ๋น„๊ต (2025๋…„ 1-5์›”)
์ตœ์ ํ™”๋œ Prophet์ด 20.6%p ๋” ์ •ํ™•
โ†“
๐Ÿ’ก ํ•ต์‹ฌ ๊ตํ›ˆ
๋ชจ๋ธ ์„ ํƒ > ํŠน์„ฑ ์—”์ง€๋‹ˆ์–ด๋ง
๋‹จ์ˆœํ•จ์ด ๋ณต์žกํ•จ์„ ์ด๊น€
โ†“
๐Ÿš€ ๋‹ค์Œ ๋‹จ๊ณ„
Prophet + ์ž์—ฐ์–ด ์ž…๋ ฅ ์‹œ์Šคํ…œ
์‹ค๋ฌด ํ™œ์šฉ ๊ฐ€๋Šฅํ•œ ๋„๊ตฌ ๊ตฌ์ถ•

๊ฐœ์„ ๋œ ๊ฐœ๋ฐœ ํ”„๋กœ์„ธ์Šค

1๋‹จ๊ณ„
์‹œ๊ณ„์—ด ๋ชจ๋ธ ์šฐ์„ 
Prophet, ARIMA ์‹œ๋„
2๋‹จ๊ณ„
์„ฑ๋Šฅ ๊ฒ€์ฆ
์‹ค๋ฌด ๊ธฐ์ค€ ๋‹ฌ์„ฑ?
3๋‹จ๊ณ„
ํ•„์š”์‹œ ๊ฐœ์„ 
ํŠน์„ฑ ์ถ”๊ฐ€, ๊ณ ๊ธ‰ ๊ธฐ๋ฒ•
4๋‹จ๊ณ„
์„œ๋น„์Šคํ™”
์›น ์ธํ„ฐํŽ˜์ด์Šค, API

์ฃผ์š” ์„ฑ๊ณผ ์ง€ํ‘œ (Prophet ์‹คํ—˜ ํ›„)

36๊ฐœ์›”
ํ•™์Šต ๋ฐ์ดํ„ฐ
2๊ฐœ
ํ•ต์‹ฌ ํŠน์„ฑ (๋‹จ์ˆœํ™”)
Prophet
์‹œ๊ณ„์—ด ์ „์šฉ ๋ชจ๋ธ
14.6%
๐Ÿ† ์ตœ์ข… ์˜ค์ฐจ์œจ

์„ฑ๋Šฅ ๊ฐœ์„  ๊ณผ์ •

๊ธฐ์กด ML
35.2%
19๊ฐœ ํŠน์„ฑ + ์•™์ƒ๋ธ”
โ†’
์ตœ์ ํ™”๋œ Prophet
14.6%
2๊ฐœ ํŠน์„ฑ + ๋‹จ์ˆœํ•จ
20.6%p
๊ฐœ์„ 

๐Ÿ“Š ๊ธฐ๋ณธ ๋ชจ๋ธ ๊ตฌํ˜„

๋ชจ๋ธ ์•„ํ‚คํ…์ฒ˜ ์„ค๊ณ„

๊ตฌํ˜„ ํŒŒ์ผ: 04_aws_budget_prediction.py

1. ๋ฐ์ดํ„ฐ ์ „์ฒ˜๋ฆฌ ๊ณผ์ •

# Athena์—์„œ CSM ๋ฐ์ดํ„ฐ ์กฐํšŒ
query = """
SELECT year, month, usageaccountid, productcode, 
       SUM(unblendedcost) as monthly_cost,
       SUM(amortized_cost) as amortized_monthly_cost
FROM awsbilling.summary_view 
WHERE year >= '2023'
GROUP BY year, month, usageaccountid, productcode
ORDER BY year, month
"""

# ์›”๋ณ„ ์ด ๋น„์šฉ ์ง‘๊ณ„ ๋ฐ ์‹œ๊ณ„์—ด ๋ฐ์ดํ„ฐ ์ƒ์„ฑ
monthly_totals = df.groupby('date')['monthly_cost'].sum().reset_index()
monthly_totals = monthly_totals.sort_values('date')

2. ํŠน์„ฑ ์—”์ง€๋‹ˆ์–ด๋ง (Feature Engineering)

# ๊ธฐ๋ณธ ์‹œ๊ณ„์—ด ํŠน์„ฑ
monthly_totals['month_index'] = range(len(monthly_totals))  # ์ˆœ์ฐจ ์ธ๋ฑ์Šค
monthly_totals['month_num'] = monthly_totals['date'].dt.month  # ์›” (1-12)
monthly_totals['quarter'] = monthly_totals['date'].dt.quarter  # ๋ถ„๊ธฐ (1-4)

# ์ด๋™ํ‰๊ท  ํŠน์„ฑ (ํŠธ๋ Œ๋“œ ํŒŒ์•…)
monthly_totals['ma_3'] = monthly_totals['monthly_cost'].rolling(3).mean()  # 3๊ฐœ์›” ์ด๋™ํ‰๊ท 
monthly_totals['ma_6'] = monthly_totals['monthly_cost'].rolling(6).mean()  # 6๊ฐœ์›” ์ด๋™ํ‰๊ท 

3. ๋จธ์‹ ๋Ÿฌ๋‹ ์•Œ๊ณ ๋ฆฌ์ฆ˜ ์„ ํƒ

์•Œ๊ณ ๋ฆฌ์ฆ˜ ์„ ํƒ ์ด์œ 
  • Random Forest: ๋น„์„ ํ˜• ํŒจํ„ด ํ•™์Šต, ๊ณผ์ ํ•ฉ ๋ฐฉ์ง€, ํŠน์„ฑ ์ค‘์š”๋„ ์ œ๊ณต
  • Linear Regression: ์„ ํ˜• ํŠธ๋ Œ๋“œ ํŒŒ์•…, ํ•ด์„ ์šฉ์ด์„ฑ, ๋ฒ ์ด์Šค๋ผ์ธ ๋ชจ๋ธ
# ๋ชจ๋ธ ์ •์˜
models = {
    'rf': RandomForestRegressor(n_estimators=100, random_state=42),
    'lr': LinearRegression()
}

# ํŠน์„ฑ ๋ณ€์ˆ˜ ์„ ํƒ
features = ['month_index', 'month_num', 'quarter', 'ma_3', 'ma_6']
X = train_data[features].fillna(method='bfill')
y = train_data['monthly_cost']

# ๋ชจ๋ธ ํ•™์Šต
for name, model in models.items():
    model.fit(X, y)

4. ์˜ˆ์ธก ๊ณผ์ •

# 2025๋…„ ์˜ˆ์ธก์„ ์œ„ํ•œ ํŠน์„ฑ ์ƒ์„ฑ
future_months = pd.date_range(start='2025-01-01', periods=12, freq='MS')
future_features = []

for i, date in enumerate(future_months):
    # ๊ณผ๊ฑฐ ๋ฐ์ดํ„ฐ ๊ธฐ๋ฐ˜ ์ด๋™ํ‰๊ท  ๊ณ„์‚ฐ
    recent_costs = train_data['monthly_cost'].tail(6).values
    ma_3 = np.mean(recent_costs[-3:]) if len(recent_costs) >= 3 else recent_costs.mean()
    ma_6 = np.mean(recent_costs) if len(recent_costs) >= 6 else recent_costs.mean()
    
    future_features.append({
        'month_index': len(train_data) + i,
        'month_num': date.month,
        'quarter': date.quarter,
        'ma_3': ma_3,
        'ma_6': ma_6
    })

# ์˜ˆ์ธก ์‹คํ–‰
predictions = {}
for name, model in models.items():
    pred = model.predict(future_X)
    predictions[name] = pred

์ดˆ๊ธฐ ์„ฑ๋Šฅ ํ‰๊ฐ€

์ดˆ๊ธฐ ๋ชจ๋ธ์˜ ํ•œ๊ณ„์ 
  • ๋‹จ์ˆœํ•œ ํŠน์„ฑ์œผ๋กœ ์ธํ•œ ํŒจํ„ด ํ•™์Šต ๋ถ€์กฑ
  • ๊ณ„์ ˆ์„ฑ ๋ฐ ์™ธ๋ถ€ ์š”์ธ ๋ฏธ๋ฐ˜์˜
  • ๊ณผ๊ฑฐ ํŠธ๋ Œ๋“œ์— ๊ณผ๋„ํ•˜๊ฒŒ ์˜์กด

๊ธฐ๋ณธ ๋ชจ๋ธ vs ๊ฐœ์„  ๋ชจ๋ธ ๋น„๊ต

๐Ÿ”ง ๊ธฐ๋ณธ ๋ชจ๋ธ

5๊ฐœ ํŠน์„ฑ
month_index, month_num, quarter, ma_3, ma_6
โ†“
Random Forest
Linear Reg
โ†“
39.9% ์˜ค์ฐจ
โ†’

๐Ÿš€ ๊ฐœ์„  ๋ชจ๋ธ

19๊ฐœ ํŠน์„ฑ
์ด๋™ํ‰๊ท , ๊ณ„์ ˆ์„ฑ, ๋ณ€๋™์„ฑ, ํŠธ๋ Œ๋“œ, ๋น„์ฆˆ๋‹ˆ์Šค
โ†“
RF (40%)
GB (40%)
LR (20%)
โ†“
35.2% ์˜ค์ฐจ
4.7%p ๊ฐœ์„ 

๐Ÿ” ์„ฑ๋Šฅ ๊ฒ€์ฆ ๋ฐ ๋ถ„์„

๊ฒ€์ฆ ํŒŒ์ผ: 05_real_budget_prediction.py | 07_model_validation.py

๋‹ค์ค‘ ์‹œ๋‚˜๋ฆฌ์˜ค ๊ฒ€์ฆ ๊ฒฐ๊ณผ

์‹œ๋‚˜๋ฆฌ์˜ค 1: 2023๋…„ ํ•™์Šต โ†’ 2024๋…„ ์˜ˆ์ธก

๊ฒ€์ฆ ์™„๋ฃŒ: 2024๋…„ ์‹ค์ œ ๋ฐ์ดํ„ฐ์™€ ๋น„๊ต ๊ฐ€๋Šฅ

์‹œ๋‚˜๋ฆฌ์˜ค 2: 2023-2024๋…„ ํ•™์Šต โ†’ 2025๋…„ ์˜ˆ์ธก (์ฃผ์š” ๋ถ„์„)

์›” ์˜ˆ์ธก๊ฐ’ ์‹ค์ œ๊ฐ’ ์˜ค์ฐจ์œจ
2025-01 โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ +20.5%
2025-02 โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ +51.9%
2025-03 โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ +38.2%
2025-04 โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ +46.1%
2025-05 โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ +42.7%
ํ‰๊ท  ์˜ˆ์ธก ์˜ค์ฐจ์œจ: 39.9%

๊ฒ€์ฆ ์‹œ๋‚˜๋ฆฌ์˜ค์˜ ์žฅ์ 

์„ฑ๋Šฅ ๋ถ„์„ ๊ฒฐ๊ณผ

๐Ÿ› ๏ธ ๋ชจ๋ธ ๊ฐœ์„  ์‹œ๋„

๊ฐœ์„  ํŒŒ์ผ: 09_improved_budget_model.py

ํŠน์„ฑ ์—”์ง€๋‹ˆ์–ด๋ง ์ง„ํ™” ๊ณผ์ •

๐Ÿ”ข ๊ธฐ๋ณธ ํŠน์„ฑ
โ€ข month_index
โ€ข month_num
โ€ข quarter
3๊ฐœ ํŠน์„ฑ
๐Ÿ“ˆ ์ด๋™ํ‰๊ท 
โ€ข ma_2, ma_3, ma_6
โ€ข mom_change
โ€ข mom_change_ma3
+5๊ฐœ ํŠน์„ฑ
๐Ÿ”„ ๊ณ„์ ˆ์„ฑ
โ€ข sin_month, cos_month
โ€ข sin_quarter, cos_quarter
โ€ข is_q1, is_q4
+6๊ฐœ ํŠน์„ฑ
โšก ๊ณ ๊ธ‰ ํŠน์„ฑ
โ€ข volatility_3m, 6m
โ€ข linear_trend
โ€ข detrended_cost
โ€ข is_year_end
+5๊ฐœ ํŠน์„ฑ

์ด 19๊ฐœ ํŠน์„ฑ์œผ๋กœ ํ™•์žฅ

๊ธฐ๋ณธ 3๊ฐœ + ์ด๋™ํ‰๊ท  5๊ฐœ + ๊ณ„์ ˆ์„ฑ 6๊ฐœ + ๊ณ ๊ธ‰ 5๊ฐœ = 19๊ฐœ

์•™์ƒ๋ธ” ๋ชจ๋ธ ๊ตฌ์กฐ

๐Ÿ“Š ์ž…๋ ฅ ๋ฐ์ดํ„ฐ
19๊ฐœ ํŠน์„ฑ ร— N๊ฐœ์›” ๋ฐ์ดํ„ฐ
โ†“
๐ŸŒณ Random Forest
200 trees
๋น„์„ ํ˜• ํŒจํ„ด
๊ฐ€์ค‘์น˜: 40%
๐Ÿ“ˆ Gradient Boosting
100 estimators
์ˆœ์ฐจ์  ํ•™์Šต
๊ฐ€์ค‘์น˜: 40%
๐Ÿ“Š Linear Regression
์„ ํ˜• ๋ชจ๋ธ
์•ˆ์ •์„ฑ ์ œ๊ณต
๊ฐ€์ค‘์น˜: 20%
โ†“
โš–๏ธ ๊ฐ€์ค‘ ํ‰๊ท 
์ตœ์ข… ์˜ˆ์ธก = RF ร— 0.4 + GB ร— 0.4 + LR ร— 0.2
โ†“
๐ŸŽฏ ์ตœ์ข… ์˜ˆ์ธก ๊ฒฐ๊ณผ
2025๋…„ ์›”๋ณ„ AWS ๋น„์šฉ ์˜ˆ์ธก

1. ํ™•์žฅ๋œ ์‹œ๊ณ„์—ด ํŠน์„ฑ

# ๋‹ค์–‘ํ•œ ์œˆ๋„์šฐ ์ด๋™ํ‰๊ท 
df['ma_2'] = df['total_cost'].rolling(2, min_periods=1).mean()  # 2๊ฐœ์›”
df['ma_3'] = df['total_cost'].rolling(3, min_periods=1).mean()  # 3๊ฐœ์›”  
df['ma_6'] = df['total_cost'].rolling(6, min_periods=1).mean()  # 6๊ฐœ์›”

# ๋ณ€ํ™”์œจ ํŠน์„ฑ
df['mom_change'] = df['total_cost'].pct_change()  # ์›”๊ฐ„ ๋ณ€ํ™”์œจ
df['mom_change_ma3'] = df['mom_change'].rolling(3, min_periods=1).mean()  # ๋ณ€ํ™”์œจ ํ‰ํ™œํ™”

2. ๊ณ„์ ˆ์„ฑ ์ธ์ฝ”๋”ฉ (Cyclical Encoding)

# ์‚ผ๊ฐํ•จ์ˆ˜๋ฅผ ์ด์šฉํ•œ ๊ณ„์ ˆ์„ฑ ํ‘œํ˜„
df['sin_month'] = np.sin(2 * np.pi * df['month_num'] / 12)
df['cos_month'] = np.cos(2 * np.pi * df['month_num'] / 12)
df['sin_quarter'] = np.sin(2 * np.pi * df['quarter'] / 4)
df['cos_quarter'] = np.cos(2 * np.pi * df['quarter'] / 4)

# ์ด์œ : 12์›”๊ณผ 1์›”์˜ ์—ฐ์†์„ฑ์„ ์ˆ˜ํ•™์ ์œผ๋กœ ํ‘œํ˜„
# sin/cos ์กฐํ•ฉ์œผ๋กœ ์›ํ˜• ์‹œ๊ฐ„ ๊ตฌ์กฐ ๋ชจ๋ธ๋ง

3. ๋ณ€๋™์„ฑ ๋ฐ ํŠธ๋ Œ๋“œ ์ง€ํ‘œ

# ๋ณ€๋™์„ฑ ์ธก์ •
df['volatility_3m'] = df['total_cost'].rolling(3, min_periods=1).std()
df['volatility_6m'] = df['total_cost'].rolling(6, min_periods=1).std()

# ํŠธ๋ Œ๋“œ ๋ถ„์„
df['linear_trend'] = np.arange(len(df))
df['detrended_cost'] = df['total_cost'] - (df['linear_trend'] * df['total_cost'].diff().mean())

# ๋น„์ฆˆ๋‹ˆ์Šค ํŠน์„ฑ (๋„๋ฉ”์ธ ์ง€์‹ ๋ฐ˜์˜)
df['is_q1'] = (df['quarter'] == 1).astype(int)  # ์‹ ๋…„ ์˜ˆ์‚ฐ ์ฆ๊ฐ€ ํšจ๊ณผ
df['is_q4'] = (df['quarter'] == 4).astype(int)  # ์—ฐ๋ง ์ง€์ถœ ์ฆ๊ฐ€ ํšจ๊ณผ
df['is_year_end'] = (df['month_num'] >= 11).astype(int)  # ์—ฐ๋ง ํšจ๊ณผ

4. ์•™์ƒ๋ธ” ๋ชจ๋ธ ๊ตฌํ˜„

class ImprovedBudgetPredictor:
    def __init__(self):
        self.models = {
            'rf': RandomForestRegressor(n_estimators=200, random_state=42),
            'gb': GradientBoostingRegressor(n_estimators=100, random_state=42),
            'lr': LinearRegression()
        }
        # ๊ฐ€์ค‘ ํ‰๊ท ์„ ์œ„ํ•œ ๊ฐ€์ค‘์น˜ ์„ค์ •
        self.weights = {'rf': 0.4, 'gb': 0.4, 'lr': 0.2}
    
    def predict_ensemble(self, X):
        """์•™์ƒ๋ธ” ์˜ˆ์ธก"""
        predictions = {}
        for name, model in self.models.items():
            predictions[name] = model.predict(X)
        
        # ๊ฐ€์ค‘ ํ‰๊ท  ๊ณ„์‚ฐ
        ensemble_pred = (
            predictions['rf'] * self.weights['rf'] +
            predictions['gb'] * self.weights['gb'] +
            predictions['lr'] * self.weights['lr']
        )
        return ensemble_pred

5. ์•Œ๊ณ ๋ฆฌ์ฆ˜๋ณ„ ํŠน์„ฑ

Random Forest (40% ๊ฐ€์ค‘์น˜)
  • 200๊ฐœ ๊ฒฐ์ • ํŠธ๋ฆฌ ์•™์ƒ๋ธ”
  • ๋น„์„ ํ˜• ํŒจํ„ด ํ•™์Šต ์šฐ์ˆ˜
  • ํŠน์„ฑ ์ค‘์š”๋„ ๋ถ„์„ ๊ฐ€๋Šฅ
  • ๊ณผ์ ํ•ฉ ๋ฐฉ์ง€ ํšจ๊ณผ
Gradient Boosting (40% ๊ฐ€์ค‘์น˜)
  • ์ˆœ์ฐจ์  ์˜ค์ฐจ ๋ณด์ • ํ•™์Šต
  • ๋ณต์žกํ•œ ํŒจํ„ด ํ•™์Šต ๋Šฅ๋ ฅ
  • ๋†’์€ ์˜ˆ์ธก ์ •ํ™•๋„
  • ํ•˜์ดํผํŒŒ๋ผ๋ฏธํ„ฐ ๋ฏผ๊ฐ
Linear Regression (20% ๊ฐ€์ค‘์น˜)
  • ์„ ํ˜• ํŠธ๋ Œ๋“œ ํŒŒ์•…
  • ํ•ด์„ ์šฉ์ด์„ฑ
  • ์•ˆ์ •์„ฑ ์ œ๊ณต
  • ๋ฒ ์ด์Šค๋ผ์ธ ์—ญํ• 

๋ชจ๋ธ ๊ฒ€์ฆ ๊ณผ์ •

๊ฒ€์ฆ ํŒŒ์ผ: 07_model_validation.py

# ์‹ค์ œ vs ์˜ˆ์ธก ๋น„๊ต (2025๋…„ 1-5์›”)
actual_2025 = [
    {"month": "01", "actual_cost": 731337.61},
    {"month": "02", "actual_cost": 576939.76},
    {"month": "03", "actual_cost": 616179.57},
    {"month": "04", "actual_cost": 607998.79},
    {"month": "05", "actual_cost": 592674.50}
]

predictions_2025 = [
    {"month": "01", "predicted_cost": 881207},
    {"month": "02", "predicted_cost": 876152},
    {"month": "03", "predicted_cost": 851643},
    {"month": "04", "predicted_cost": 888317},
    {"month": "05", "predicted_cost": 845591}
]

# ์˜ค์ฐจ ๊ณ„์‚ฐ
for i in range(5):
    actual = actual_2025[i]['actual_cost']
    predicted = predictions_2025[i]['predicted_cost']
    error = abs(predicted - actual) / actual * 100
    print(f"2025-{i+1:02d}: {error:.1f}% ์˜ค์ฐจ")

๊ฐœ์„  ๊ฒฐ๊ณผ ๋ถ„์„

๊ฐœ์„  ์‹œ๋„์˜ ํ•œ๊ณ„
  • ๋ณต์žกํ•œ ํŠน์„ฑ ์—”์ง€๋‹ˆ์–ด๋ง์—๋„ ๋ถˆ๊ตฌํ•˜๊ณ  ๊ทผ๋ณธ์  ์„ฑ๋Šฅ ํ–ฅ์ƒ ์ œํ•œ
  • ๊ณผ๊ฑฐ ํŒจํ„ด ๊ธฐ๋ฐ˜ ์˜ˆ์ธก์˜ ๊ตฌ์กฐ์  ํ•œ๊ณ„
  • ์™ธ๋ถ€ ๋ณ€์ˆ˜(๊ฒฝ์ œ ์ƒํ™ฉ, ์ •์ฑ… ๋ณ€ํ™”) ๋ฏธ๋ฐ˜์˜
  • ๋ชจ๋ธ ํ•ด์„์„ฑ ์ €ํ•˜ (19๊ฐœ ํŠน์„ฑ์˜ ๋ณต์žกํ•œ ์ƒํ˜ธ์ž‘์šฉ)

์‹œ๊ฐํ™” ๋„๊ตฌ ํ™œ์šฉ

๋Œ€์‹œ๋ณด๋“œ ํŒŒ์ผ: 13_QuickSight_Dashboard_Guide.md | 14_create_quicksight_dashboard.py

# QuickSight ๋Œ€์‹œ๋ณด๋“œ ์ž๋™ ์ƒ์„ฑ
def create_budget_dashboard():
    quicksight = boto3.client('quicksight')
    
    # ๋ฐ์ดํ„ฐ์…‹ ์ƒ์„ฑ
    response = quicksight.create_data_set(
        AwsAccountId=account_id,
        DataSetId='budget-prediction-dataset',
        Name='Budget Prediction Analysis',
        PhysicalTableMap={
            'budget-table': {
                'S3Source': {
                    'DataSourceArn': athena_datasource_arn,
                    'InputColumns': [
                        {'Name': 'date', 'Type': 'DATETIME'},
                        {'Name': 'actual_cost', 'Type': 'DECIMAL'},
                        {'Name': 'predicted_cost', 'Type': 'DECIMAL'}
                    ]
                }
            }
        }
    )
    
    # ์‹œ๊ฐํ™” ์ƒ์„ฑ (์‹œ๊ณ„์—ด ์ฐจํŠธ, ์˜ค์ฐจ ๋ถ„์„ ๋“ฑ)
    return create_visualizations()

๐Ÿ“‹ ๊ฒฐ๊ณผ ๋ถ„์„ ๋ฐ ๊ฐœ์„  ๋ฐฉํ–ฅ

โœ… ์ฃผ์š” ๋ถ„์„ ๊ฒฐ๊ณผ

1. ๋ฐ์ดํ„ฐ ์ถฉ๋ถ„์„ฑ ์žฌํ‰๊ฐ€

  • ์–‘์  ์ถฉ๋ถ„์„ฑ: 3๋…„๊ฐ„(36๊ฐœ์›”) ๋ฐ์ดํ„ฐ๋Š” ML ํ•™์Šต์— ์ถฉ๋ถ„ํ•œ ์–‘
  • ์งˆ์  ํ•œ๊ณ„: ๊ณผ๊ฑฐ ํŒจํ„ด์˜ ๋ฏธ๋ž˜ ์˜ˆ์ธก ํ•œ๊ณ„์„ฑ
  • ์™ธ๋ถ€ ๋ณ€์ˆ˜ ๋ถ€์žฌ: ๊ฒฝ์ œ ์ƒํ™ฉ, ์ •์ฑ… ๋ณ€ํ™”, ๋น„์ฆˆ๋‹ˆ์Šค ์ „๋žต ๋ณ€ํ™” ๋ฏธ๋ฐ˜์˜
  • ๊ตฌ์กฐ์  ๋ณ€ํ™”: ํด๋ผ์šฐ๋“œ ์‚ฌ์šฉ ํŒจํ„ด์˜ ๊ธ‰๊ฒฉํ•œ ๋ณ€ํ™” ์š”์ธ

2. ๋ชจ๋ธ ๋ณต์žก๋„์™€ ์„ฑ๋Šฅ์˜ ๊ด€๊ณ„

  • ๋ณต์žกํ•œ ๋ชจ๋ธ์ด ๋ฐ˜๋“œ์‹œ ๋†’์€ ์„ฑ๋Šฅ์„ ๋ณด์žฅํ•˜์ง€ ์•Š์Œ
  • ๊ณผ์ ํ•ฉ์œผ๋กœ ์ธํ•œ ์ผ๋ฐ˜ํ™” ์„ฑ๋Šฅ ์ €ํ•˜
  • ๋ชจ๋ธ ํ•ด์„ ๊ฐ€๋Šฅ์„ฑ๊ณผ ์„ฑ๋Šฅ ๊ฐ„์˜ ํŠธ๋ ˆ์ด๋“œ์˜คํ”„

3. ๋น„์ฆˆ๋‹ˆ์Šค ์š”๊ตฌ์‚ฌํ•ญ๊ณผ ๊ธฐ์ˆ ์  ํ•œ๊ณ„

  • ๊ธฐ์ˆ ์  ์ •ํ™•๋„์™€ ์‹ค๋ฌด ํ™œ์šฉ์„ฑ์˜ ์ฐจ์ด
  • ๋„๋ฉ”์ธ ์ „๋ฌธ๊ฐ€ ํ˜‘์—…์˜ ์ค‘์š”์„ฑ
  • ์˜ˆ์ธก๋ณด๋‹ค ํŠธ๋ Œ๋“œ ๋ถ„์„์˜ ์‹ค์šฉ์  ๊ฐ€์น˜

4. ํ”„๋กœ์ ํŠธ ๊ด€๋ฆฌ ๊ด€์ 

  • ์ ์ง„์  ๊ฐœ๋ฐœ ์ ‘๊ทผ๋ฒ•์˜ ํ•„์š”์„ฑ
  • ์ดˆ๊ธฐ ๊ฐ€์ • ๊ฒ€์ฆ์˜ ์ค‘์š”์„ฑ
  • ์‹คํŒจ ์‚ฌ๋ก€๋ฅผ ํ†ตํ•œ ํ•™์Šต ํšจ๊ณผ
๐Ÿ’ญ ๊ฒฐ๋ก 

๋จธ์‹ ๋Ÿฌ๋‹์€ ๋งŒ๋Šฅ ํ•ด๊ฒฐ์ฑ…์ด ์•„๋‹ˆ๋ฉฐ, ๋ฐ์ดํ„ฐ ํ’ˆ์งˆ, ๋น„์ฆˆ๋‹ˆ์Šค ์ปจํ…์ŠคํŠธ, ํ˜„์‹ค์  ๊ธฐ๋Œ€์น˜ ์„ค์ •์ด ํ”„๋กœ์ ํŠธ ์„ฑ๊ณต์˜ ํ•ต์‹ฌ ์š”์†Œ์ž…๋‹ˆ๋‹ค. ๊ฒฝ์šฐ์— ๋”ฐ๋ผ ๋‹จ์ˆœํ•œ ๊ทœ์น™ ๊ธฐ๋ฐ˜ ์ ‘๊ทผ๋ฒ•์ด ๋ณต์žกํ•œ ML ๋ชจ๋ธ๋ณด๋‹ค ๋” ์‹ค์šฉ์ ์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

โš ๏ธ ํ–ฅํ›„ ๊ฐœ์„  ๋ฐฉํ–ฅ
  • ๋‹ค์ค‘ ์‹œ๋‚˜๋ฆฌ์˜ค ํ™œ์šฉ: 1๋…„ vs 2๋…„ vs 3๋…„ ํ•™์Šต ๋ฐ์ดํ„ฐ ์„ฑ๋Šฅ ๋น„๊ต
  • ์‹ค์‹œ๊ฐ„ ๊ฒ€์ฆ ์ฒด๊ณ„: 2025๋…„ ์‹ค์ œ ๋ฐ์ดํ„ฐ ํ™•๋ณด ์‹œ ์ง€์†์  ๋ชจ๋ธ ํ‰๊ฐ€
  • ์™ธ๋ถ€ ๊ฒฝ์ œ ์ง€ํ‘œ: GDP, ์ธํ”Œ๋ ˆ์ด์…˜, IT ํˆฌ์ž ์ง€์ˆ˜ ๋“ฑ ์ถ”๊ฐ€ ๋ณ€์ˆ˜ ํฌํ•จ
  • ๋น„์ฆˆ๋‹ˆ์Šค ์ปจํ…์ŠคํŠธ: ํ”„๋กœ์ ํŠธ ๊ณ„ํš, ์กฐ์ง ๋ณ€ํ™” ๋“ฑ ๋‚ด๋ถ€ ์š”์ธ ๋ฐ˜์˜
  • ์•™์ƒ๋ธ” ์ ‘๊ทผ๋ฒ•: ๋‹ค์ค‘ ๋ชจ๋ธ ์กฐํ•ฉ์„ ํ†ตํ•œ ์˜ˆ์ธก ์•ˆ์ •์„ฑ ํ–ฅ์ƒ
  • ์˜ˆ์ธก ๊ตฌ๊ฐ„ ์ œ๊ณต: ๋ถˆํ™•์‹ค์„ฑ์„ ํฌํ•จํ•œ ๊ตฌ๊ฐ„ ์˜ˆ์ธก์œผ๋กœ ์‹ค์šฉ์„ฑ ์ฆ๋Œ€
  • ์ ์ง„์  ํ•™์Šต: ์›”๋ณ„ ์‹ค์ œ ๋ฐ์ดํ„ฐ ํ™•๋ณด ์‹œ ๋ชจ๋ธ ์žฌํ•™์Šต ์ž๋™ํ™”

โ“ ์ฐธ๊ณ : ์ž์ฃผ ๋ฌป๋Š” ์งˆ๋ฌธ

๐Ÿ’ก ์ด ์„น์…˜์—์„œ๋Š” ML ํ”„๋กœ์ ํŠธ๋ฅผ ์ง„ํ–‰ํ•˜๋ฉด์„œ ์ž์ฃผ ๋ฐ›๋Š” ์งˆ๋ฌธ๋“ค๊ณผ ์˜คํ•ด๋“ค์„ ์ •๋ฆฌํ–ˆ์Šต๋‹ˆ๋‹ค.

Q1. ์ด๊ฒƒ์ด ํŒŒ์ธํŠœ๋‹์ธ๊ฐ€์š”?

A: ์•„๋‹™๋‹ˆ๋‹ค. ์ „ํ†ต์ ์ธ ๋จธ์‹ ๋Ÿฌ๋‹์ž…๋‹ˆ๋‹ค.
์šฐ๋ฆฌ ํ”„๋กœ์ ํŠธ (์ „ํ†ต์  ML):
# ์ฒ˜์Œ๋ถ€ํ„ฐ ์šฐ๋ฆฌ ๋ฐ์ดํ„ฐ๋กœ ํ•™์Šต
features = ['month_index', 'month_num', 'quarter', 'ma_3', 'ma_6']
model = RandomForestRegressor()
model.fit(X, y)  # ์ฒ˜์Œ๋ถ€ํ„ฐ ํ•™์Šต
ํŒŒ์ธํŠœ๋‹ (๋Œ€๊ทœ๋ชจ ์–ธ์–ด๋ชจ๋ธ):
# ์ด๋ฏธ ํ›ˆ๋ จ๋œ ๋ชจ๋ธ์„ ๊ฐ€์ ธ์™€์„œ ์ถ”๊ฐ€ ํ•™์Šต
pretrained_model = load_model("gpt-3.5")
fine_tuned_model = pretrained_model.fine_tune(my_data)

Q2. ๋ชจ๋ธ์ด 23๋…„โ†’24๋…„ ๋ณ€ํ™”๋ฅผ ํ•™์Šตํ•œ ๊ฑด๊ฐ€์š”?

A: ์•„๋‹™๋‹ˆ๋‹ค. ํŒจํ„ด์„ ํ•™์Šตํ–ˆ์Šต๋‹ˆ๋‹ค.
์ž˜๋ชป๋œ ์ดํ•ด ์‹ค์ œ ์ƒํ™ฉ
"23๋…„โ†’24๋…„ ๋ณ€ํ™”๋ฅผ ํ•™์Šต" "์›”๋ณ„, ๊ณ„์ ˆ๋ณ„ ํŒจํ„ด์„ ํ•™์Šต"
"์—ฐ๋„๋ณ„ ์ฐจ์ด๋ฅผ ํ•™์Šต" "ํŠน์„ฑ๊ณผ ๊ฒฐ๊ณผ์˜ ๊ด€๊ณ„๋ฅผ ํ•™์Šต"
๋ชจ๋ธ์ด ์‹ค์ œ๋กœ ํ•™์Šตํ•œ ํŒจํ„ด:
  • "1์›”์€ ๋ณดํ†ต 12์›”๋ณด๋‹ค 10% ์ฆ๊ฐ€ํ•œ๋‹ค"
  • "Q4๋Š” Q3๋ณด๋‹ค ํ‰๊ท  15% ์ฆ๊ฐ€ํ•œ๋‹ค"
  • "์ด๋™ํ‰๊ท ์ด ์ƒ์Šน ์ค‘์ผ ๋•Œ ๋‹ค์Œ ๋‹ฌ๋„ ์ฆ๊ฐ€ํ•œ๋‹ค"

Q3. ๊ทธ๋Ÿผ ์˜ˆ์ธก์ด ํ‹€๋ฆด ์ˆ˜๋ฐ–์— ์—†๋Š” ๊ฑฐ ์•„๋‹Œ๊ฐ€์š”?

A: ๋งž์Šต๋‹ˆ๋‹ค. ๊ทผ๋ณธ์  ํ•œ๊ณ„๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.
๋ชจ๋ธ์˜ ๊ธฐ๋ณธ ๊ฐ€์ •: "๊ณผ๊ฑฐ ํŒจํ„ด์ด ๋ฏธ๋ž˜์—๋„ ๋ฐ˜๋ณต๋œ๋‹ค"
ํ˜„์‹ค: 2025๋…„์—๋Š” ์ƒˆ๋กœ์šด ์š”์ธ๋“ค์ด ๋“ฑ์žฅ
  • ์ƒˆ๋กœ์šด AWS ์„œ๋น„์Šค ๋„์ž…
  • ๋น„์šฉ ์ตœ์ ํ™” ์ •์ฑ… ๋ณ€๊ฒฝ
  • ๊ฒฝ์ œ ์ƒํ™ฉ ๋ณ€ํ™”
  • ์‚ฌ์šฉ ํŒจํ„ด ๋ณ€ํ™”
๐Ÿ’ก ์ธ์‚ฌ์ดํŠธ: ์ด๋Ÿฐ "๋ป”ํ•œ ํ•œ๊ณ„"๋ฅผ ์ธ์‹ํ•˜๋Š” ๊ฒƒ ์ž์ฒด๊ฐ€ ์ค‘์š”ํ•œ ํ•™์Šต์ž…๋‹ˆ๋‹ค.

Q4. LLM์„ ์‚ฌ์šฉํ•˜๋ฉด ๋” ์ •ํ™•ํ•ด์งˆ๊นŒ์š”?

A: ๊ทผ๋ณธ์ ์œผ๋กœ๋Š” ํฌ๊ฒŒ ๋‹ฌ๋ผ์ง€์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
LLM์˜ ์žฅ์  (์ œํ•œ์ ):
  • ๋‹ค์–‘ํ•œ ์ •๋ณด ํ†ตํ•ฉ: ๊ฒฝ์ œ ๋‰ด์Šค, ์ •์ฑ… ๋ณ€ํ™” ๋“ฑ ๊ณ ๋ ค ๊ฐ€๋Šฅ
  • ์„ค๋ช… ๊ฐ€๋Šฅ์„ฑ: ์˜ˆ์ธก ์ด์œ ๋ฅผ ์ž์—ฐ์–ด๋กœ ์„ค๋ช…
ํ•˜์ง€๋งŒ ๊ทผ๋ณธ์  ํ•œ๊ณ„๋Š” ๋™์ผ:
  • ๊ณผ๊ฑฐ ๋ฐ์ดํ„ฐ์— ์˜์กด
  • ๋ฏธ๋ž˜์˜ ์ƒˆ๋กœ์šด ๋ณ€ํ™” ์˜ˆ์ธก ๋ถˆ๊ฐ€
  • ํ™˜๊ฐ(Hallucination) ์œ„ํ—˜
๐Ÿ’ญ ์†”์งํ•œ ๊ฒฐ๋ก : ๋„๋ฉ”์ธ ์ „๋ฌธ๊ฐ€์˜ ์ง๊ด€ + ๋‹จ์ˆœํ•œ ํ†ต๊ณ„๊ฐ€ ๋” ์‹ค์šฉ์ ์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
"๋‹ค์Œ ๋‹ฌ์— ์ƒˆ ํ”„๋กœ์ ํŠธ ์‹œ์ž‘ํ•˜๋‹ˆ๊นŒ ํ‰์†Œ๋ณด๋‹ค 30% ๋” ๋“ค ๊ฒƒ ๊ฐ™์•„" โ† ์ด๊ฒŒ ๋” ์ •ํ™•ํ•  ์ˆ˜ ์žˆ์–ด์š”!

Q5. ๊ทธ๋Ÿผ ML์€ ์˜๋ฏธ๊ฐ€ ์—†๋Š” ๊ฑด๊ฐ€์š”?

A: ์•„๋‹™๋‹ˆ๋‹ค. ์˜ฌ๋ฐ”๋ฅธ ๊ธฐ๋Œ€์น˜ ์„ค์ •์ด ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค.
ML์˜ ์‹ค์ œ ๊ฐ€์น˜:
  • ํŒจํ„ด ๋ฐœ๊ฒฌ: ์‚ฌ๋žŒ์ด ๋†“์น˜๋Š” ๋ฏธ๋ฌ˜ํ•œ ํŒจํ„ด ํƒ์ง€
  • ๋ฒ ์ด์Šค๋ผ์ธ ์ œ๊ณต: ์ „๋ฌธ๊ฐ€ ํŒ๋‹จ์˜ ์ถœ๋ฐœ์ 
  • ๊ฐ€์„ค ๊ฒ€์ฆ: "์ด๋Ÿฐ ์š”์ธ์ด ์˜ํ–ฅ์„ ์ค„๊นŒ?" ํ…Œ์ŠคํŠธ
  • ์ž๋™ํ™”: ๋ฐ˜๋ณต์ ์ธ ๋ถ„์„ ์ž‘์—… ํšจ์œจํ™”
์˜ฌ๋ฐ”๋ฅธ ํ™œ์šฉ๋ฒ•:
# ์ž˜๋ชป๋œ ๊ธฐ๋Œ€
"ML์ด ๋ฏธ๋ž˜๋ฅผ ์ •ํ™•ํžˆ ์˜ˆ์ธกํ•ด์ค„ ๊ฒƒ์ด๋‹ค"

# ์˜ฌ๋ฐ”๋ฅธ ๊ธฐ๋Œ€  
"ML์ด ๊ณผ๊ฑฐ ํŒจํ„ด์„ ๋ถ„์„ํ•ด์„œ ์ฐธ๊ณ  ์ž๋ฃŒ๋ฅผ ์ œ๊ณตํ•ด์ค„ ๊ฒƒ์ด๋‹ค"
"์ „๋ฌธ๊ฐ€๊ฐ€ ๋” ๋‚˜์€ ํŒ๋‹จ์„ ํ•  ์ˆ˜ ์žˆ๋„๋ก ๋„์›€์„ ์ค„ ๊ฒƒ์ด๋‹ค"

Q6. ์‹ค์ œ ์„œ๋น„์Šค๋กœ ๋งŒ๋“ค ๋•Œ๋Š” ์–ด๋–ป๊ฒŒ ํ•ด์•ผ ํ•˜๋‚˜์š”?

A: ์›น ์ธํ„ฐํŽ˜์ด์Šค์™€ API๋กœ ์„œ๋น„์Šคํ™”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
์„œ๋น„์Šคํ™” ๋‹จ๊ณ„:
1๋‹จ๊ณ„
์›น ์—…๋กœ๋“œ
CSV ํŒŒ์ผ ์—…๋กœ๋“œ
2๋‹จ๊ณ„
ํด๋ผ์šฐ๋“œ ๋ฐฐํฌ
AWS/Azure ๋ฐฐํฌ
3๋‹จ๊ณ„
API ์„œ๋น„์Šค
์ž๋™ํ™” ์—ฐ๋™
์‚ฌ์šฉ์ž ๊ฒฝํ—˜:
# CLI (ํ˜„์žฌ)
python predict.py --data costs.csv

# ์›น ์„œ๋น„์Šค (๋ชฉํ‘œ)
1. ๋ธŒ๋ผ์šฐ์ €์—์„œ ํŒŒ์ผ ์—…๋กœ๋“œ
2. "์˜ˆ์ธกํ•˜๊ธฐ" ๋ฒ„ํŠผ ํด๋ฆญ
3. ์ฐจํŠธ๋กœ ๊ฒฐ๊ณผ ํ™•์ธ

Q7. "10์›”์— A ์„œ๋น„์Šค ์ข…๋ฃŒ ์˜ˆ์ •"๊ฐ™์€ ์ •๋ณด๋Š” ์–ด๋–ป๊ฒŒ ๋ฐ˜์˜ํ•˜๋‚˜์š”?

A: ๋น„์ฆˆ๋‹ˆ์Šค ์ด๋ฒคํŠธ๋ฅผ ์‚ฌ์ „ ์ •์˜ํ•˜๊ณ  ์‚ฌ์šฉ์ž ์ž…๋ ฅ์„ ๋ฐ›์•„ ๋ฐ˜์˜ํ•ฉ๋‹ˆ๋‹ค.
๊ตฌํ˜„ ๋ฐฉ์‹:
1. ์‚ฌ์ „ ์ •์˜
์ด๋ฒคํŠธ ํ…œํ”Œ๋ฆฟ
โ†“
2. ์‚ฌ์šฉ์ž ์ž…๋ ฅ
๋‚ ์งœ, ๋น„์šฉ ์˜ํ–ฅ
โ†“
3. ๋กœ์ง ์ ์šฉ
์˜ˆ์ธก ์กฐ์ •
# ์‚ฌ์ „ ์ •์˜๋œ ์ด๋ฒคํŠธ ํƒ€์ž…
EVENTS = {
    'service_shutdown': {
        'name': '์„œ๋น„์Šค ์ข…๋ฃŒ',
        'impact': 'negative',
        'inputs': ['date', 'monthly_cost']
    },
    'service_launch': {
        'name': '์‹ ๊ทœ ์„œ๋น„์Šค',
        'impact': 'positive', 
        'inputs': ['date', 'expected_cost']
    }
}

# ์‚ฌ์šฉ์ž ์ž…๋ ฅ
event_type = "service_shutdown"
shutdown_date = "2025-10-01"
monthly_savings = 50000

# ์ž๋™ ์ ์šฉ
for month in prediction_timeline:
    if month >= shutdown_date:
        prediction[month] -= monthly_savings
์‚ฌ์šฉ์ž ์ธํ„ฐํŽ˜์ด์Šค ์˜ˆ์‹œ:
์ด๋ฒคํŠธ ํƒ€์ž…:
์‹œ์ž‘ ๋‚ ์งœ:
์›”๋ณ„ ๋น„์šฉ ์˜ํ–ฅ:

Q8. ML + ๋น„์ฆˆ๋‹ˆ์Šค ์ปจํ…์ŠคํŠธ ์กฐํ•ฉ์˜ ์žฅ์ ์€?

A: ๊ฐ๊ฐ์˜ ์žฅ์ ์„ ๊ฒฐํ•ฉํ•˜์—ฌ ์‹ค์šฉ์ ์ธ ์˜ˆ์ธก์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.
์ ‘๊ทผ๋ฒ• ์žฅ์  ํ•œ๊ณ„
ML๋งŒ ์‚ฌ์šฉ ๊ณผ๊ฑฐ ํŒจํ„ด ํ•™์Šต
๊ฐ๊ด€์  ๋ถ„์„
๋ฏธ๋ž˜ ๋ณ€ํ™” ์˜ˆ์ธก ๋ถˆ๊ฐ€
๋น„์ฆˆ๋‹ˆ์Šค ์ปจํ…์ŠคํŠธ ๋ฌด์‹œ
์ „๋ฌธ๊ฐ€ ์ง๊ฐ๋งŒ ๋น„์ฆˆ๋‹ˆ์Šค ์ดํ•ด
๋ฏธ๋ž˜ ๋ณ€ํ™” ๊ณ ๋ ค
์ฃผ๊ด€์  ํŽธํ–ฅ
์ผ๊ด€์„ฑ ๋ถ€์กฑ
ํ•˜์ด๋ธŒ๋ฆฌ๋“œ ์ ‘๊ทผ ํŒจํ„ด + ๋น„์ฆˆ๋‹ˆ์Šค ์ง€์‹
ํˆฌ๋ช…ํ•œ ์กฐ์ • ๊ณผ์ •
๋ณต์žก์„ฑ ์ฆ๊ฐ€
์œ ์ง€๋ณด์ˆ˜ ํ•„์š”
์‹ค์ œ ์˜ˆ์‹œ:
# ML ์˜ˆ์ธก: $85,000 (๊ณผ๊ฑฐ ํŒจํ„ด ๊ธฐ๋ฐ˜)
# ๋น„์ฆˆ๋‹ˆ์Šค ์กฐ์ •: -$50,000 (A ์„œ๋น„์Šค ์ข…๋ฃŒ)
# ์ตœ์ข… ์˜ˆ์ธก: $35,000

# ์„ค๋ช…: "๊ณผ๊ฑฐ ํŒจํ„ด์œผ๋กœ๋Š” $85K์ด์ง€๋งŒ, 
#       A ์„œ๋น„์Šค ์ข…๋ฃŒ๋กœ $50K ์ ˆ์•ฝ ์˜ˆ์ƒ"

Q9. ์ด๋Ÿฐ ์‹œ์Šคํ…œ์„ ์‹ค์ œ๋กœ ๊ตฌ์ถ•ํ•˜๋ ค๋ฉด ์–ผ๋งˆ๋‚˜ ๊ฑธ๋ฆฌ๋‚˜์š”?

A: ๋‹จ๊ณ„๋ณ„๋กœ ์ ‘๊ทผํ•˜๋ฉด ์ƒ๊ฐ๋ณด๋‹ค ๋น ๋ฅด๊ฒŒ ๊ตฌ์ถ• ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.
๊ฐœ๋ฐœ ์ผ์ • ์˜ˆ์ƒ:

Phase 1: MVP

1-2์ฃผ
โ€ข ํŒŒ์ผ ์—…๋กœ๋“œ ์›นํŽ˜์ด์ง€
โ€ข ๊ธฐ๋ณธ ์˜ˆ์ธก ๊ธฐ๋Šฅ
โ€ข ๊ฒฐ๊ณผ ํ‘œ์‹œ

Phase 2: ๊ฐœ์„ 

1๊ฐœ์›”
โ€ข ์‚ฌ์šฉ์ž ๊ณ„์ •
โ€ข ๋น„์ฆˆ๋‹ˆ์Šค ์ด๋ฒคํŠธ ์ž…๋ ฅ
โ€ข ์ฐจํŠธ/๊ทธ๋ž˜ํ”„

Phase 3: ์ž๋™ํ™”

2-3๊ฐœ์›”
โ€ข AWS API ์—ฐ๋™
โ€ข ์‹ค์‹œ๊ฐ„ ๋Œ€์‹œ๋ณด๋“œ
โ€ข ์•Œ๋ฆผ ์‹œ์Šคํ…œ
ํ•ต์‹ฌ ํฌ์ธํŠธ:
  • ํ˜„์žฌ ML ๋ชจ๋ธ์€ ๊ทธ๋Œ€๋กœ ํ™œ์šฉ - ์ธํ„ฐํŽ˜์ด์Šค๋งŒ ์ถ”๊ฐ€
  • ๋‹จ๊ณ„๋ณ„ ์ถœ์‹œ - ์™„๋ฒฝํ•˜์ง€ ์•Š์•„๋„ ์‚ฌ์šฉ์ž ํ”ผ๋“œ๋ฐฑ ์ˆ˜์ง‘
  • ํด๋ผ์šฐ๋“œ ํ™œ์šฉ - ์ธํ”„๋ผ ๊ตฌ์ถ• ์‹œ๊ฐ„ ๋‹จ์ถ•
๐ŸŽฏ ํ•ต์‹ฌ ๋ฉ”์‹œ์ง€
ML์€ ๋งŒ๋Šฅ์ด ์•„๋‹ˆ์ง€๋งŒ, ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์ดํ•ดํ•˜๊ณ  ํ™œ์šฉํ•˜๋ฉด ์ถฉ๋ถ„ํžˆ ๊ฐ€์น˜ ์žˆ๋Š” ๋„๊ตฌ์ž…๋‹ˆ๋‹ค. ์ค‘์š”ํ•œ ๊ฒƒ์€ ํ•œ๊ณ„๋ฅผ ์ธ์ •ํ•˜๊ณ , ๋„๋ฉ”์ธ ์ „๋ฌธ๊ฐ€์™€ ํ˜‘์—…ํ•˜๋ฉฐ, ์ง€์†์ ์œผ๋กœ ํ•™์Šตํ•˜๋Š” ์ž์„ธ์ž…๋‹ˆ๋‹ค.

๐Ÿ’ก ์ถ”๊ฐ€ ์ธ์‚ฌ์ดํŠธ: ๋น„์ฆˆ๋‹ˆ์Šค ์ปจํ…์ŠคํŠธ๋ฅผ ML๊ณผ ๊ฒฐํ•ฉํ•˜๋ฉด ์‹ค์šฉ์ ์ด๊ณ  ํˆฌ๋ช…ํ•œ ์˜ˆ์ธก ์‹œ์Šคํ…œ์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๐Ÿ”ฎ Prophet ์‹คํ—˜: ๋ชจ๋ธ ์„ ํƒ์˜ ์ค‘์š”์„ฑ

๐Ÿ’ก ํ•ต์‹ฌ ๊นจ๋‹ฌ์Œ: ๋ณต์žกํ•œ ํŠน์„ฑ ์—”์ง€๋‹ˆ์–ด๋ง๋ณด๋‹ค ์ ์ ˆํ•œ ๋ชจ๋ธ ์„ ํƒ์ด ๋” ์ค‘์š”ํ–ˆ์Šต๋‹ˆ๋‹ค.

์‹คํ—˜ ๋ฐฐ๊ฒฝ

๊ธฐ์กด ML ๋ชจ๋ธ์˜ ํ•œ๊ณ„๋ฅผ ๋А๋ผ๊ณ  "์™œ ์‹œ๊ณ„์—ด ์ „์šฉ ๋ชจ๋ธ์„ ์•ˆ ์ผ์„๊นŒ?"๋ผ๋Š” ์˜๋ฌธ์—์„œ ์‹œ์ž‘๋œ ์‹คํ—˜์ž…๋‹ˆ๋‹ค.

Prophet ์‹คํ—˜ ๊ณผ์ •

โŒ ๊ธฐ๋ณธ Prophet

โ€ข ๋ณต์žกํ•œ ํŠน์„ฑ (5๊ฐœ ํšŒ๊ท€๋ณ€์ˆ˜)
โ€ข ๊ณผ๋„ํ•œ ๊ณ„์ ˆ์„ฑ ์„ค์ •
โ€ข ์Œ์ˆ˜ ์˜ˆ์ธก ๋ฐœ์ƒ
๊ฒฐ๊ณผ: 57.5% ์˜ค์ฐจ

โœ… ์ตœ์ ํ™”๋œ Prophet

โ€ข ๋‹จ์ˆœํ•œ ํŠน์„ฑ (2๊ฐœ๋งŒ)
โ€ข ํ˜„์‹ค์ ์ธ ํ•™์Šต ๋ฐ์ดํ„ฐ
โ€ข ๊ณผ์ ํ•ฉ ๋ฐฉ์ง€ ์„ค์ •
๊ฒฐ๊ณผ: 14.6% ์˜ค์ฐจ

๐Ÿ“Š ๊ธฐ์กด ML

โ€ข 19๊ฐœ ๋ณต์žกํ•œ ํŠน์„ฑ
โ€ข 3๊ฐœ ๋ชจ๋ธ ์•™์ƒ๋ธ”
โ€ข ์ „ํ†ต์  ML ์ ‘๊ทผ
๊ฒฐ๊ณผ: 35.2% ์˜ค์ฐจ

์ตœ์ข… ์„ฑ๋Šฅ ๋น„๊ต

์ˆœ์œ„ ๋ชจ๋ธ ํ‰๊ท  ์˜ค์ฐจ์œจ ํŠน์ง•
๐Ÿ† 1์œ„ ์ตœ์ ํ™”๋œ Prophet 14.6% ๋‹จ์ˆœํ•จ + ์‹œ๊ณ„์—ด ์ „์šฉ
2์œ„ ๊ธฐ์กด ML (RF+GB+LR) 35.2% ๋ณต์žกํ•œ ํŠน์„ฑ ์—”์ง€๋‹ˆ์–ด๋ง
3์œ„ ๊ธฐ๋ณธ Prophet 57.5% ๊ณผ์ ํ•ฉ๋œ ๋ณต์žก ๋ชจ๋ธ

์ตœ์ ํ™”๋œ Prophet ์„ฑ๊ณต ์š”์ธ

# ํ•ต์‹ฌ: ๋‹จ์ˆœํ•จ์ด ์Šน๋ฆฌ
model = Prophet(
    changepoint_prior_scale=0.01,  # ํŠธ๋ Œ๋“œ ๋ณ€ํ™” ๋ฏผ๊ฐ๋„ ๋‚ฎ์ถค
    seasonality_prior_scale=1.0,   # ๊ณ„์ ˆ์„ฑ ๊ฐ•๋„ ์กฐ์ ˆ
    seasonality_mode='additive'    # ๋‹จ์ˆœํ•œ ๋ง์…ˆ ๋ชจ๋“œ
)

# ์ตœ์†Œํ•œ์˜ ๋น„์ฆˆ๋‹ˆ์Šค ํŠน์„ฑ๋งŒ
model.add_regressor('is_year_end')  # ์—ฐ๋ง ํšจ๊ณผ
model.add_regressor('is_q1')        # ์‹ ๋…„ ํšจ๊ณผ

Prophet์˜ ์ถ”๊ฐ€ ์žฅ์ 

๐ŸŽฏ ํ•ต์‹ฌ ๊ตํ›ˆ
๋ณต์žกํ•œ NLP๋‚˜ ํŠน์„ฑ ์—”์ง€๋‹ˆ์–ด๋ง์„ ์‹œ๋„ํ•˜๊ธฐ ์ „์— ์ ์ ˆํ•œ ๋ชจ๋ธ ์„ ํƒ์ด ์šฐ์„ ์ด์—ˆ์Šต๋‹ˆ๋‹ค.

์˜ฌ๋ฐ”๋ฅธ ์ˆœ์„œ:
  1. ์‹œ๊ณ„์—ด ์ „์šฉ ๋ชจ๋ธ ์‹œ๋„ (Prophet, ARIMA)
  2. ๊ธฐ๋ณธ ์„ฑ๋Šฅ ํ™•์ธ ํ›„ ํ•„์š”์‹œ ํŠน์„ฑ ์ถ”๊ฐ€
  3. ๋งˆ์ง€๋ง‰์— ๊ณ ๊ธ‰ ๊ธฐ๋ฒ• (NLP, ์•™์ƒ๋ธ”) ์ ์šฉ

์‹ค๋ฌด ์ ์šฉ ๊ฐ€๋Šฅ์„ฑ

โœ… ์ตœ์ ํ™”๋œ Prophet = ์‹ค๋ฌด ํ™œ์šฉ ๊ฐ€๋Šฅ

14.6% ํ‰๊ท  ์˜ค์ฐจ
์‹ค๋ฌด ๊ธฐ์ค€ (ยฑ15%) ๋‚ด ๋‹ฌ์„ฑ
์‹ค์ œ ์˜ˆ์ธก ๊ฒฐ๊ณผ (2025๋…„ 1-5์›”):
  • 1์›”: 19.0% ์˜ค์ฐจ
  • 2์›”: 21.5% ์˜ค์ฐจ
  • 3์›”: 9.5% ์˜ค์ฐจ
  • 4์›”: 12.0% ์˜ค์ฐจ
  • 5์›”: 11.0% ์˜ค์ฐจ

์ฝ”๋“œ ๊ตฌํ˜„

๊ตฌํ˜„ ํŒŒ์ผ: prophet_budget_prediction_v2.py

# ์ตœ์ ํ™”๋œ Prophet ํ•ต์‹ฌ ์ฝ”๋“œ
def build_simple_prophet_model(df):
    model = Prophet(
        yearly_seasonality=True,
        weekly_seasonality=False,
        daily_seasonality=False,
        changepoint_prior_scale=0.01,  # ๊ณผ์ ํ•ฉ ๋ฐฉ์ง€
        seasonality_prior_scale=1.0,   # ๊ณ„์ ˆ์„ฑ ์กฐ์ ˆ
        seasonality_mode='additive'
    )
    
    # ํ•ต์‹ฌ ํŠน์„ฑ๋งŒ
    model.add_regressor('is_year_end')
    model.add_regressor('is_q1')
    
    return model

# ์˜ˆ์ธก ์‹คํ–‰
model.fit(df)
future = model.make_future_dataframe(periods=12, freq='MS')
forecast = model.predict(future)

๐Ÿ’ญ ๊ฐœ์ธ์  ์ œ์–ธ: ๋‚˜๋ผ๋ฉด ์ด๋ ‡๊ฒŒ ํ•˜๊ฒ ๋‹ค

๐Ÿ“ ์ด ์„น์…˜์€ ํ”„๋กœ์ ํŠธ๋ฅผ ์ง„ํ–‰ํ•˜๋ฉด์„œ ์–ป์€ ๊ฐœ์ธ์  ๊ฒฝํ—˜๊ณผ ์ƒ๊ฐ์„ ์ •๋ฆฌํ•œ ๋‚ด์šฉ์ž…๋‹ˆ๋‹ค.
๐Ÿ”ฎ Prophet ์‹คํ—˜ ํ›„ ์—…๋ฐ์ดํŠธ: ๋ชจ๋ธ ์„ ํƒ์˜ ์ค‘์š”์„ฑ์„ ๊นจ๋‹ฌ์€ ํ›„ ์ˆ˜์ •๋œ ์ „๋žต์ž…๋‹ˆ๋‹ค.

0. ๋ชจ๋ธ ์„ ํƒ ์šฐ์„  ์ „๋žต (Prophet ์‹คํ—˜ ํ›„ ์ถ”๊ฐ€)

ํ•ต์‹ฌ ๊นจ๋‹ฌ์Œ: ๋ณต์žกํ•œ ๊ธฐ๋ฒ•๋ณด๋‹ค ์ ์ ˆํ•œ ๋ชจ๋ธ ์„ ํƒ์ด ์šฐ์„ 
์˜ฌ๋ฐ”๋ฅธ ์ˆœ์„œ:
1๋‹จ๊ณ„
์‹œ๊ณ„์—ด ๋ชจ๋ธ
Prophet, ARIMA
2๋‹จ๊ณ„
๊ธฐ๋ณธ ์„ฑ๋Šฅ ํ™•์ธ
์‹ค๋ฌด ๊ธฐ์ค€ ๋‹ฌ์„ฑ?
3๋‹จ๊ณ„
ํ•„์š”์‹œ ํŠน์„ฑ ์ถ”๊ฐ€
๋น„์ฆˆ๋‹ˆ์Šค ๋„๋ฉ”์ธ
4๋‹จ๊ณ„
๊ณ ๊ธ‰ ๊ธฐ๋ฒ•
NLP, ์•™์ƒ๋ธ”
# ์ž˜๋ชป๋œ ์ˆœ์„œ (์šฐ๋ฆฌ๊ฐ€ ํ•œ ๊ฒƒ)
1. ์ „ํ†ต์  ML๋ถ€ํ„ฐ ์‹œ์ž‘
2. ๋ณต์žกํ•œ ํŠน์„ฑ ์—”์ง€๋‹ˆ์–ด๋ง (19๊ฐœ)
3. ์•™์ƒ๋ธ” ๋ชจ๋ธ ๊ตฌ์ถ•
4. ์„ฑ๋Šฅ ๋ถ€์กฑ โ†’ ๋” ๋ณต์žกํ•œ ๊ธฐ๋ฒ• ์‹œ๋„

# ์˜ฌ๋ฐ”๋ฅธ ์ˆœ์„œ (Prophet ์‹คํ—˜ ํ›„)
1. Prophet ์‹œ๋„ โ†’ 14.6% ์˜ค์ฐจ ๋‹ฌ์„ฑ โœ…
2. ์‹ค๋ฌด ๊ธฐ์ค€ ๋งŒ์กฑ โ†’ ์™„๋ฃŒ
3. (ํ•„์š”์‹œ) ๋น„์ฆˆ๋‹ˆ์Šค ํŠน์„ฑ ์ถ”๊ฐ€
4. (ํ•„์š”์‹œ) ๊ณ ๊ธ‰ ๊ธฐ๋ฒ• ์ ์šฉ
๐Ÿ’ก ๊ฒฐ๋ก : ์ตœ์ ํ™”๋œ Prophet์œผ๋กœ 14.6% ์˜ค์ฐจ ๋‹ฌ์„ฑ โ†’ ์ถ”๊ฐ€ ๋ณต์žกํ™” ๋ถˆํ•„์š”

1. ์ž์—ฐ์–ด ์ž…๋ ฅ ๊ธฐ๋ฐ˜ ์‹œ์Šคํ…œ ๊ตฌ์ถ•

ํ˜„์žฌ ๋ฐฉ์‹์˜ ํ•œ๊ณ„:
# ์‚ฌ์ „ ์ •์˜๋œ ์ด๋ฒคํŠธ๋งŒ ์ฒ˜๋ฆฌ ๊ฐ€๋Šฅ
EVENTS = ['service_shutdown', 'service_launch', 'migration']
# โ†’ ์ƒˆ๋กœ์šด ์ƒํ™ฉ ์ƒ๊ธฐ๋ฉด ์ฝ”๋“œ ์ˆ˜์ • ํ•„์š”
์ œ์•ˆํ•˜๋Š” ๋ฐฉ์‹:
# ์ž์—ฐ์–ด ์ž…๋ ฅ โ†’ ๋™์  ํŒŒ๋ผ๋ฏธํ„ฐ ์ƒ์„ฑ
user_input = """
10์›”์— A ์„œ๋น„์Šค ์ข…๋ฃŒํ•˜๊ณ , 12์›”์— B ํ”„๋กœ์ ํŠธ ์‹œ์ž‘ํ•˜๋Š”๋ฐ 
์ดˆ๊ธฐ 3๊ฐœ์›”์€ ๋น„์šฉ์ด 2๋ฐฐ ๋“ค ๊ฒƒ ๊ฐ™์•„. 
์—ฌ๋ฆ„์— ํด๋ผ์šฐ๋“œ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ํ•˜๋ฉด์„œ 6๊ฐœ์›”๊ฐ„ 150% ์˜ˆ์ƒ.
"""

# LLM์ด ํŒŒ๋ผ๋ฏธํ„ฐ ์ถ”์ถœ โ†’ ๋™์  ์ฝ”๋“œ ์ƒ์„ฑ
parsed_events = llm_parse_business_context(user_input)
adjustment_code = generate_adjustment_code(parsed_events)
exec(adjustment_code)  # ์‹ค์‹œ๊ฐ„ ์ ์šฉ
์žฅ์ :
  • ๋ฏธ๋ฆฌ ์ •์˜ํ•˜์ง€ ์•Š์€ ๋ณต์žกํ•œ ์ƒํ™ฉ๋„ ์ฒ˜๋ฆฌ ๊ฐ€๋Šฅ
  • ์‚ฌ์šฉ์ž๊ฐ€ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ์„ค๋ช…ํ•˜๋ฉด ๋จ
  • ์ฝ”๋“œ ์ˆ˜์ • ์—†์ด ์ƒˆ๋กœ์šด ์‹œ๋‚˜๋ฆฌ์˜ค ๋Œ€์‘
โš ๏ธ ์ฃผ์˜์‚ฌํ•ญ: LLM ์ถœ๋ ฅ์˜ ์‹ ๋ขฐ์„ฑ ๊ฒ€์ฆ ํ•„์ˆ˜. ์‚ฌ์šฉ์ž ํ™•์ธ ๋‹จ๊ณ„ ๋ฐ˜๋“œ์‹œ ํฌํ•จ.

2. ๋‹จ๊ณ„๋ณ„ ๊ตฌ์ถ• ์ „๋žต (Prophet ๊ธฐ๋ฐ˜)

Phase 1: Prophet ๊ฒ€์ฆ

โ€ข ์ตœ์ ํ™”๋œ Prophet ๋ชจ๋ธ ๊ตฌํ˜„
โ€ข ์›น ์ธํ„ฐํŽ˜์ด์Šค (ํŒŒ์ผ ์—…๋กœ๋“œ)
โ€ข ๊ธฐ๋ณธ ์˜ˆ์ธก + ์‹ ๋ขฐ๊ตฌ๊ฐ„
๋ชฉํ‘œ: 14.6% ์˜ค์ฐจ ์žฌํ˜„

Phase 2: ์ž์—ฐ์–ด ํ†ตํ•ฉ

โ€ข Prophet + LLM ์กฐํ•ฉ
โ€ข ์ž์—ฐ์–ด โ†’ ๋น„์ฆˆ๋‹ˆ์Šค ์ด๋ฒคํŠธ
โ€ข ์‚ฌ์šฉ์ž ํ™•์ธ ํ”„๋กœ์„ธ์Šค
๋ชฉํ‘œ: ์œ ์—ฐ์„ฑ + ์ •ํ™•์„ฑ

Phase 3: ์ž๋™ํ™”

โ€ข AWS API ์ž๋™ ์—ฐ๋™
โ€ข ์‹ค์‹œ๊ฐ„ ๋Œ€์‹œ๋ณด๋“œ
โ€ข Prophet ๊ธฐ๋ฐ˜ ์•Œ๋ฆผ
๋ชฉํ‘œ: ์™„์ „ ์ž๋™ํ™”
๐Ÿ’ก ํ•ต์‹ฌ ๋ณ€ํ™”: ๊ธฐ์กด ML ๋Œ€์‹  Prophet์„ ๊ธฐ๋ฐ˜์œผ๋กœ ์‹œ์ž‘. ์ด๋ฏธ ์‹ค๋ฌด ๊ธฐ์ค€ ๋‹ฌ์„ฑํ–ˆ์œผ๋ฏ€๋กœ ์•ˆ์ •์  ๊ตฌ์ถ• ๊ฐ€๋Šฅ.

3. ๊ธฐ์ˆ  ์Šคํƒ ์„ ํƒ ๊ธฐ์ค€ (Prophet ๊ธฐ๋ฐ˜)

๊ตฌ๋ถ„ ์„ ํƒ ์ด์œ 
๋ฐฑ์—”๋“œ FastAPI ๋น ๋ฅธ ๊ฐœ๋ฐœ, ์ž๋™ ๋ฌธ์„œํ™”, Python ์ƒํƒœ๊ณ„
ํ”„๋ก ํŠธ์—”๋“œ HTML + JavaScript ๋‹จ์ˆœํ•จ, ๋น ๋ฅธ ํ”„๋กœํ† ํƒ€์ดํ•‘
ML ๋ชจ๋ธ Prophet 14.6% ์˜ค์ฐจ ๋‹ฌ์„ฑ, ์‹œ๊ณ„์—ด ์ „์šฉ
LLM OpenAI API ์•ˆ์ •์„ฑ, ๊ตฌ์กฐํ™”๋œ ์ถœ๋ ฅ ์ง€์›
๋ฐฐํฌ AWS ECS ๊ธฐ์กด AWS ํ™˜๊ฒฝ๊ณผ ํ†ตํ•ฉ, ํ™•์žฅ์„ฑ
ํ•ต์‹ฌ ๋ณ€ํ™”: scikit-learn ์•™์ƒ๋ธ” โ†’ Prophet ๋‹จ์ผ ๋ชจ๋ธ. ๋‹จ์ˆœํ•˜๋ฉด์„œ๋„ ๋” ์ •ํ™•ํ•จ.

4. ์‹คํŒจ ๋Œ€๋น„ ์ „๋žต

์˜ˆ์ƒ ์‹คํŒจ ์‹œ๋‚˜๋ฆฌ์˜ค์™€ ๋Œ€์‘:
  • LLM ํŒŒ์‹ฑ ์˜ค๋ฅ˜ โ†’ ์‚ฌ์šฉ์ž ํ™•์ธ ๋‹จ๊ณ„ + ์ˆ˜๋™ ์ˆ˜์ • ๊ธฐ๋Šฅ
  • ์˜ˆ์ธก ์ •ํ™•๋„ ๋ถˆ๋งŒ โ†’ ์‹ ๋ขฐ๊ตฌ๊ฐ„ ํ‘œ์‹œ + "์ฐธ๊ณ ์šฉ" ๋ช…์‹œ
  • ์‚ฌ์šฉ์ž ์ฑ„ํƒ ์ €์กฐ โ†’ ๊ธฐ์กด Excel ์›Œํฌํ”Œ๋กœ์šฐ์™€ ํ†ตํ•ฉ
  • ์œ ์ง€๋ณด์ˆ˜ ๋ถ€๋‹ด โ†’ ๋‹จ์ˆœํ•œ ์•„ํ‚คํ…์ฒ˜ + ์ถฉ๋ถ„ํ•œ ๋ฌธ์„œํ™”
# ์‹คํŒจ ๋Œ€๋น„ ์ฝ”๋“œ ์˜ˆ์‹œ
def safe_llm_parse(user_input):
    try:
        result = llm.parse(user_input)
        confidence = validate_result(result)
        
        if confidence < 0.7:
            return fallback_to_manual_input()
        
        return result
    except Exception:
        return fallback_to_manual_input()

def fallback_to_manual_input():
    return show_traditional_form()  # ๊ธฐ์กด ๋“œ๋กญ๋‹ค์šด ๋ฐฉ์‹

5. ์„ฑ๊ณต ์ง€ํ‘œ ์ •์˜

์ •๋Ÿ‰์  ์ง€ํ‘œ:
  • ์›” ํ™œ์„ฑ ์‚ฌ์šฉ์ž 10๋ช… ์ด์ƒ
  • ์˜ˆ์ธก ์š”์ฒญ ์›” 50ํšŒ ์ด์ƒ
  • LLM ํŒŒ์‹ฑ ์„ฑ๊ณต๋ฅ  80% ์ด์ƒ
  • ์‚ฌ์šฉ์ž ๋งŒ์กฑ๋„ 3.5/5 ์ด์ƒ
์ •์„ฑ์  ์ง€ํ‘œ:
  • ๊ธฐ์กด Excel ์ž‘์—… ๋Œ€์ฒด
  • ์˜ˆ์‚ฐ ํšŒ์˜์—์„œ ์‹ค์ œ ํ™œ์šฉ
  • ๋‹ค๋ฅธ ํŒ€์—์„œ ์‚ฌ์šฉ ๋ฌธ์˜
  • ์œ ์ง€๋ณด์ˆ˜ ๋ถ€๋‹ด ์ˆ˜์šฉ ๊ฐ€๋Šฅ
๐Ÿ’ญ ์†”์งํ•œ ๊ธฐ๋Œ€์น˜: ์™„๋ฒฝํ•œ ์˜ˆ์ธก๋ณด๋‹ค๋Š” "์˜ˆ์‚ฐ ํšŒ์˜์—์„œ ์ฐธ๊ณ ํ•  ๋งŒํ•œ ์ž๋ฃŒ" ์ˆ˜์ค€์ด๋ฉด ์„ฑ๊ณต

6. ์žฅ๊ธฐ์  ๋น„์ „

1๋…„ ํ›„ ๋ชฉํ‘œ:
# ์ด์ƒ์ ์ธ ์‚ฌ์šฉ ์‹œ๋‚˜๋ฆฌ์˜ค
์‚ฌ์šฉ์ž: "๋‹ค์Œ ๋‹ฌ์— ์‹ ๊ทœ ํ”„๋กœ์ ํŠธ 3๊ฐœ ์‹œ์ž‘ํ•˜๊ณ , 
        ์—ฌ๋ฆ„์— ๋ ˆ๊ฑฐ์‹œ ์‹œ์Šคํ…œ 3๊ฐœ ์ข…๋ฃŒ ์˜ˆ์ •์ด์•ผ"

์‹œ์Šคํ…œ: "ํŒŒ์•…ํ–ˆ์Šต๋‹ˆ๋‹ค. 
        3์›”๋ถ€ํ„ฐ ์›” $30K ์ฆ๊ฐ€, 7์›”๋ถ€ํ„ฐ ์›” $45K ์ ˆ์•ฝ ์˜ˆ์ƒ.
        ์‹ ๋ขฐ๋„: ์ค‘๊ฐ„. ํ™•์ธํ•˜์‹œ๊ฒ ์Šต๋‹ˆ๊นŒ?"

์‚ฌ์šฉ์ž: "๋งž์•„, ์ ์šฉํ•ด์ค˜"

์‹œ์Šคํ…œ: "2025๋…„ ์˜ˆ์‚ฐ ์˜ˆ์ธก์„ ์—…๋ฐ์ดํŠธํ–ˆ์Šต๋‹ˆ๋‹ค. 
        ๋ณด๊ณ ์„œ๋ฅผ ์ด๋ฉ”์ผ๋กœ ๋ฐœ์†กํ–ˆ์Šต๋‹ˆ๋‹ค."
ํ•ต์‹ฌ ๊ฐ€์น˜:
  • ํˆฌ๋ช…์„ฑ: ์˜ˆ์ธก ๊ทผ๊ฑฐ๋ฅผ ๋ช…ํ™•ํžˆ ์„ค๋ช…
  • ์œ ์—ฐ์„ฑ: ์ƒˆ๋กœ์šด ์ƒํ™ฉ์— ๋น ๋ฅด๊ฒŒ ์ ์‘
  • ์‹ค์šฉ์„ฑ: ์‹ค์ œ ์—…๋ฌด์— ๋„์›€์ด ๋˜๋Š” ์ˆ˜์ค€
  • ์ง€์†์„ฑ: ์œ ์ง€๋ณด์ˆ˜ ๊ฐ€๋Šฅํ•œ ๋‹จ์ˆœํ•จ
๐ŸŽฏ ์ตœ์ข… ์ œ์–ธ (Prophet ์‹คํ—˜ ํ›„ ์—…๋ฐ์ดํŠธ)
๊ฐœ์„ ๋œ ML๋กœ 14.6% ์˜ค์ฐจ๋ฅผ ๋‹ฌ์„ฑํ•œ ์ง€๊ธˆ, ์ถ”๊ฐ€ ๋ณต์žกํ™”๋Š” ๋ถˆํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

๐Ÿ’ก ํ•ต์‹ฌ ๊ตํ›ˆ:
  • ๋ชจ๋ธ ์„ ํƒ์ด ํŠน์„ฑ ์—”์ง€๋‹ˆ์–ด๋ง๋ณด๋‹ค ์ค‘์š”
  • ์‹œ๊ณ„์—ด ๋ฐ์ดํ„ฐ๋Š” ์‹œ๊ณ„์—ด ์ „์šฉ ๋ชจ๋ธ ์šฐ์„ 
  • ๋‹จ์ˆœํ•จ์ด ๋ณต์žกํ•จ์„ ์ด๊ธธ ์ˆ˜ ์žˆ๋‹ค
  • ์‹ค๋ฌด ๊ธฐ์ค€ ๋‹ฌ์„ฑ ์‹œ ์ถ”๊ฐ€ ์ตœ์ ํ™” ์‹ ์ค‘ํžˆ ํŒ๋‹จ
๐Ÿš€ ๋‹ค์Œ ํ”„๋กœ์ ํŠธ์—์„œ๋Š”:
  1. Prophet๋ถ€ํ„ฐ ์‹œ์ž‘
  2. ์‹ค๋ฌด ๊ธฐ์ค€ ๋‹ฌ์„ฑ ํ™•์ธ
  3. ํ•„์š”์‹œ์—๋งŒ ์ถ”๊ฐ€ ๊ธฐ๋ฒ• ์ ์šฉ
  4. ์‚ฌ์šฉ์ž ๊ฒฝํ—˜์— ์ง‘์ค‘
ํ”„๋กœ์ ํŠธ ๊ฐœ์š”
๊ธฐ๋ณธ ๋ชจ๋ธ
์„ฑ๋Šฅ ๊ฒ€์ฆ
๋ชจ๋ธ ๊ฐœ์„ 
๊ฒฐ๊ณผ ๋ถ„์„
Prophet ์‹คํ—˜
์ž์ฃผ ๋ฌป๋Š” ์งˆ๋ฌธ
๊ฐœ์ธ์  ์ œ์–ธ