직관 vs 데이터, 83.7%에서 만나다

서로에게 질문하며 성장하는 AI와 영업팀의 이야기 - 2화

by Chris

"Chris, 이거 틀렸어요."

2025년 4월, 월요일 아침 9시. 민준 과장이 내 책상 앞에 노트북을 펼쳐 놓으며 말했다. 화면에는 우리의 새로운 XGBoost 모델이 추천한 고객 리스트가 떠 있었다.

"3번, 김영수 대표. 이 사람은 절대 안 돼요. 작년에 세 번이나 미팅했는데 매번 '지금은 예산이 없다'고 했거든요."

나는 모델의 예측 점수를 확인했다. 87.2점. 상위 5% 안에 드는 높은 점수였다.

"하지만 데이터상으로는..."

"데이터가 뭘 알아요." 민준 과장이 고개를 저었다. "15년 영업한 제 감으로는 이 사람, 올해도 안 됩니다."


Random Forest 이후, 더 깊은 질문

첫 번째 모델이 성공한 지 6개월이 지났다. 72.3%의 정확도는 팀에게 작은 신뢰를 주었지만, 동시에 더 큰 기대를 낳았다.

"Chris, 이제 좀 더 정교하게 만들 수 없을까요?"

프로젝트 매니저 주영이가 물었다.

"Random Forest는 좋았어요. 근데 왜 이 고객이 유망한지, 구체적으로 설명하기가 애매해요. '거래액이 높아서'가 전부잖아요. 우리는 더 알고 싶어요. 이 고객이 정확히 무엇에 관심 있는지, 언제 접촉하면 좋은지."

그건 나도 느끼고 있던 한계였다.


15만 건의 행동 데이터

이번엔 데이터부터 달랐다.

단순한 CRM 기록이 아니라, 실제 고객들이 우리 플랫폼에서 '무엇을 했는지'를 추적했다. 이커머스 플랫폼 파트너사 15만 개의 행동 로그.

어떤 기능 페이지를 방문했나 (마케팅 자동화? 데이터 분석? 재고 관리?)

얼마나 오래 머물렀나

어떤 가이드 문서를 다운로드했나

고객센터에 어떤 질문을 했나

무료 체험 신청 후 실제로 사용했나


"이건... 엄청난 데이터네요."

Python Jupyter Notebook을 켜고 데이터를 불러왔다.


import pandas as pd import numpy as np

# 데이터 로드

behavior_logs = pd.read_csv('customer_behavior_logs.csv')

purchase_history = pd.read_csv('purchase_history.csv')

crm_data = pd.read_csv('crm_master.csv')

print(f"행동 로그: {len(behavior_logs):,}건")

print(f"구매 이력: {len(purchase_history):,}건")

print(f"CRM 고객: {len(crm_data):,}명")


행동 로그: 152,847건 구매 이력: 15,023건 CRM 고객: 12,445명

15만 건. 이전 프로젝트의 30배.



XGBoost, 경사를 따라 학습하는 알고리즘

이번엔 Random Forest가 아니라 XGBoost를 선택했다.

왜?

Random Forest는 각 트리가 독립적으로 학습한다. 서로 다른 데이터 샘플을 보고, 투표로 결정한다. 좋은 방법이지만, 한계가 있다. 이전 트리의 '실수'에서 배우지 못한다.

XGBoost는 다르다. Gradient Boosting이라는 기법을 쓴다.

첫 번째 트리가 예측한다. 틀린다. 두 번째 트리는 그 '틀린 부분'을 집중적으로 학습한다. 세 번째 트리는 또 남은 오류를 잡는다. 이렇게 순차적으로, 점진적으로, 오류를 줄여간다.

마치 산을 오를 때 가장 가파른 경사를 따라가는 것처럼.


import xgboost as xgb

from sklearn.model_selection

import train_test_split

# 피처 엔지니어링

features = pd.DataFrame()

# 행동 패턴 피처

features['visit_frequency'] = behavior_logs.groupby('customer_id')['page_view'].count()

features['avg_session_duration'] = behavior_logs.groupby('customer_id')['duration_seconds'].mean()

features['feature_interest_score'] = behavior_logs.groupby('customer_id')['premium_feature_views'].sum()

# 구매 이력 피처

features['purchase_recency'] = (pd.Timestamp.now() - purchase_history['last_purchase_date']).dt.days

features['purchase_frequency'] = purchase_history.groupby('customer_id').size()

features['avg_order_value'] = purchase_history.groupby('customer_id')['order_amount'].mean()

# CRM 기본 피처

features['company_age_months'] = crm_data['company_age_months']

features['employee_count'] = crm_data['employee_count']

features['industry_code'] = crm_data['industry_encoded']

# 총 23개 피처

print(f"최종 피처 수: {features.shape[1]}")


23개 피처. 이전의 12개에서 거의 두 배로 늘었다.


직관을 수치화하기

"Chris, 한 가지 부탁이 있어요."

민준 과장이 회의실에서 말했다.

