비즈니스 문제와 후보 변수 식별 — 호텔 예약 사례 깊이 들여다보기 (Buisson Ch.4.1)

Starter CD 에서 6 카테고리 후보 brainstorm 까지, 단계 1 의 전체 절차

Buisson (2021) Ch.4 의 첫 두 절을 정리한다. 호텔 예약 사례에서 시작 CD (NRDeposit → IsCanceled) 를 정의하고, 데이터에 보이는 직관 위반 (보증금 시 95% 취소율) 을 confounder 로 해석한 후, 6 카테고리 (Past Actions, Intentions, Cognition, Personal, Business, Time) 에서 후보 변수를 brainstorm 하는 절차를 단계별로 시연한다.

Experimentation
Causal Inference
저자

Kwangmin Kim

공개

2026년 05월 08일

1 정의

정의: Starter CD 와 후보 brainstorm

DAG 구축의 단계 1 (Buisson, 2021, Ch.4):

  1. Starter CD: 분석 질문을 한 줄 화살표로 표현
  2. 데이터로 1차 점검: 단순 분포·교차표로 직관 충돌 식별
  3. Confounder 가설: 직관 충돌이 있으면 미관측 공통 원인 가설
  4. 6 카테고리 brainstorm: Past Actions, Intentions, Cognition, Personal, Business, Time Trends 에서 후보 변수 추출
직관 — 단계 1 이 어려운 이유

분석가가 “후보 변수 식별” 단계에서 자주 빠지는 함정:

  • 데이터 의존: “있는 컬럼만 본다” — 진짜 중요한 미관측 변수 놓침
  • 첫 인상 의존: “처음 떠오른 1~2개로 시작” — 빠진 카테고리 발견 못 함
  • 순서 의존: “데이터 → 가설” 순서 — Hypothesis-driven 이 아니라 Data-dredging

대신 권장:

“5 분 동안 6 카테고리에서 변수 brainstorm. 그 후에야 데이터 본다.”

이 한 가지 습관이 분석의 깊이를 결정한다.

2 호텔 예약 사례 — 비즈니스 문제 정의

2.1 데이터셋 소개

Antonio 등의 호텔 예약 데이터

Antonio, Almeida, Nunes (2019) 의 공개 데이터셋. 같은 도시 두 호텔의 약 87000 건 예약 (City Hotel + Resort Hotel).

import pandas as pd
df = pd.read_csv("hotel_bookings.csv")
print(df.shape)  # (87,395, 32)
print(df.columns.tolist())

핵심 변수:

변수 설명 유형
NRDeposit 환불 불가 보증금 여부 Binary
IsCanceled 예약 취소 여부 Binary
DistributionChannel 예약 경로 Categorical
CustomerType 고객 유형 (Transient, Group, etc) Categorical
MarketSegment 시장 세그먼트 Categorical
Children 동반 아동 수 Integer
ADR 일평균 객실료 Numeric
PreviousCancellation 과거 취소 이력 Binary
IsRepeatedGuest 재방문 여부 Binary
Country 국적 Categorical
Quarter, Year 시점 Categorical

2.2 Starter CD

분석 질문 → CD 한 줄

분석 질문:

“환불 불가 보증금이 예약 취소율에 영향을 주는가?”

비즈니스 동기:

  • 만약 NRD 가 취소를 줄인다 → 모든 예약에 NRD 적용 (정책 강화)
  • 만약 NRD 가 취소를 늘린다 → 의외 결과, 추가 조사 필요
  • 만약 효과 없다 → 정책 변경 불필요

CD 시작:

NRDeposit (Y/N) ──→ IsCanceled (Y/N)

이 한 줄이 모든 분석의 뿌리.

2.3 데이터로 첫 점검 — 충격적 발견

단순 교차표
                  IsCanceled = 0    IsCanceled = 1
NRDeposit = 0     63,316 (73%)      23,042 (27%)
NRDeposit = 1     55 (5%)           982 (95%)

NRD 없는 예약: 27% 취소 NRD 있는 예약: 95% 취소

상대 위험 (RR):

\[ RR = \frac{0.95}{0.27} \approx 3.5 \]

오즈 비 (OR):

\[ OR = \frac{0.95 / 0.05}{0.27 / 0.73} \approx 51 \]

