Skip to main content
Summary

왜 예측 자동화가 필요한가

지금까지의 자동화는 주로 "이미 일어난 일"을 정리했다. 엑셀 파일을 모으고, 데이터베이스에 저장하고, 보고서를 만들고, 담당자에게 알렸다. 이것만으로도 큰 효과가 있지만 비즈니스 가치는 한 단계 더 나아갈 때 커진다. 바로 "앞으로 일어날 가능성이 높은 일"을 미리 보고 다음 행동을 정하는 것이다.

예를 들어 매출 보고서는 지난달 실적을 보여준다. 매출 예측은 다음 달 부족할 가능성이 있는 지역과 상품을 알려준다. 고객 목록은 현재 고객을 보여준다. 이탈 예측은 곧 떠날 가능성이 높은 고객을 알려준다. 재고 현황은 지금 창고에 있는 수량을 보여준다. 수요 예측은 다음 주에 어떤 상품이 부족해질지 알려준다.

이 장에서 말하는 의사결정 자동화는 AI가 모든 결정을 대신한다는 뜻이 아니다. 모델이 위험도, 가능성, 우선순위를 계산하고, 파이썬이 그 결과를 대시보드·알림·CRM 작업 목록으로 연결하는 구조다. 최종 할인 승인, 재고 대량 발주, 거래 차단처럼 영향이 큰 결정은 사람이 확인해야 한다.

예측과 의사결정 자동화하기AI 생성 이미지

예측 업무는 목표부터 정해야 한다

머신러닝 모델은 질문이 명확할 때 쓸모가 있다. "고객을 분석해 줘"는 좋은 목표가 아니다. "향후 30일 안에 해지할 가능성이 높은 고객을 찾아 줘"는 좋은 목표다. 모델의 예측 대상, 사용 시점, 후속 행동이 분명하기 때문이다.

실무에서 자주 쓰는 예측 자동화 데이터는 다음처럼 구성한다.

업무예측 대상주요 입력 데이터후속 행동
매출 예측다음 주·다음 달 매출 금액과거 매출, 요일, 월, 프로모션, 지역, 상품군목표 대비 부족 지역 알림
재고 수요 예측상품별 예상 판매량판매 이력, 현재 재고, 리드타임, 품절 이력, 시즌발주 후보 생성
고객 이탈 예측30일 내 이탈 여부최근 구매일, 구매 빈도, 구매 금액, 문의 건수, 로그인 기록CRM 유지 캠페인 등록
이상 거래 탐지비정상 거래 가능성거래 금액, 시간대, 고객 이력, 결제 수단, 지역검토 큐 등록 또는 승인 보류

핵심은 예측 시점에 알 수 없는 데이터를 입력에 넣지 않는 것이다. 이를 데이터 누수라고 한다. 예를 들어 "고객 해지일"을 이용해 "해지 가능성"을 예측하면 모델 성능은 높아 보이지만 실제 운영에서는 사용할 수 없다. 모델 학습 데이터는 반드시 예측 당시 사용할 수 있는 정보만 포함해야 한다.

데이터는 모델보다 중요하다

예측 자동화의 성패는 모델 종류보다 데이터 정의에서 더 많이 갈린다. 같은 고객 이탈 예측이라도 회사마다 이탈의 의미가 다르다. 구독 서비스는 결제 취소가 이탈일 수 있고, B2B 영업에서는 90일 이상 주문이 없는 상태가 이탈일 수 있다.

먼저 타깃을 정한다.

고객 이탈 예측 예시
- 기준일: 2026-05-01
- 예측 대상: 기준일 현재 활성 고객
- 타깃: 기준일 이후 30일 안에 해지 또는 미구매 상태가 되었는가
- 출력: 고객별 이탈 확률
- 행동: 확률 0.7 이상 고객을 CRM 유지 캠페인 목록에 등록

그다음 입력 변수를 만든다. 입력 변수는 모델이 판단에 사용하는 단서다.

customer_id
region
plan_type
tenure_days
last_purchase_days
purchase_count_90d
total_amount_90d
support_ticket_count_30d
login_count_30d
churned_30d

여기서 churned_30d가 정답 열이다. 과거 데이터에서는 이 고객이 실제로 30일 안에 이탈했는지 알 수 있으므로 학습에 사용한다. 운영 시점에는 이 열이 없고, 모델이 이 값을 확률로 예측한다.

scikit-learn으로 기본 모델 학습하기

