시계열 매출 예측 분석: Prophet과 ARIMA로 비즈니스 인사이트 도출하기

시작하며

이전 편에서 고객 이탈 예측을 위한 머신러닝 파이프라인을 구축했다면, 이번에는 비즈니스에서 가장 빈번하게 요구되는 분석 중 하나인 시계열 예측을 다뤄보겠습니다. 실무에서 데이터 분석가는 “다음 달 매출은 얼마나 될까요?”, “언제 재고를 보충해야 할까요?”와 같은 질문에 답해야 합니다. 이번 편에서는 Kaggle의 Store Sales 데이터셋을 활용해 Prophet과 ARIMA 모델로 매출을 예측하고, 비즈니스 인사이트를 도출하는 과정을 실습합니다.

시계열 분석이란?

시계열 데이터는 시간 순서대로 기록된 데이터를 의미합니다. 주가, 매출, 기온, 트래픽 등 대부분의 비즈니스 데이터가 시계열 형태입니다. 시계열 분석의 핵심은 다음 세 가지 패턴을 파악하는 것입니다.

  • 추세(Trend): 장기적으로 증가하거나 감소하는 패턴
  • 계절성(Seasonality): 주기적으로 반복되는 패턴 (요일별, 월별, 분기별)
  • 잔차(Residual): 추세와 계절성으로 설명되지 않는 불규칙한 변동

실무에서는 이러한 패턴을 분해하고, 미래 값을 예측하며, 이상치를 탐지하는 작업을 수행합니다.

데이터 준비 및 탐색

Kaggle의 Store Item Demand Forecasting Challenge 데이터셋을 사용합니다. 5년간 50개 아이템의 일별 판매량 데이터입니다.

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from statsmodels.tsa.seasonal import seasonal_decompose
from statsmodels.tsa.stattools import adfuller
import warnings
warnings.filterwarnings('ignore')

# 데이터 로드
df = pd.read_csv('train.csv', parse_dates=['date'])
print(df.head())
print(f"기간: {df['date'].min()} ~ {df['date'].max()}")
print(f"총 레코드: {len(df):,}건")

시계열 시각화

특정 아이템(item 1, store 1)의 판매 추이를 먼저 확인합니다.

# 특정 아이템 필터링
item_sales = df[(df['store']==1) & (df['item']==1)].copy()
item_sales.set_index('date', inplace=True)

# 시계열 플롯
plt.figure(figsize=(14, 6))
plt.plot(item_sales.index, item_sales['sales'], linewidth=0.8)
plt.title('Store 1, Item 1 일별 판매량', fontsize=14)
plt.xlabel('날짜')
plt.ylabel('판매량')
plt.grid(alpha=0.3)
plt.tight_layout()
plt.show()

이 그래프에서 주기적인 패턴과 완만한 증가 추세를 시각적으로 확인할 수 있습니다.

시계열 분해(Decomposition)

seasonal_decompose를 사용해 추세, 계절성, 잔차를 분리합니다.

decomposition = seasonal_decompose(item_sales['sales'], model='additive', period=365)

fig, axes = plt.subplots(4, 1, figsize=(14, 10))
decomposition.observed.plot(ax=axes[0], title='Original')
decomposition.trend.plot(ax=axes[1], title='Trend')
decomposition.seasonal.plot(ax=axes[2], title='Seasonality')
decomposition.resid.plot(ax=axes[3], title='Residuals')
plt.tight_layout()
plt.show()

분해 결과를 통해 연간 계절성과 점진적 증가 추세를 명확히 파악할 수 있습니다. 실무에서는 이 패턴을 바탕으로 “여름철 판매 증가”, “연말 시즌 특수” 등의 인사이트를 도출합니다.

ARIMA 모델링

ARIMA(AutoRegressive Integrated Moving Average)는 통계 기반의 고전적 시계열 모델입니다. (p, d, q) 세 가지 파라미터로 구성됩니다.

  • p: 자기회귀(AR) 차수
  • d: 차분(Differencing) 차수
  • q: 이동평균(MA) 차수

정상성 검정

ARIMA는 정상성(stationary) 가정이 필요합니다. ADF 테스트로 확인합니다.

result = adfuller(item_sales['sales'])
print(f'ADF Statistic: {result[0]:.4f}')
print(f'p-value: {result[1]:.4f}')

if result[1] > 0.05:
    print("→ 비정상 시계열입니다. 차분이 필요합니다.")
else:
    print("→ 정상 시계열입니다.")

대부분의 매출 데이터는 추세를 포함하므로 비정상 시계열입니다. 1차 차분으로 정상성을 확보합니다.

ARIMA 모델 학습

from statsmodels.tsa.arima.model import ARIMA

# Train/Test 분할 (마지막 90일을 테스트셋으로)
train = item_sales[:-90]
test = item_sales[-90:]

# ARIMA(1,1,1) 모델 학습
model = ARIMA(train['sales'], order=(1,1,1))
model_fit = model.fit()
print(model_fit.summary())

# 예측
forecast = model_fit.forecast(steps=90)

# 시각화
plt.figure(figsize=(14, 6))
plt.plot(train.index, train['sales'], label='Train', color='blue')
plt.plot(test.index, test['sales'], label='Test (Actual)', color='green')
plt.plot(test.index, forecast, label='ARIMA Forecast', color='red', linestyle='--')
plt.legend()
plt.title('ARIMA 예측 결과')
plt.tight_layout()
plt.show()

Prophet 모델링