NRD 가 있을 때 취소 odds 가 51 배 ?

직관 — 직관에 어긋나면 confounder 의심

상식:

“환불 안 해주는 보증금을 받으면, 사람들은 더 안 취소할 것이다 (못 환불받으니까).”

데이터:

“환불 불가 보증금이 있으면, 사람들이 95% 취소한다.”

두 진술이 충돌. 가능한 설명:

  1. Reverse causality: 취소가 보증금을 일으킨다? — 시점상 불가능 (보증금이 취소 전에 결정됨)
  2. Confounding: 보증금과 취소 양쪽에 영향을 주는 공통 원인이 있다.
  3. Selection bias: 분석 표본 자체가 편향됨? — 점검 필요

가장 가능성 높은 설명: Confounding.

→ 호텔이 위험을 평가한 후 “이 예약은 취소 가능성 높음” → NRD 부과 → 그 예약은 결국 취소됨.

위험 (a priori cancellation risk) 이 양쪽의 공통 원인.

2.4 Confounder 가설

CD 갱신
[A priori cancellation risk]
       ↓                ↓
   NRDeposit ──→ IsCanceled

A priori cancellation risk 는 미관측 변수. 호텔의 위험 평가 모델 (또는 직원의 직감) 에 들어 있는 정보.

이 단순한 갱신이 분석의 출발점을 완전히 바꾼다.

기존 질문: “NRD → Cancel 효과는?”

수정된 질문: “Risk 를 통제한 후 NRD → Cancel 효과는?”

후자가 진정한 인과 질문. 전자는 confounded 결과만 보여줌.

직관 — DAG 의 협업적 가치

이 갱신된 DAG (Risk → NRD, Risk → Cancel) 를 동료에게 보여주면:

“맞아. 우리는 휴가철 예약·해외 단체에 NRD 를 강제해. 그런 예약이 자주 취소되지.”

“주말 예약·신용 등급 낮은 카드도 NRD 부과해.”

“최근 가격 인상 때문에 high-end 예약자들이 NRD 회피.”

→ 동료마다 다른 risk 측면을 알려줌. DAG 가 공통 언어 역할.

DAG 없이 단순 회귀만 돌리면 이런 정보가 분석으로 들어오지 않음.

2.5 이상적 답 — RCT

진정한 답을 주는 실험

위 confounding 문제를 가장 깔끔히 해결하는 방법: RCT.

무작위 배정 (호텔이 위험 평가 무시)
         ↓
   ┌─ Group A ─→ NRD 부과 → 취소율 측정
   └─ Group B ─→ NRD 없음 → 취소율 측정
         ↓
   두 그룹의 취소율 차이 = NRD 의 진짜 인과 효과

문제:

  • 호텔이 무작위로 NRD 적용을 거부할 수 있음 (위험 관리 정책상)
  • 무작위 NRD 가 비즈니스 손실 (위험 예약을 그냥 받으면 취소되어 매출 손실)
  • 윤리적 문제 (고객에게 임의로 다른 정책 적용)

RCT 가 어려우면? 관찰 데이터 + 다중 confounder 통제 로 차선책.

이게 Buisson Ch.4 의 나머지 절차.

3 후보 변수 brainstorm — 6 카테고리

3.1 데이터부터 보지 않는 이유

“있는 데이터부터” 의 함정

자연스러운 직감: “회사 DB 열어보자. 어떤 컬럼 있는지 보고 시작하자.”

Buisson 의 비유 (재방문):

“취객이 집 열쇠를 찾을 때, 잃어버린 곳이 아니라 가로등 아래에서 찾는다.”

문제점:

  1. WYSIATI 편향 (Kahneman): 보이는 게 전부라고 생각. 미관측 중요 변수 놓침.
  2. 데이터 정의 액면 수용: 컬럼 이름·정의를 그대로 받아들여, 행동을 정확히 측정하는지 의심 안 함.
  3. 카테고리 편향: 데이터의 분류 (MarketSegment) 가 비즈니스 관점일 뿐, 행동 관점이 아닐 수 있음.

대신 권장: 6 카테고리에서 후보 brainstorm 후, 그 다음에 데이터 점검.

이 순서가 데이터 의존 편향을 방지.

