가격 최적화 분석 (Pricing Analytics)¶
개요¶
가격 최적화 분석은 수익 극대화, 시장 점유율 확보, 고객 가치 극대화를 위한 가격 전략 수립 방법론이다. 수요 탄력성, 경쟁 가격, 고객 세그먼트를 종합적으로 분석한다.
분석 프레임워크¶
1. 가격 탄력성 분석¶
수요의 가격 탄력성(PED):
\[
PED = \frac{\% \Delta Q}{\% \Delta P} = \frac{\partial Q / Q}{\partial P / P}
\]
| PED 값 | 해석 | 가격 전략 |
|---|---|---|
| |PED| > 1 | 탄력적 | 가격 인하로 수익 증가 |
| |PED| = 1 | 단위 탄력적 | 가격 변화 무관 |
| |PED| < 1 | 비탄력적 | 가격 인상으로 수익 증가 |
추정 방법:
import pandas as pd
import numpy as np
from scipy.optimize import curve_fit
import statsmodels.api as sm
def estimate_price_elasticity(df: pd.DataFrame) -> dict:
"""
df: price, quantity, (controls) 컬럼 포함
"""
# 로그-로그 회귀 (상수 탄력성 모델)
df['log_price'] = np.log(df['price'])
df['log_quantity'] = np.log(df['quantity'])
X = sm.add_constant(df['log_price'])
y = df['log_quantity']
model = sm.OLS(y, X).fit()
elasticity = model.params['log_price']
se = model.bse['log_price']
return {
'elasticity': elasticity,
'std_error': se,
'r_squared': model.rsquared,
'interpretation': 'elastic' if abs(elasticity) > 1 else 'inelastic'
}
# 사용 예시
# result = estimate_price_elasticity(sales_data)
# print(f"가격 탄력성: {result['elasticity']:.2f}")
2. 수요 함수 추정¶
선형 수요 함수: $$ Q = a - bP + cI + dA + \epsilon $$
- Q: 수요량
- P: 가격
- I: 소득
- A: 광고비
- a, b, c, d: 추정 계수
로그-선형 수요 함수: $$ \ln Q = \alpha + \beta \ln P + \gamma \ln I + \delta \ln A + \epsilon $$
def fit_demand_function(df: pd.DataFrame, model_type: str = 'linear') -> dict:
"""수요 함수 추정"""
if model_type == 'linear':
X = df[['price', 'income', 'ad_spend']]
X = sm.add_constant(X)
y = df['quantity']
elif model_type == 'log_linear':
X = np.log(df[['price', 'income', 'ad_spend']])
X = sm.add_constant(X)
y = np.log(df['quantity'])
model = sm.OLS(y, X).fit()
return {
'coefficients': model.params.to_dict(),
'r_squared': model.rsquared,
'price_elasticity': model.params['price'] if model_type == 'log_linear' else None
}
3. 최적 가격 도출¶
이윤 극대화 가격:
이윤 함수: $$ \pi = (P - MC) \cdot Q(P) $$
1차 조건 (FOC): $$ \frac{\partial \pi}{\partial P} = Q + (P - MC) \cdot \frac{\partial Q}{\partial P} = 0 $$
최적 가격 공식 (마크업): $$ P^* = \frac{MC}{1 + \frac{1}{PED}} $$
def optimal_price(marginal_cost: float, elasticity: float) -> float:
"""이윤 극대화 가격 계산"""
if abs(elasticity) <= 1:
raise ValueError("탄력성 절대값이 1보다 커야 함 (수익 극대화 조건)")
markup = 1 / (1 + 1/elasticity)
optimal_p = marginal_cost / markup
return optimal_p
# 예시: MC=100, PED=-2
# optimal_price(100, -2) = 200
가격 전략 유형¶
1. 침투 가격 (Penetration Pricing)¶
- 목적: 시장 점유율 확보
- 적용: 신제품 출시, 네트워크 효과 시장
- 특징: 초기 저가 → 점진적 인상
| 단계 | 가격 | 목표 |
|---|---|---|
| 출시 | 경쟁사 -30% | 인지도 확보 |
| 성장 | 경쟁사 -15% | 점유율 20% |
| 성숙 | 시장 평균 | 수익성 회복 |
2. 스키밍 가격 (Skimming Pricing)¶
- 목적: 초기 고수익 확보
- 적용: 혁신 제품, 특허 보호 시장
- 특징: 초기 고가 → 점진적 인하
3. 가치 기반 가격 (Value-Based Pricing)¶
- 핵심: 고객이 인지하는 가치 기준
- 방법: Conjoint Analysis, Van Westendorp
Van Westendorp 분석:
def van_westendorp_analysis(df: pd.DataFrame) -> dict:
"""
df 컬럼: too_cheap, cheap, expensive, too_expensive
"""
prices = np.linspace(df['too_cheap'].min(), df['too_expensive'].max(), 100)
# 누적 분포 계산
too_cheap_cum = [(df['too_cheap'] >= p).mean() for p in prices]
cheap_cum = [(df['cheap'] >= p).mean() for p in prices]
expensive_cum = [(df['expensive'] <= p).mean() for p in prices]
too_expensive_cum = [(df['too_expensive'] <= p).mean() for p in prices]
# 교차점 찾기
# PMC (Point of Marginal Cheapness): too_cheap = expensive
# PME (Point of Marginal Expensiveness): too_expensive = cheap
# OPP (Optimal Price Point): too_cheap = too_expensive
# IPP (Indifference Price Point): cheap = expensive
results = {
'acceptable_range': (find_intersection(too_cheap_cum, expensive_cum, prices),
find_intersection(too_expensive_cum, cheap_cum, prices)),
'optimal_price': find_intersection(too_cheap_cum, too_expensive_cum, prices),
'indifference_price': find_intersection(cheap_cum, expensive_cum, prices)
}
return results
def find_intersection(curve1, curve2, prices):
diff = np.array(curve1) - np.array(curve2)
idx = np.argmin(np.abs(diff))
return prices[idx]
4. 동적 가격 (Dynamic Pricing)¶
실시간 수요/공급에 따른 가격 조정.
적용 산업: - 항공: 좌석 가용성, 예약 시점 - 호텔: 점유율, 시즌 - 이커머스: 경쟁 가격, 재고 - 라이드셰어: 수요/공급 비율 (서지 프라이싱)
class DynamicPricer:
def __init__(self, base_price: float, min_price: float, max_price: float):
self.base_price = base_price
self.min_price = min_price
self.max_price = max_price
def calculate_price(
self,
demand_ratio: float, # 현재 수요 / 평균 수요
inventory_ratio: float, # 현재 재고 / 최대 재고
competitor_price: float = None
) -> float:
"""동적 가격 계산"""
# 수요 계수 (수요 높으면 가격 상승)
demand_factor = 1 + 0.5 * (demand_ratio - 1)
# 재고 계수 (재고 적으면 가격 상승)
inventory_factor = 1 + 0.3 * (1 - inventory_ratio)
# 경쟁 계수
if competitor_price:
comp_factor = 0.9 + 0.2 * (competitor_price / self.base_price)
else:
comp_factor = 1.0
# 최종 가격
price = self.base_price * demand_factor * inventory_factor * comp_factor
# 범위 제한
return np.clip(price, self.min_price, self.max_price)
세그먼트별 가격 차별화¶
가격 차별화 유형¶
| 유형 | 설명 | 예시 |
|---|---|---|
| 1급 | 개인별 지불의사 추출 | 경매, 협상 |
| 2급 | 수량/버전별 차등 | 볼륨 디스카운트, Freemium |
| 3급 | 세그먼트별 차등 | 학생 할인, 지역별 가격 |
세그먼트 가격 최적화¶
def segment_price_optimization(segments: list[dict]) -> dict:
"""
각 세그먼트별 최적 가격 계산
segments = [
{'name': 'premium', 'size': 1000, 'elasticity': -1.5, 'wtp_mean': 150},
{'name': 'standard', 'size': 5000, 'elasticity': -2.5, 'wtp_mean': 80},
{'name': 'budget', 'size': 10000, 'elasticity': -4.0, 'wtp_mean': 40},
]
"""
results = {}
mc = 30 # 한계비용 가정
for seg in segments:
ped = seg['elasticity']
# 마크업 가격
optimal_p = mc / (1 + 1/ped)
# 예상 수요 (가격 변화에 따른)
price_change = (optimal_p - seg['wtp_mean']) / seg['wtp_mean']
quantity_change = price_change * ped
expected_quantity = seg['size'] * (1 + quantity_change)
# 예상 이익
profit = (optimal_p - mc) * expected_quantity
results[seg['name']] = {
'optimal_price': round(optimal_p, 2),
'expected_quantity': int(expected_quantity),
'expected_profit': round(profit, 0)
}
return results
경쟁 가격 분석¶
가격 포지셔닝 맵¶
경쟁 가격 모니터링¶
from dataclasses import dataclass
from typing import Optional
import requests
@dataclass
class CompetitorPrice:
competitor: str
product: str
price: float
timestamp: str
url: Optional[str] = None
class CompetitorPriceTracker:
def __init__(self):
self.price_history: list[CompetitorPrice] = []
def add_price(self, price_data: CompetitorPrice):
self.price_history.append(price_data)
def get_price_position(self, our_price: float, product: str) -> dict:
"""우리 가격의 경쟁 포지션"""
product_prices = [
p.price for p in self.price_history
if p.product == product
]
if not product_prices:
return {'position': 'unknown'}
avg_price = np.mean(product_prices)
min_price = np.min(product_prices)
max_price = np.max(product_prices)
percentile = (our_price - min_price) / (max_price - min_price) * 100
return {
'our_price': our_price,
'market_avg': round(avg_price, 2),
'market_min': round(min_price, 2),
'market_max': round(max_price, 2),
'percentile': round(percentile, 1),
'vs_avg': f"{((our_price/avg_price)-1)*100:+.1f}%"
}
가격 실험 (A/B 테스트)¶
실험 설계¶
| 요소 | 권장 |
|---|---|
| 샘플 크기 | MDE 5% 기준 ~10,000/그룹 |
| 기간 | 최소 2주 (주간 변동 고려) |
| 가격 변동폭 | 10-20% (너무 크면 이탈) |
| 측정 지표 | 전환율, AOV, LTV, 이탈률 |
from scipy import stats
def price_ab_test_analysis(
control_conversions: int,
control_visitors: int,
treatment_conversions: int,
treatment_visitors: int,
control_aov: float,
treatment_aov: float
) -> dict:
"""가격 A/B 테스트 분석"""
# 전환율
cr_control = control_conversions / control_visitors
cr_treatment = treatment_conversions / treatment_visitors
# 전환율 차이 유의성 (Z-test)
pooled_cr = (control_conversions + treatment_conversions) / \
(control_visitors + treatment_visitors)
se = np.sqrt(pooled_cr * (1 - pooled_cr) * \
(1/control_visitors + 1/treatment_visitors))
z_stat = (cr_treatment - cr_control) / se
p_value = 2 * (1 - stats.norm.cdf(abs(z_stat)))
# 매출 (RPV: Revenue per Visitor)
rpv_control = cr_control * control_aov
rpv_treatment = cr_treatment * treatment_aov
rpv_lift = (rpv_treatment - rpv_control) / rpv_control
return {
'conversion_rate': {
'control': round(cr_control * 100, 2),
'treatment': round(cr_treatment * 100, 2),
'lift': f"{((cr_treatment/cr_control)-1)*100:+.1f}%",
'p_value': round(p_value, 4)
},
'aov': {
'control': round(control_aov, 0),
'treatment': round(treatment_aov, 0),
'lift': f"{((treatment_aov/control_aov)-1)*100:+.1f}%"
},
'revenue_per_visitor': {
'control': round(rpv_control, 2),
'treatment': round(rpv_treatment, 2),
'lift': f"{rpv_lift*100:+.1f}%"
},
'recommendation': 'treatment' if rpv_treatment > rpv_control and p_value < 0.05 else 'control'
}
산업별 적용¶
| 산업 | 주요 방법 | 핵심 변수 |
|---|---|---|
| SaaS | 가치 기반, Freemium | 기능 차등, 사용량 |
| 이커머스 | 동적 가격, 경쟁 기반 | 재고, 경쟁가, 시즌 |
| 항공/호텔 | 수익 관리 (RM) | 좌석/객실 가용성 |
| 제조 | 비용+ 가격 | 원가, 마진 타겟 |
| B2B | 협상, 볼륨 디스카운트 | 계약 규모, 관계 |
체크리스트¶
- [ ] 가격 탄력성 추정
- [ ] 수요 함수 모델링
- [ ] 고객 세그먼트별 WTP 분석
- [ ] 경쟁 가격 벤치마크
- [ ] 최적 가격점 도출
- [ ] A/B 테스트 설계
- [ ] 가격 민감도 모니터링
참고 자료¶
- The Strategy and Tactics of Pricing - Nagle & Holden
- Predictably Irrational - Dan Ariely
마지막 업데이트: 2026-03-04