파이썬에서 표 형태 예측 모델을 만들 때는 scikit-learn을 자주 사용한다. 기본 흐름은 단순하다. 데이터를 나누고, 전처리하고, 모델을 학습하고, 검증한 뒤, 새 데이터에 예측을 적용한다. 비즈니스 예측 모델도 이 흐름에서 크게 벗어나지 않는다.1

아래 예시는 고객 이탈 예측이다. 숫자 열은 빠진 값을 중앙값으로 채우고, 문자 열은 원-핫 인코딩으로 숫자화한다. 원-핫 인코딩은 region=Seoul, region=Busan 같은 범주 값을 모델이 읽을 수 있는 0과 1의 열로 바꾸는 방식이다.

from pathlib import Path
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.compose import ColumnTransformer
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import OneHotEncoder
from sklearn.impute import SimpleImputer
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import classification_report, roc_auc_score

DATA_DIR = Path("data")
OUTPUT_DIR = Path("output")
OUTPUT_DIR.mkdir(exist_ok=True)

# 1. 학습 데이터 읽기
df = pd.read_csv(DATA_DIR / "customer_churn_training.csv")

# 2. 입력과 정답 분리
id_col = "customer_id"
target_col = "churned_30d"

X = df.drop(columns=[id_col, target_col])
y = df[target_col]

numeric_features = [
    "tenure_days",
    "last_purchase_days",
    "purchase_count_90d",
    "total_amount_90d",
    "support_ticket_count_30d",
    "login_count_30d",
]

categorical_features = ["region", "plan_type"]

# 3. 전처리 정의
preprocess = ColumnTransformer(
    transformers=[
        ("num", SimpleImputer(strategy="median"), numeric_features),
        ("cat", Pipeline(steps=[
            ("imputer", SimpleImputer(strategy="most_frequent")),
            ("encoder", OneHotEncoder(handle_unknown="ignore")),
        ]), categorical_features),
    ]
)

# 4. 전처리와 모델을 하나의 파이프라인으로 묶기
model = Pipeline(steps=[
    ("preprocess", preprocess),
    ("classifier", RandomForestClassifier(
        n_estimators=200,
        random_state=42,
        class_weight="balanced"
    )),
])

# 5. 학습용과 검증용 데이터 분리
X_train, X_test, y_train, y_test = train_test_split(
    X, y,
    test_size=0.2,
    random_state=42,
    stratify=y
)

# 6. 학습
model.fit(X_train, y_train)

# 7. 검증
pred = model.predict(X_test)
proba = model.predict_proba(X_test)[:, 1]

print(classification_report(y_test, pred))
print("ROC-AUC:", roc_auc_score(y_test, proba))

여기서 정확도만 보면 안 된다. 이탈 고객이 전체의 5%라면 모두 "이탈하지 않음"이라고 예측해도 정확도는 95%가 될 수 있다. 하지만 이런 모델은 아무 가치가 없다. 이탈 예측에서는 실제 이탈 고객을 얼마나 잘 찾아내는지, 즉 재현율이 중요할 수 있다. 반대로 영업팀이 연락할 수 있는 고객 수가 제한적이라면, 예측한 고위험 고객 중 실제 이탈 고객 비율인 정밀도가 더 중요할 수 있다.

예측 결과를 업무 목록으로 바꾸기

모델의 출력은 보통 확률이다. 확률 자체는 업무가 아니다. 자동화의 가치는 이 확률을 사람이 실행할 수 있는 목록으로 바꿀 때 생긴다.

# 운영 대상 고객 데이터
new_df = pd.read_csv(DATA_DIR / "customer_churn_scoring.csv")

customer_ids = new_df[id_col]
X_new = new_df.drop(columns=[id_col])

new_df["churn_probability"] = model.predict_proba(X_new)[:, 1]

# 업무 기준 적용
new_df["priority"] = pd.cut(
    new_df["churn_probability"],
    bins=[0, 0.4, 0.7, 1.0],
    labels=["low", "medium", "high"],
    include_lowest=True
)

crm_tasks = new_df[new_df["priority"] == "high"][[
    "customer_id",
    "region",
    "plan_type",
    "churn_probability",
    "priority"
]].copy()

crm_tasks["task_type"] = "retention_call"
crm_tasks["status"] = "needs_review"

crm_tasks.to_csv(OUTPUT_DIR / "crm_retention_tasks.csv", index=False)

중요한 점은 status를 바로 approved로 두지 않는 것이다. 처음 운영할 때는 needs_review로 저장하고 담당자가 확인한다. 몇 주 동안 결과를 검토해 모델이 실제로 유용하다는 근거가 쌓이면 일부 저위험 작업부터 자동 등록할 수 있다.