3.2 6 카테고리 frame

변수 brainstorm 프레임
NRDeposit ──→ IsCanceled
    ↑              ↑
    │              │
    ├── 1. Past Actions
    ├── 2. Intentions
    ├── 3. Cognition & Emotions
    ├── 4. Personal Characteristics
    ├── 5. Business Behaviors
    └── 6. Time Trends

각 카테고리는 E-BUI2-1 인간 행동 5 구성요소 에 도입. 시간 추세는 추가.

분석가의 절차: 각 카테고리에 대해

  1. 이 카테고리에서 NRD 와 Cancel 양쪽에 영향을 줄 만한 변수는 무엇인가?
  2. 영향이 있다고 직관적으로 판단되면 CD 에 추가
  3. 데이터 존재 여부와 무관하게 추가 (미관측이어도 그림)

3.3 카테고리 1: Past Actions

과거 행동의 역할

질문: “고객의 과거 행동 중 NRD 부과 또는 취소 결정에 영향을 주는 것은?”

후보:

  • PreviousCancellation: 과거 취소 이력
  • IsRepeatedGuest: 재방문 여부
  • PreviousBookingsNotCanceled: 과거 정상 완료 예약 수
  • PreviousLoyaltyTierProgress: 로열티 등급 진행
직관 — 과거 행동의 두 인과 경로

PreviousCancellation 의 영향:

  1. NRD 결정: 호텔이 “이 사람은 과거 취소했음 → NRD 강제” — 인과 화살표 PrevCancel → NRD
  2. 취소 의사: “과거 취소한 사람은 또 취소할 가능성” — 인과 화살표 PrevCancel → Cancel

→ PrevCancel 이 confounder. 양쪽으로 화살표.

PreviousCancellation
       ↓        ↓
   NRDeposit ──→ Cancel

비즈니스 의미: 과거 취소를 통제하지 않으면, NRD 의 효과가 PrevCancel 의 효과와 섞임.

직관 — 행동 변수의 일반 원칙

“분석 대상이 행동이면, 과거 행동이 좋은 예측 변수다.”

이유:

  • 습관 (habit): 한 번 행동한 사람이 또 행동할 가능성 ↑
  • 특성의 proxy: 미관측 personal characteristics 의 결과로서 과거 행동이 그 특성을 부분 노출
  • 자기 강화: 과거 행동이 미래 환경 (호텔의 정책 적용) 을 만듦

→ 과거 행동을 항상 변수로 고려. 데이터에 있으면 회귀 포함, 없으면 미관측 노드로 그려둠.

3.4 카테고리 2: Intentions

의도의 역할

질문: “고객의 의도 중 NRD 또는 Cancel 결정에 영향을 주는 것은?”

후보:

  • TripReason (여행 사유): 휴가 / 비즈니스 / 가족 행사 / 의료
  • CancellationReason (취소 사유): 일정 변경 / 가격 변동 / 비교 후 다른 호텔 선택

데이터에 명시적으로 없음. 그러나 인터뷰·설문으로 측정 가능.

직관 — TripReason 의 양면 효과
[TripReason] (미관측)
       ↓        ↓
   NRDeposit  IsCanceled

TripReason 이 NRD 양쪽으로 영향을 주는 이유:

  • 휴가 여행:
    • NRD ↑: 호텔이 성수기·휴가철 예약에 NRD 강제
    • Cancel ↑: 날씨, 일정 변경, 가족 사정으로 취소 가능성
  • 비즈니스 여행:
    • NRD ↓: 회사 카드, 표준 계약, NRD 면제
    • Cancel ↓: 회사 일정 fixed, 변경 어려움

→ TripReason 이 강한 confounder. 데이터에 없어도 CD 에 표기. 회귀에 직접 못 넣지만, 다른 proxy (예: BookingChannel — 회사 카드 vs 개인) 로 부분 통제 가능.

직관 — CancellationReason — 다른 역할
NRD ──→ Cancel
         ↑
    [CancellationReason]
         (미관측)

CancellationReason 은 IsCanceled 의 직접 원인이지만 NRD 의 원인 아님.

이유: 취소 사유는 예약 시점에는 알려지지 않음. 호텔이 “취소 사유” 를 미리 알고 NRD 결정 안 함.