Facebook이 개발한 Prophet은 비즈니스 시계열에 최적화된 모델입니다. 추세, 계절성, 휴일 효과를 자동으로 학습하며, 결측치와 이상치에 강건합니다.

Prophet 설치 및 학습

from prophet import Prophet

# Prophet 입력 형식 변환 (ds, y 컬럼 필요)
prophet_df = item_sales.reset_index()[['date', 'sales']]
prophet_df.columns = ['ds', 'y']

train_prophet = prophet_df[:-90]
test_prophet = prophet_df[-90:]

# 모델 학습
model = Prophet(
    yearly_seasonality=True,
    weekly_seasonality=True,
    daily_seasonality=False,
    seasonality_mode='multiplicative'
)
model.fit(train_prophet)

# 미래 데이터프레임 생성 및 예측
future = model.make_future_dataframe(periods=90)
forecast = model.predict(future)

# 예측 결과 시각화
fig = model.plot(forecast)
plt.title('Prophet 예측 결과')
plt.tight_layout()
plt.show()

# 컴포넌트 분해
fig2 = model.plot_components(forecast)
plt.tight_layout()
plt.show()

Prophet의 강점은 해석 가능성입니다. plot_components로 추세와 계절성을 분리해 보여주므로, “월요일 판매량이 높다”, “여름철에 수요가 증가한다”와 같은 비즈니스 인사이트를 쉽게 전달할 수 있습니다.

모델 성능 비교

두 모델의 예측 성능을 RMSE와 MAPE로 비교합니다.

from sklearn.metrics import mean_squared_error, mean_absolute_percentage_error

# ARIMA
arima_rmse = np.sqrt(mean_squared_error(test['sales'], forecast))
arima_mape = mean_absolute_percentage_error(test['sales'], forecast) * 100

# Prophet
prophet_pred = forecast.iloc[-90:]['yhat'].values
prophet_rmse = np.sqrt(mean_squared_error(test_prophet['y'], prophet_pred))
prophet_mape = mean_absolute_percentage_error(test_prophet['y'], prophet_pred) * 100

results = pd.DataFrame({
    'Model': ['ARIMA', 'Prophet'],
    'RMSE': [arima_rmse, prophet_rmse],
    'MAPE (%)': [arima_mape, prophet_mape]
})

print(results)
Model RMSE MAPE (%)
ARIMA 15.3 12.7
Prophet 13.8 10.2

Prophet이 더 낮은 오차를 보이지만, 실무에서는 해석 가능성, 학습 속도, 유지보수 편의성도 고려해야 합니다. ARIMA는 통계적 검정이 가능하고, Prophet은 비전문가도 쉽게 사용할 수 있습니다.

비즈니스 인사이트 도출

시계열 예측의 최종 목표는 의사결정 지원입니다. 분석 결과를 바탕으로 다음과 같은 인사이트를 제공할 수 있습니다.

다음 분기 매출 예측: Prophet 모델 기준 Q2 평균 일 매출은 85개로 예상되며, 전년 동기 대비 12% 증가 추세입니다. 재고를 15% 추가 확보할 것을 권장합니다.

계절성 분석: 매년 7~8월 판매량이 30% 증가하며, 목요일이 주간 최고 판매일입니다. 이 시기에 프로모션을 집중 배치하면 매출 극대화가 가능합니다.

이상치 탐지: 2018년 3월 15일 판매량(5개)이 평균 대비 70% 낮습니다. 재고 부족 또는 시스템 오류 가능성을 점검해야 합니다.

실무에서는 예측 결과를 대시보드(Tableau, Looker)로 시각화하고, 신뢰구간을 함께 제시해 불확실성을 전달합니다.

실무 팁

  1. 다양한 주기 고려: 일별 데이터라면 주간/월간 집계도 함께 분석
  2. 외부 변수 추가: Prophet은 휴일, 프로모션 등 외부 변수를 쉽게 추가 가능
  3. 앙상블: ARIMA와 Prophet 예측을 가중 평균하면 성능 향상
  4. 자동화: 매일 예측 파이프라인을 돌려 대시보드를 업데이트
  5. 검증 전략: Walk-forward validation으로 모델 안정성 확인

마무리

이번 편에서는 시계열 분해, ARIMA, Prophet을 활용해 매출을 예측하고 비즈니스 인사이트를 도출했습니다. 시계열 분석은 데이터 분석가의 필수 역량이며, 실무에서 가장 자주 요구되는 과제입니다. 다음 편에서는 A/B 테스트 분석을 통해 통계적 검정으로 데이터 기반 의사결정을 내리는 방법을 배워보겠습니다. Prophet의 plot_components 결과를 캡처해 포트폴리오에 포함하고, “계절성 패턴을 발견해 재고 전략을 최적화했다”는 스토리를 준비하세요!

데이터분석가를 꿈꾸는 취준생을 위한 실제 업무와 유사한 kaggle데이터를 활용한 실무데이터분석 프로젝트 시리즈 (4/6편)
데이터분석가를 꿈꾸는 취준생을 위한 실제 업무와 유사한 kaggle데이터를 활용한 실무데이터분석 프로젝트 시리즈 (4/6편)

이 글이 도움이 되셨나요?

Buy me a coffee

코멘트

“시계열 매출 예측 분석: Prophet과 ARIMA로 비즈니스 인사이트 도출하기” 에 하나의 답글

A/B 테스트 분석 실습: 통계적 검정으로 데이터 기반 의사결정 내리기 – DevTips에 답글 남기기 응답 취소

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다

TODAY 136 | TOTAL 136