"제가 15년 동안 영업하면서 느낀 건데요. 고객 업종이 중요해요. 같은 거래액이어도, 패션업계와 식품업계는 완전히 달라요. 패션은 시즌 타는데, 식품은 안정적이거든요."

"그럼 업종별로 전환율을 따로 계산해서 피처로 넣으면 어떨까요?"

"오, 그거 좋은데요?"

이게 바로 '도메인 지식'과 '데이터 사이언스'가 만나는 순간이었다.


# 업종별 전환율 계산

industry_conversion = crm_data.groupby('industry').agg({ 'converted': ['mean', 'count'] }).reset_index()

industry_conversion.columns = ['industry', 'conversion_rate', 'sample_count']

# 최소 샘플 수 필터링 (신뢰도 확보)

industry_conversion = industry_conversion[industry_conversion['sample_count'] >= 30]

# 고객 데이터에 매핑

features['industry_conversion_rate'] = features['industry_code'].map( industry_conversion.set_index('industry')['conversion_rate'] )

print("\\n업종별 전환율 Top 5:")

print(industry_conversion.nlargest(5, 'conversion_rate')[['industry', 'conversion_rate']])


업종별 전환율 Top 5:

industry conversion_rate

건강/뷰티 0.34

식품 0.31

가구/인테리어 0.28

반려동물용품 0.26

육아/출산 0.24


민준 과장의 직관이 맞았다. 업종마다 전환율이 확연히 달랐다.


83.7%라는 숫자가 나오기까지

하이퍼파라미터 튜닝에만 사흘이 걸렸다.

XGBoost는 조정할 수 있는 노브가 많다. 너무 많다.


from sklearn.model_selection import GridSearchCV

# 파라미터 그리드

param_grid = { 'max_depth': [3, 5, 7, 9], # 트리 깊이

'learning_rate': [0.01, 0.05, 0.1], # 학습률

'n_estimators': [100, 200, 300], # 트리 개수

'min_child_weight': [1, 3, 5], # 리프 노드 최소 가중치

'subsample': [0.7, 0.8, 0.9], # 샘플링 비율

'colsample_bytree': [0.7, 0.8, 0.9], # 피처 샘플링

}

# GridSearchCV로 최적 파라미터 탐색

xgb_model = xgb.XGBClassifier(

objective='binary:logistic',

eval_metric='auc',

random_state=42 )

grid_search = GridSearchCV(

xgb_model,

param_grid,

cv=5,

scoring='roc_auc',

n_jobs=-1,

verbose=1 )

grid_search.fit(X_train, y_train)

print(f"최적 파라미터: {grid_search.best_params_}")

print(f"최고 AUC 점수: {grid_search.best_score_:.4f}")



4 × 3 × 3 × 3 × 3 × 3 = 324개 조합.

각 조합마다 5-Fold 교차 검증.

총 1,620번의 모델 학습.

컴퓨터가 밤새 돌아갔다.


최적 파라미터: { 'max_depth': 7,

'learning_rate': 0.05,

'n_estimators': 200,

'min_child_weight': 3,

'subsample': 0.8,

'colsample_bytree': 0.8 }

최고 AUC 점수: 0.8521


최종 모델을 학습시키고, 테스트 세트에 적용했다.

# 최종 모델 학습

final_model = xgb.XGBClassifier(**grid_search.best_params_)

final_model.fit(X_train, y_train)

# 테스트 세트 평가

y_pred = final_model.predict(X_test)

y_pred_proba = final_model.predict_proba(X_test)[:, 1]

from sklearn.metrics import accuracy_score, roc_auc_score, classification_report

accuracy = accuracy_score(y_test, y_pred)

auc = roc_auc_score(y_test, y_pred_proba)

print(f"\\n=== 최종 모델 성능 ===")

print(f"정확도: {accuracy:.3f}")

print(f"AUC 점수: {auc:.3f}")

print(f"\\n개선 효과: {(accuracy - 0.723) / 0.723 * 100:.1f}%")

=== 최종 모델 성능 ===

정확도: 0.837

AUC 점수: 0.891

개선 효과: 15.8%


83.7%.

Random Forest의 72.3%에서 11.4%p 상승.



"김영수 대표 건, 제가 틀렸습니다"

3주 후, 민준 과장이 팀 회의에서 말했다.

"여러분, 기억하시죠? 제가 모델 결과가 틀렸다고 했던 김영수 대표?"

다들 고개를 끄덕였다.

"어제 계약했습니다. 3년 프리미엄 플랜."

"뭐라고요?"

"알고 보니까 그 사이에 회사 상황이 완전히 바뀌었더라고요. 작년 말에 시리즈 A 투자 받고, 올해 초에 직원 10명 늘어났어요. 그래서 이제 본격적으로 시스템 갖추려는 거였죠."

민준 과장이 웃으며 말을 이었다.

"근데 신기한 게, 모델은 그걸 알고 있었어요. 어떻게? 행동 로그를 봤더니, 최근 3개월간 프리미엄 기능 페이지 방문이 급증했고, 가격 문의도 여러 번 했더라고요. 저는 그냥 '작년에 안 된 사람'으로만 기억했는데..."