→ CancellationReason 은 confounder 가 아닌 직접 원인 (mediator 도 아님). NRD 효과 추정에 영향 없음 — 회귀에 포함 안 해도 됨.

이 구분이 분석가의 작업을 줄임. 모든 변수를 회귀에 넣을 필요 없음.

3.5 카테고리 3: Cognition & Emotions

인지·감정의 역할

질문: “고객의 인지·감정 상태 중 결정에 영향을 주는 것은?”

분석가의 도구: 의사결정 시점 분석.

시점 1: 예약 시
  - 약관 이해도
  - 가격 인지
  - 호텔 평판 인지
  - 보증금에 대한 거부감

시점 2: 잠재적 취소 시
  - Sunk Cost 효과 ("이미 낸 돈이니 가서 묵자")
  - 후회 회피 ("취소하면 손해")
  - 다른 옵션 발견 (저렴한 호텔)
  - 일정 변경 충격
직관 — 약관 이해도의 양면 효과

UnderstandsNRD (약관 이해 여부) 미관측 변수:

  • 이해 못 함 + NRD 있음 → 예약 후 일정 변경 시 그냥 취소 (보증금이 sunk 라는 인식 부족)
  • 이해함 + NRD 있음 → 일정 변경 시 어떻게든 가서 묵음 (보증금 손실 회피)

→ 약관 이해도가 NRD 의 효과를 modify (effect modification).

비즈니스 함의: 약관 명료화 (큰 글씨, 두 번 확인) 가 취소율을 줄일 수 있음.

CD:

[UnderstandsNRD]
       ↓
NRD ──→ Cancel

(Effect modifier 표기 방식은 Ch.5 또는 Ch.11 에서 자세히)

직관 — Sunk Cost 효과

TreatsNRDasSunkCost 미관측 변수.

행동 경제학 발견:

  • 어떤 사람은 sunk cost 를 강하게 회피 (“이미 낸 돈이니 어떻게든 가야”)
  • 어떤 사람은 sunk cost 를 무시 (“못 받을 돈이니 신경 안 써”)

NRD 가 있을 때 취소율은 이 인지 패턴에 의존.

[TreatsNRDasSunkCost]
       ↓
NRD ──→ Cancel

이 변수도 미관측. 그러나 CD 에 표기하면 분석의 한계가 명확해짐.

3.6 카테고리 4: Personal Characteristics

인구통계의 역할

질문: “고객의 인구통계 특성 중 결정에 영향을 주는 것은?”

후보:

  • Age: 데이터 없음 (호텔 데이터셋의 한계)
  • Gender: 데이터 없음
  • Country: 있음
  • Income / SocialClass: 직접 없음, ADR (객실료) 로 proxy 가능
Country, [Age], [Gender], [Income]
       ↓                          ↓
   NRDeposit  ──→  IsCanceled
직관 — Country 의 proxy 역할

Country 는 다음을 부분적으로 대표:

  • 결제 문화 (선불·후불 선호)
  • 여행 스타일 (단체·개인)
  • 신용 카드 사용 패턴
  • 시간대 (예약·취소 timing)
  • 호텔 정책 친숙도

→ Country 자체가 인과 변수가 아니라, 미관측 personal characteristics 의 proxy.

회귀에 Country 를 dummy 변수로 포함하면, 미관측 변수의 일부가 통제됨. 완벽하지 않지만 차선.

3.7 카테고리 5: Business Behaviors

비즈니스 행동의 역할

질문: “고객이 비즈니스 시스템과 어떻게 상호작용하는가?”

후보:

  • CustomerType: Transient, Group, Contract, Transient-Party
  • MarketSegment: Direct, Online TA, Offline TA, Group, Other
  • DistributionChannel: Direct, TA/TO, Corporate, Other

→ 세 변수가 강하게 상관 (Cramer’s V > 0.5). 다중공선성 위험.

직관 — Business 변수의 비즈니스 lens vs 행동 lens

“MarketSegment = Online TA” 는 비즈니스 입장에서 분류 (호텔이 어느 채널에서 예약 받았는가).

행동 입장에서는 다른 분류가 더 의미 있을 수 있음:

  • 개인 vs 단체 (CustomerType + Children)
  • 자발적 vs 강제 (회사 출장 vs 개인 휴가)
  • 즉흥 vs 계획 (예약 시점 vs 도착 시점 차이)

