이 글은 누구를 위한 것인가
- 마켓플레이스 또는 자체 커머스 플랫폼의 가격 최적화를 고민하는 PM과 데이터 엔지니어
- AI 기반 가격 책정 시스템을 설계하거나 도입하려는 백엔드 개발자
- 경쟁사 대비 가격 경쟁력을 유지하면서도 마진을 높이고 싶은 이커머스 운영팀
들어가며
아마존은 하루에 약 250만 번 가격을 변경한다. 우버는 수요와 공급에 따라 실시간으로 요금을 조정한다. 항공사는 수개월 전부터 가격을 최적화한다. 이들의 공통점은 데이터 기반 동적 가격 책정이다.
국내에서도 쿠팡, 11번가, 배달의민족 등이 다양한 형태의 동적 가격 전략을 운영하고 있다. 중요한 것은 단순히 "가격을 내린다"가 아니라, 수익을 극대화하면서 고객 신뢰를 유지하는 균형을 찾는 것이다.
이 글에서는 마켓플레이스에서 AI 기반 동적 가격 책정 시스템을 어떻게 설계하는지 단계별로 설명한다.
이 글은 bluefoxdev.kr의 AI 기반 커머스 최적화 를 참고하고, 가격 알고리즘 설계 관점에서 확장하여 작성했습니다.
1. 동적 가격 책정의 핵심 개념
1.1 가격 탄력성(Price Elasticity) 이해
가격 탄력성은 가격 변화에 따른 수요 변화율이다.
가격 탄력성 = (수요 변화율 %) / (가격 변화율 %)
탄력성 > 1: 가격 민감 상품 (가격 내리면 수요 크게 증가)
탄력성 < 1: 가격 비민감 상품 (가격 올려도 수요 유지)
탄력성 = 1: 단위 탄력적
카테고리별 탄력성 특성:
| 카테고리 | 탄력성 | 가격 전략 |
|---|---|---|
| 생필품(화장지, 세제) | 낮음 (0.3~0.6) | 가격 인상 여지 있음 |
| 전자제품 | 중간 (0.8~1.2) | 경쟁사 모니터링 필수 |
| 패션/의류 | 높음 (1.5~2.5) | 시즌 할인 효과 큼 |
| 여행/항공 | 매우 높음 (2.0+) | 조기 예약 할인 효과 |
1.2 수익 최적화 목표 함수
단순히 판매량을 최대화하는 것이 아니라 이익을 최대화해야 한다.
def revenue_objective(price, demand_function, cost):
"""
목표: 가격 * 판매량 - 비용 최대화
"""
quantity = demand_function(price)
revenue = price * quantity
total_cost = cost * quantity
profit = revenue - total_cost
return profit
# 최적 가격 탐색
from scipy.optimize import minimize_scalar
result = minimize_scalar(
lambda p: -revenue_objective(p, demand_fn, unit_cost),
bounds=(min_price, max_price),
method='bounded'
)
optimal_price = result.x
2. 가격 책정 알고리즘 설계
2.1 Rule-Based → ML 기반 단계적 발전
동적 가격 시스템은 단계적으로 발전시키는 것이 현실적이다.
1단계: Rule-Based
- 경쟁사 가격 ±5% 자동 맞춤
- 재고 80% 이하 시 10% 할인
- 시간대별 할증/할인
2단계: Statistical Model
- 가격 탄력성 회귀 모델
- 계절성 보정
- 카테고리별 세분화
3단계: ML/AI
- 실시간 수요 예측
- 멀티 변수 최적화
- 강화학습 기반 가격 탐색
2.2 수요 예측 모델 (Python)
import pandas as pd
from sklearn.ensemble import GradientBoostingRegressor
from sklearn.preprocessing import StandardScaler
class DemandForecastModel:
def __init__(self):
self.model = GradientBoostingRegressor(
n_estimators=200,
learning_rate=0.05,
max_depth=5,
random_state=42
)
self.scaler = StandardScaler()
def prepare_features(self, df: pd.DataFrame) -> pd.DataFrame:
features = df.copy()
features['day_of_week'] = pd.to_datetime(features['date']).dt.dayofweek
features['month'] = pd.to_datetime(features['date']).dt.month
features['is_weekend'] = features['day_of_week'].isin([5, 6]).astype(int)
features['price_lag_1'] = features['price'].shift(1)
features['price_pct_change'] = features['price'].pct_change()
return features.dropna()
def train(self, df: pd.DataFrame):
features = self.prepare_features(df)
X = features[['price', 'day_of_week', 'month', 'is_weekend',
'price_lag_1', 'price_pct_change', 'competitor_price']]
y = features['quantity_sold']
X_scaled = self.scaler.fit_transform(X)
self.model.fit(X_scaled, y)
def predict_demand(self, price: float, context: dict) -> float:
X = [[price, context['day_of_week'], context['month'],
context['is_weekend'], context['price_lag'],
(price - context['price_lag']) / context['price_lag'],
context['competitor_price']]]
X_scaled = self.scaler.transform(X)
return self.model.predict(X_scaled)[0]
3. 경쟁사 가격 모니터링 시스템
3.1 아키텍처 설계
[경쟁사 사이트]
↓ (스크래핑 또는 가격 비교 API)
[가격 수집 서비스] → [데이터 정규화] → [가격 DB]
↓
[가격 분석 엔진] → [가격 결정 서비스] → [상품 가격 업데이트]
↑
[알림 서비스] (급격한 가격 변동 감지)
3.2 가격 비교 API 연동
직접 스크래핑 대신 Naver Shopping API, 다나와 API 등을 활용할 수 있다.
interface CompetitorPrice {
productId: string;
competitorId: string;
price: number;
availableStock: boolean;
capturedAt: Date;
}
class PriceMonitoringService {
async getMarketPrice(productId: string): Promise<CompetitorPrice[]> {
const [naverPrices, daanaPrices] = await Promise.all([
this.fetchNaverShoppingPrices(productId),
this.fetchDaanaPrices(productId),
]);
return [...naverPrices, ...daanaPrices];
}
calculateMarketPosition(
myPrice: number,
competitorPrices: CompetitorPrice[]
): { percentile: number; position: 'lowest' | 'middle' | 'highest' } {
const prices = competitorPrices.map(p => p.price).sort((a, b) => a - b);
const rank = prices.filter(p => p <= myPrice).length;
const percentile = (rank / prices.length) * 100;
if (percentile <= 20) return { percentile, position: 'lowest' };
if (percentile >= 80) return { percentile, position: 'highest' };
return { percentile, position: 'middle' };
}
}
4. 가격 제약 조건과 가드레일
4.1 셀러 보호 정책
마켓플레이스에서 플랫폼이 일방적으로 가격을 조정하면 셀러 신뢰를 잃는다. 다음 원칙을 지켜야 한다.
- 최저 가격 보장: 셀러가 설정한 최저 판매가 이하로 내리지 않음
- 가격 변동 한도: 1시간 내 최대 ±15% 이내로 제한
- 셀러 동의 옵션: 자동 가격 조정 on/off 권한 제공
- 투명한 이유 제공: 가격 변경 시 이유를 셀러 대시보드에 표시
4.2 소비자 보호 가드레일
interface PricingConstraints {
minPrice: number; // 원가 + 최소 마진
maxPrice: number; // MSRP 기준 최대 할증
maxHourlyChange: number; // 시간당 최대 변동률 (0.15 = 15%)
priceRounding: number; // 가격 단위 (100원 단위 등)
}
function applyConstraints(
suggestedPrice: number,
constraints: PricingConstraints,
previousPrice: number
): number {
// 변동률 제한
const maxChange = previousPrice * constraints.maxHourlyChange;
const clampedPrice = Math.max(
previousPrice - maxChange,
Math.min(previousPrice + maxChange, suggestedPrice)
);
// 최소/최대 범위 적용
const boundedPrice = Math.max(
constraints.minPrice,
Math.min(constraints.maxPrice, clampedPrice)
);
// 가격 반올림
return Math.round(boundedPrice / constraints.priceRounding) * constraints.priceRounding;
}
5. 실전 운영 전략
5.1 카테고리별 가격 책정 전략
| 카테고리 | 전략 | 빈도 |
|---|---|---|
| 전자제품 | 경쟁가 추종 | 1시간 |
| 패션/의류 | 재고 기반 할인 | 1일 |
| 생필품 | 탄력성 기반 최적화 | 1주 |
| 신선식품 | 유통기한 기반 할인 | 실시간 |
5.2 A/B 테스트로 알고리즘 검증
새로운 가격 책정 알고리즘은 반드시 A/B 테스트로 검증해야 한다. 전체 상품의 10%만 새 알고리즘 적용 → 2주간 결과 측정 → 통계적 유의성 확인 후 전체 적용.
마무리: 핵심 정리
동적 가격 책정은 "가격을 자주 바꾸는 것"이 아니라 데이터 기반으로 최적의 가격을 찾는 지속적인 프로세스다.
- 가격 탄력성 측정으로 시작
- Rule-Based → Statistical → ML 순으로 단계적 고도화
- 셀러와 소비자 보호 가드레일 필수
- A/B 테스트로 모든 알고리즘 변경 검증
수익 극대화와 고객 신뢰 유지의 균형을 잃지 않는 것이 장기 성공의 열쇠다.