그가 노트북을 열어 모델의 피처 중요도를 보여줬다.

# Feature Importance 시각화

import matplotlib.pyplot as plt

feature_importance = pd.DataFrame({

'feature': X_train.columns,

'importance': final_model.feature_importances_ }).sort_values('importance', ascending=False)

plt.figure(figsize=(10, 8))

plt.barh(feature_importance['feature'][:15], feature_importance['importance'][:15])

plt.xlabel('Importance')

plt.title('XGBoost Feature Importance - Top 15')

plt.tight_layout()

plt.show()

print("\\nTop 10 중요 피처:")

print(feature_importance.head(10))


Top 10 중요 피처:

feature importance

0 feature_interest_score 0.182

1 avg_session_duration 0.156

2 industry_conversion_rate 0.134

3 visit_frequency 0.121

4 avg_order_value 0.098

5 purchase_frequency 0.087

6 company_age_months 0.072

7 purchase_recency 0.061

8 premium_guide_download 0.054

9 employee_count 0.035


"봐요, 1위가 '프리미엄 기능 관심 점수'예요. 이 사람이 최근에 얼마나 우리 고급 기능에 관심 있었는지를 나타내는 거죠."

회의실이 조용해졌다.


응답률 2.3배, 그리고 깨달음

2개월간의 A/B 테스트 결과.

XGBoost 추천 고객 (200명)

응답률: 53.5%

상담 전환율: 44.2%

계약 체결율: 8.5%


기존 Random Forest (200명)

응답률: 37.6%

상담 전환율: 28.3%

계약 체결율: 4.8%


응답률이 2.3배 차이는 아니지만, 1.42배 상승했다. 계약 체결율은 1.77배.

하지만 숫자보다 중요한 건 다른 것이었다.

"Chris, 이제 알겠어요."

민준 과장이 커피를 마시며 말했다.

"데이터와 직관은 경쟁하는 게 아니라, 협력하는 거더라고요. 제 15년 경험은 여전히 소중해요. 그 경험을 '업종 특성'이라는 피처로 만들었잖아요. 근데 데이터는 제가 놓친 걸 잡아줘요. 김영수 대표처럼 최근에 변한 사람들."

"맞아요. 그래서 이게 '인터랙션 사이언스'예요. AI가 사람을 대체하는 게 아니라, 서로 질문하고 배우는 거죠."

"AI에게 묻는 거죠. '이 고객은 왜 유망해?' 그러면 AI가 '최근 3개월간 프리미엄 기능을 10번 봤어요'라고 답해주고. 그럼 저는 '아, 그럼 프리미엄 기능 설명부터 시작해야겠네'라고 전략을 짜는 거고."


그날 밤, 나의 노트

"83.7%는 단순한 정확도 숫자가 아니었다. 이건 사람과 AI가 서로의 언어를 배우기 시작한 지점이다.

민준 과장은 이제 모델에게 '왜?'라고 묻는다. Feature Importance를 보고, 이 고객이 왜 높은 점수를 받았는지 이해하려 한다. 그리고 그 이해를 바탕으로 더 나은 영업 전략을 짠다.

나는 민준 과장에게 '어떤 고객이 어려워요?'라고 묻는다. 그의 15년 경험을 듣고, 그걸 피처로 만든다. '업종별 전환율'처럼.

XGBoost가 Random Forest보다 11.4%p 정확도가 높은 이유는 단순히 알고리즘이 더 좋아서가 아니다. 우리가 23개 피처로 늘렸고, 그 중 절반은 민준 과장의 직관에서 나온 것이기 때문이다.

직관과 데이터는 83.7%에서 만났다. 그리고 함께 더 나은 질문을 하기 시작했다."


- 더 알아보기: XGBoost 시스템 아키텍처

"15만 건의 데이터를 어떻게 처리했는지 궁금하신가요?"

이번 프로젝트의 전체 파이프라인을 상세하게 정리했습니다. 행동 로그 수집부터 23개 피처 엔지니어링, XGBoost 하이퍼파라미터 튜닝, 그리고 83.7% 정확도를 달성한 전체 과정까지.

- XGBoost 아키텍처 다이어그램 다운로드 (PPTX)

실제 사용한 피처 목록, GridSearchCV 설정, A/B 테스트 설계가 모두 포함되어 있습니다.


다음 편 예고: "AI가 쓴 메시지가 더 따뜻했던 이유"

GPT-4가 우리 팀에 합류한 날. 8,000건의 영업 대화를 학습한 AI는 무엇을 배웠을까? 그리고 왜 베테랑 영업사원이 AI의 메시지를 보고 울컥했을까?


#인터랙션사이언스 #XGBoost #머신러닝고도화 #데이터와직관 #AI영업자동화 #피처엔지니어링 #행동데이터분석 #영업팀AI #세일즈테크 #83.7프로의비밀

작가의 이전글72.3%: Random Forest가 가져온 작은변화