분석가의 선택지:

  1. 기존 비즈니스 분류 그대로 사용 → 빠름, 그러나 행동 lens 결여
  2. 새 변수 합성 (예: “Corporate + Children = 1 / Other = 0”) → 정밀, 시간 소요

Buisson 의 권장: 후자, 단 변수가 너무 많아지지 않도록 선별.

3.9 종합 — 후보 변수 CD

1차 후보 CD
[TripReason]      [Country]       [UnderstandsNRD]    Quarter, Year
       ↓               ↓                ↓                  ↓
   ┌────────────────────────────────────────────────────────┐
   │                                                          │
   │   PreviousCancellation                                   │
   │   IsRepeatedGuest                                        │
   │   CustomerType                                           │
   │   MarketSegment       ──→ NRDeposit ──→ IsCanceled       │
   │   DistributionChannel                  ↗                 │
   │   ADR                                                    │
   │                                                          │
   │   [TreatsNRDasSunkCost]  ──→ Cancel (only)               │
   │   [CancellationReason]   ──→ Cancel (only)               │
   │                                                          │
   └──────────────────────────────────────────────────────────┘

(괄호 [ ] 는 미관측)

이 CD 가 단계 1 의 산출물.

4 응용 — 다른 비즈니스 문제로 일반화

4.1 이커머스 — 추천 효과

분석 질문

“맞춤 추천이 구매 전환을 높이는가?”

Starter:

RecommendationShown ──→ Purchase

6 카테고리 brainstorm:

카테고리 후보 미관측?
Past Actions 과거 구매 빈도, 마지막 구매 후 시간 있음
Intentions 검색 의도 (browsing vs 구매) 미관측
Cognition 가격 비교 인지, 광고 학습 미관측
Personal 인구통계, 카테고리 선호 부분
Business 디바이스, 시간대, 페이지, 경로 있음
Time Trends 계절 (Black Friday 등) 있음

→ 추천 알고리즘이 구매 의도 높은 사용자에게 추천을 더 보여줌 → confounder.

4.2 SaaS — Onboarding 효과

분석 질문

“Onboarding 튜토리얼이 retention 을 높이는가?”

Starter:

TutorialCompleted ──→ Retention(30d)

6 카테고리:

카테고리 후보
Past Actions 다른 SaaS 사용 경험
Intentions 사용 목적 (단기 vs 장기)
Cognition 기술 학습 동기
Personal 직무, 회사 규모
Business 가입 채널 (광고·검색·추천)
Time Trends 가입 코호트 (월별 변화)

→ 사용 목적이 강한 사용자가 (1) 튜토리얼 완료 ↑, (2) Retention ↑ → confounder.

5 코드 예시 — Python 으로 1 차 점검

5.1 단순 교차표와 OR

import numpy as np
import pandas as pd
from scipy.stats import chi2_contingency

# 가상 호텔 데이터 생성
np.random.seed(42)
n = 87000

# 미관측 trip risk (TripReason 의 proxy)
trip_risk = np.random.beta(2, 5, n)  # 0~1 범위

# NRD 결정 (위험 높으면 NRD)
nrd_prob = trip_risk * 0.3 + 0.01
nrd = (np.random.uniform(0, 1, n) < nrd_prob).astype(int)

# IsCanceled 결정 (위험 높으면 취소)
cancel_prob = trip_risk * 0.7 + 0.1
cancel = (np.random.uniform(0, 1, n) < cancel_prob).astype(int)

df = pd.DataFrame({
    "NRDeposit": nrd,
    "IsCanceled": cancel,
    "trip_risk": trip_risk,
})

# 단순 교차표
crosstab = pd.crosstab(df["NRDeposit"], df["IsCanceled"])
print("=== 단순 교차표 ===")
print(crosstab)

# 비율
crosstab_pct = pd.crosstab(df["NRDeposit"], df["IsCanceled"], normalize="index")
print("\n=== 행 비율 ===")
print(crosstab_pct)

# Odds Ratio
a, b = crosstab.values[0]
c, d = crosstab.values[1]
or_value = (d * a) / (b * c)
print(f"\nOR(NRD vs no-NRD): {or_value:.2f}")
직관 — OR 해석