이 파일은 이후 API 자동화와 연결할 수 있다. CRM API를 호출해 작업을 만들고, Slack이나 Teams에 "고위험 고객 35건이 검토 대기 중"이라는 알림을 보낼 수 있다. 대시보드에는 지역별 고위험 고객 수, 담당자별 처리 현황, 캠페인 후 실제 유지율을 보여준다.

수요 예측과 재고 판단은 시간 순서가 중요하다

매출·수요 예측은 고객 이탈 예측과 다르게 시간 순서가 중요하다. 과거 2년 데이터를 무작위로 섞어 학습·검증하면 미래 예측 성능을 과대평가할 수 있다. 실제 운영에서는 과거로 미래를 맞혀야 하기 때문이다.

간단한 수요 예측 데이터는 다음처럼 만들 수 있다.

sales_date
product_id
category
weekday
month
is_holiday
promotion_flag
price
stockout_flag
sales_qty

sales_qty가 예측할 값이다. 이 문제는 숫자를 예측하므로 분류가 아니라 회귀 문제다. 검증도 과거 기간으로 학습하고 이후 기간으로 테스트하는 방식이 적절하다.

from sklearn.ensemble import RandomForestRegressor
from sklearn.metrics import mean_absolute_error

sales = pd.read_csv(DATA_DIR / "daily_product_sales.csv", parse_dates=["sales_date"])
sales = sales.sort_values("sales_date")

train = sales[sales["sales_date"] < "2026-04-01"]
test = sales[sales["sales_date"] >= "2026-04-01"]

features = ["product_id", "category", "weekday", "month", "is_holiday", "promotion_flag", "price"]
target = "sales_qty"

X_train = train[features]
y_train = train[target]
X_test = test[features]
y_test = test[target]

# 문자형 열이 있다면 앞의 ColumnTransformer 구조를 재사용한다.
reg_model = Pipeline(steps=[
    ("preprocess", preprocess),
    ("regressor", RandomForestRegressor(n_estimators=200, random_state=42)),
])

reg_model.fit(X_train, y_train)
pred_qty = reg_model.predict(X_test)

print("MAE:", mean_absolute_error(y_test, pred_qty))

MAE는 평균 절대 오차다. 예측 수량이 실제 수량과 평균적으로 몇 개 차이 나는지 보여준다. 재고 업무에서는 이 숫자가 이해하기 쉽다. "모델 성능이 0.82"보다 "상품별 일 판매량 예측이 평균 12개 정도 빗나간다"가 담당자에게 더 유용하다.

예측을 의사결정 자동화로 연결하기

예측 결과는 세 가지 방식으로 업무에 연결된다.

첫째, 대시보드다. 경영진이나 팀장은 전체 추세를 본다. 다음 달 매출 예상, 고위험 고객 수, 품절 예상 상품 수, 이상 거래 건수를 한눈에 확인한다.

둘째, 알림이다. 담당자가 바로 행동해야 하는 항목을 알려준다. 예를 들어 "3일 내 품절 예상 상품 12개" 또는 "이상 거래 점수 0.9 이상 5건"처럼 기준을 넘은 항목만 보낸다.

셋째, 작업 목록이다. CRM, ERP, 티켓 시스템에 실제 할 일을 만든다. 이때 모델 점수만 저장하지 말고 판단 근거가 되는 주요 입력값도 함께 저장해야 한다.

CRM 작업 목록 예시
- customer_id: C10291
- churn_probability: 0.82
- priority: high
- reason_data: 최근 구매 75일 전, 30일 로그인 0회, 문의 3건
- recommended_action: 유지 혜택 안내 전화
- status: needs_review

처음부터 완전 자동 실행을 목표로 하지 않는다. 추천 목록을 만들고, 사람이 처리하고, 처리 결과를 다시 데이터로 저장한다. 이 피드백이 쌓여야 모델과 업무 규칙을 개선할 수 있다.

모델 운영에서 반드시 점검할 것

예측 모델은 한 번 만들고 끝나는 프로그램이 아니다. 시간이 지나면 고객 행동, 가격 정책, 상품 구성, 프로모션 방식이 바뀐다. 그러면 과거 데이터로 학습한 모델의 성능이 떨어질 수 있다. 운영 환경에서는 데이터 변화와 모델 성능 저하를 감지해야 한다.2

점검 항목은 다음과 같다.

  • 입력 데이터 건수가 갑자기 줄거나 늘었는가

  • 주요 열의 누락값 비율이 증가했는가

  • 지역, 상품군, 고객 등급 분포가 과거와 달라졌는가

  • 예측 확률이 한쪽으로 치우치기 시작했는가

  • 고위험으로 분류된 고객의 실제 이탈률이 낮아졌는가

  • 추천 작업을 처리한 후 성과가 개선되고 있는가

  • 모델이 특정 고객군에 불리하게 작동하지 않는가

간단한 운영 로그도 필요하다.

from datetime import datetime

monitoring = {
    "run_at": datetime.now().isoformat(),
    "input_rows": len(new_df),
    "high_priority_rows": int((new_df["priority"] == "high").sum()),
    "avg_churn_probability": float(new_df["churn_probability"].mean()),
    "missing_login_count_30d": int(new_df["login_count_30d"].isna().sum()),
}

pd.DataFrame([monitoring]).to_csv(
    OUTPUT_DIR / "model_run_log.csv",
    mode="a",
    header=not (OUTPUT_DIR / "model_run_log.csv").exists(),
    index=False
)

이 로그는 단순하지만 중요하다. 어느 날 입력 데이터가 10만 건에서 500건으로 줄었다면 모델 문제가 아니라 데이터 수집 문제가 먼저 의심된다. 평균 이탈 확률이 평소 0.18이었는데 갑자기 0.75가 되었다면 입력 데이터 형식이나 모델 버전을 확인해야 한다.

자동 결정에는 승인 단계를 둔다

AutoML처럼 데이터 준비, 모델 선택, 튜닝, 평가 일부를 자동화하는 도구도 있다. 이런 도구는 반복 작업을 줄이고 빠르게 후보 모델을 찾는 데 도움이 된다. 하지만 비즈니스 맥락, 데이터 품질, 비용, 해석 가능성, 과적합 위험까지 자동으로 해결하지는 못한다.3

따라서 예측 자동화에는 승인 기준을 둔다.

  • 정보 제공: 대시보드에만 표시한다.

  • 추천: 담당자에게 다음 행동을 제안한다.

  • 반자동 실행: 기준 이하 금액·저위험 항목만 자동 등록한다.

  • 승인 후 실행: 할인, 발주, 거래 보류는 담당자가 승인한다.

  • 자동 실행 금지: 법적·재무적 영향이 큰 결정은 사람이 최종 결정한다.

모델은 확률을 계산한다. 업무 규칙은 그 확률을 어떤 행동으로 바꿀지 정한다. 사람은 위험한 결정을 검토한다. 이 세 가지 역할이 분리되어야 안전하다.

작게 시작하는 예측 자동화 절차

처음부터 전사 예측 시스템을 만들 필요는 없다. 다음 순서가 현실적이다.

  1. 하나의 업무 질문을 정한다. 예: "다음 30일 이탈 가능 고객 찾기"

  2. 예측 결과를 사용할 팀과 행동을 정한다.

  3. 과거 데이터를 모아 타깃과 입력 변수를 만든다.

  4. 단순한 기준 모델을 만든다.

  5. 검증 지표를 업무 언어로 해석한다.

  6. 예측 결과를 CSV나 대시보드로 제공한다.

  7. 담당자가 결과를 검토하고 처리 결과를 남긴다.

  8. 성능, 비용, 오류, 데이터 변화를 모니터링한다.

  9. 충분히 안정적일 때만 일부 작업을 자동 등록한다.

예측 자동화의 목적은 사람을 빼는 것이 아니다. 사람이 매일 모든 고객, 모든 상품, 모든 거래를 같은 깊이로 볼 수 없기 때문에 우선순위를 계산해 주는 것이다. 파이썬은 데이터를 모으고 모델을 실행한다. 머신러닝은 가능성을 계산한다. 업무 시스템은 그 결과를 실행 가능한 목록으로 바꾼다. 사람은 중요한 결정과 예외 상황을 검토한다.

이 구조를 지키면 예측 모델은 단순한 분석 결과가 아니라 실제 업무 흐름을 바꾸는 자동화 자산이 된다.

참고

1Building Predictive Business AI Models With Python And Scikit-Learn

2Compare 45+ MLOps Tools in 2026

3What Is AutoML?

책 목록

파이썬과 AI를 활용한 비즈니스 자동화

전체 목차 보기

이 노트는 보도·비평·교육·연구 목적으로 작성되었습니다. 저작권 문의가 있으시면 에서 알려주세요.

틸노트는 사용자가 AI를 활용해 노트를 쉽게 작성하거나 편집할 수 있는 서비스입니다.

AI 스퀘어 단톡방에 함께해요

AI 활용과 틸노트 사용 팁을 나누는 오픈채팅방입니다. 입장 비밀번호는 tilnote입니다.

참여하기