예상 결과:

  • NRD = 0: ~30% 취소
  • NRD = 1: ~80% 취소
  • OR ≈ 9 (Buisson 의 실제 데이터에서는 ~51)

이 OR 이 진짜 인과 효과 (NRD 가 취소를 ~9배 증가시킴) 일까?

답: 아니다. trip_risk 가 confounder 로 양쪽에 영향을 줘서 가짜 양의 상관 발생.

→ 다음 단계에서 trip_risk 를 통제하는 회귀 적합.

5.2 단순 vs Confounder 통제 회귀

import statsmodels.api as sm

# 단순 회귀
X1 = sm.add_constant(df["NRDeposit"])
m1 = sm.Logit(df["IsCanceled"], X1).fit(disp=False)
print(f"=== 단순 회귀: IsCanceled ~ NRD ===")
print(f"  beta = {m1.params['NRDeposit']:.3f}")
print(f"  OR = {np.exp(m1.params['NRDeposit']):.2f}")

# Confounder 통제
X2 = sm.add_constant(df[["NRDeposit", "trip_risk"]])
m2 = sm.Logit(df["IsCanceled"], X2).fit(disp=False)
print(f"\n=== Confounder 통제: IsCanceled ~ NRD + TripRisk ===")
print(f"  beta_NRD = {m2.params['NRDeposit']:.3f}")
print(f"  OR_NRD = {np.exp(m2.params['NRDeposit']):.2f}")
print(f"  beta_risk = {m2.params['trip_risk']:.3f}")
직관 — Confounder 통제의 효과

예상 결과:

  • 단순 회귀: OR ≈ 9
  • Confounder 통제: OR ≈ 1 (또는 작은 양수)

trip_risk 가 회귀에 포함되면 NRD 의 OR 이 1 가까이 떨어짐 — 진짜 인과 효과 ~ 0 에 가까움.

이게 confounder 통제의 위력. 그러나 현실에서는 trip_risk 가 미관측. 우리가 가지고 있는 변수 (PrevCancel, Country, MarketSegment 등) 로 부분 통제만 가능.

→ 잔여 confounding 이 항상 남음. 결과 해석 시 명시.

5.3 변수 brainstorm 자동화

def brainstorm_candidates(treatment, outcome, df):
    """6 카테고리에서 후보 변수 자동 식별 (휴리스틱)."""
    candidates = {
        "Past Actions": [],
        "Intentions": [],
        "Cognition": [],
        "Personal": [],
        "Business": [],
        "Time Trends": [],
    }

    keywords = {
        "Past Actions": ["previous", "prior", "history", "past", "repeated"],
        "Intentions": ["reason", "purpose", "goal"],
        "Cognition": ["awareness", "knowledge", "intent"],
        "Personal": ["age", "gender", "country", "income"],
        "Business": ["channel", "segment", "type", "category"],
        "Time Trends": ["year", "quarter", "month", "season", "date"],
    }

    for col in df.columns:
        if col in [treatment, outcome]:
            continue
        col_lower = col.lower()
        for cat, kws in keywords.items():
            if any(kw in col_lower for kw in kws):
                candidates[cat].append(col)
                break

    return candidates


# 예시 사용
print("\n=== 후보 변수 brainstorm ===")
candidates = brainstorm_candidates("NRDeposit", "IsCanceled", df)
for cat, vars_ in candidates.items():
    print(f"  {cat}: {vars_ if vars_ else '없음 (직관으로 보강)'}")
직관 — 자동화의 한계

이 도구는 변수 이름 으로 카테고리를 추측. 실제 분석에서는 부족.

이유:

  • 변수 이름이 의미를 정확히 반영 안 함 (예: seg_type 이 무엇 의미?)
  • 미관측 변수는 데이터에 없으므로 자동으로 식별 안 됨
  • 카테고리 분류가 도메인 의존적

→ 자동화는 시작점 일 뿐. 분석가의 도메인 직관으로 보강 필수.

6 관련 주제

6.1 Ch.4 의 형제 글

6.2 이전 챕터

6.3 후속 챕터

6.5 카테고리 진입점

Subscribe

Enjoy this blog? Get notified of new posts by email: