[이제와서 시작하는 Metabase 마스터하기 #8] 데이터 모델링 - Models, Metrics, Segments
학습 목표
이 포스트를 마치면 다음을 할 수 있습니다:
- Semantic Layer의 개념과 중요성 이해
- Models로 복잡한 데이터를 단순화
- Metrics로 일관된 비즈니스 지표 정의
- Segments로 자주 사용하는 필터 재사용
- 데이터 모델링 Best Practices 적용
- 조직 전체의 데이터 일관성 확보
Semantic Layer란?
Semantic Layer(의미론적 계층)는 원본 데이터와 비즈니스 사용자 사이의 추상화 계층입니다.
graph TB
A[Business Users] --> B[Semantic Layer]
B --> C[Models]
B --> D[Metrics]
B --> E[Segments]
C --> F[Raw Tables]
D --> F
E --> F
style B fill:#e1f5ff
style C fill:#fff4e1
style D fill:#e8f5e9
style E fill:#fce4ec
왜 필요한가?
문제점 (Semantic Layer 없이):
1
2
3
4
5
6
7
Analyst A:
매출 = SUM(total) WHERE status = 'completed'
Analyst B:
매출 = SUM(subtotal - discount) WHERE payment_status = 'paid'
→ 같은 "매출"이지만 다른 숫자!
해결책 (Semantic Layer 사용):
1
2
3
4
5
중앙에서 정의:
Revenue Metric = SUM(total) WHERE status = 'completed'
모든 분석가가 동일한 정의 사용
→ 일관된 분석 결과
Metabase의 Semantic Layer
graph LR
A[Raw Data] --> B[Models]
B --> C[Metrics]
B --> D[Segments]
C --> E[Questions]
D --> E
E --> F[Dashboards]
3가지 구성 요소:
- Models: 정제된 데이터 뷰
- Metrics: 비즈니스 지표 정의
- Segments: 재사용 가능한 필터
Models (모델)
개념
Model은 복잡한 쿼리를 단순한 테이블처럼 사용할 수 있게 하는 저장된 Question입니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
-- Raw tables (복잡함)
SELECT
o.id,
o.created_at,
o.total,
c.name as customer_name,
c.state,
p.name as product_name
FROM orders o
JOIN customers c ON o.customer_id = c.id
JOIN order_items oi ON o.id = oi.order_id
JOIN products p ON oi.product_id = p.id
-- Model: "Order Details" (간단함)
SELECT * FROM order_details
Model 생성하기
방법 1: Question을 Model로 변환
1
2
3
4
5
1. Question 생성 (SQL 또는 GUI)
2. Save 후
3. ... menu > "Turn into a model"
4. Collection 선택
5. Create
방법 2: 직접 Model 생성
1
2
3
1. New > Model
2. SQL 작성
3. Save
Model 예제
Model 1: Clean Orders
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
-- Purpose: 완료된 주문만, 필요한 필드만
CREATE MODEL clean_orders AS
SELECT
o.id as order_id,
o.created_at as order_date,
o.total as order_total,
o.subtotal,
o.tax,
o.discount,
c.id as customer_id,
c.name as customer_name,
c.email as customer_email,
c.state as customer_state,
c.created_at as customer_signup_date
FROM orders o
JOIN customers c ON o.customer_id = c.id
WHERE o.status = 'completed'
AND o.created_at >= '2024-01-01'
사용:
1
2
3
New Question > Data: "Clean Orders" model
이제 복잡한 조인 없이 바로 사용 가능
Model 2: Product Performance
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
CREATE MODEL product_performance AS
SELECT
p.id as product_id,
p.name as product_name,
p.category,
p.price as current_price,
COUNT(DISTINCT o.id) as order_count,
SUM(oi.quantity) as units_sold,
SUM(oi.quantity * oi.price) as total_revenue,
AVG(r.rating) as avg_rating,
COUNT(DISTINCT r.id) as review_count
FROM products p
LEFT JOIN order_items oi ON p.id = oi.product_id
LEFT JOIN orders o ON oi.order_id = o.id AND o.status = 'completed'
LEFT JOIN reviews r ON p.id = r.product_id
WHERE p.is_active = true
GROUP BY p.id, p.name, p.category, p.price
Model 3: Customer 360
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
CREATE MODEL customer_360 AS
SELECT
c.id as customer_id,
c.name,
c.email,
c.state,
c.created_at as signup_date,
-- Order metrics
COUNT(DISTINCT o.id) as total_orders,
SUM(o.total) as lifetime_value,
AVG(o.total) as avg_order_value,
MAX(o.created_at) as last_order_date,
MIN(o.created_at) as first_order_date,
DATEDIFF('day', MAX(o.created_at), CURRENT_DATE) as days_since_last_order,
-- Behavioral
SUM(CASE WHEN o.created_at >= CURRENT_DATE - 90 THEN 1 ELSE 0 END) as orders_last_90d,
-- Segmentation
CASE
WHEN SUM(o.total) >= 1000 THEN 'VIP'
WHEN SUM(o.total) >= 500 THEN 'Regular'
ELSE 'Casual'
END as customer_segment
FROM customers c
LEFT JOIN orders o ON c.id = o.customer_id AND o.status = 'completed'
GROUP BY c.id, c.name, c.email, c.state, c.created_at
Model 메타데이터 설정
Description:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Model: Customer 360
Description:
통합된 고객 프로필 with 주문 이력 및 행동 지표
Update frequency: Daily at 2 AM
Owner: Analytics Team
Use cases:
- Customer segmentation
- Lifetime value analysis
- Churn prediction
Important notes:
- lifetime_value는 completed 주문만 포함
- customer_segment는 전체 기간 기준
Column descriptions:
1
2
3
4
1. customer_id: 고유 고객 ID
2. lifetime_value: 총 구매액 (완료된 주문만)
3. days_since_last_order: 마지막 주문 이후 일수 (재구매 분석용)
4. customer_segment: VIP(>$1000) / Regular($500-1000) / Casual(<$500)
Model 관리
Caching:
1
2
3
Model settings > Caching
- Cache TTL: 24 hours (매일 새벽 갱신)
- Refresh schedule: Daily at 2:00 AM
Permissions:
1
2
3
4
Model settings > Permissions
- View: All users
- Edit: Analytics team only
- 이유: 비즈니스 로직의 일관성 유지
Metrics (메트릭)
개념
Metric은 비즈니스 지표의 표준 정의입니다.
1
2
3
4
5
예시:
- Monthly Recurring Revenue (MRR)
- Customer Acquisition Cost (CAC)
- Net Promoter Score (NPS)
- Conversion Rate
Metric 생성
1
2
3
4
1. Model 선택
2. "Add a metric" 클릭
3. 이름, 정의, 설명 작성
4. Save
Metric 예제
Metric 1: Total Revenue
1
2
3
4
5
6
7
Name: Total Revenue
Model: Clean Orders
Definition: Sum of order_total
Description:
완료된 주문의 총 매출액
Excludes: 취소, 환불, 보류 주문
Includes: 세금 포함 금액
Metric 2: Active Customers
1
2
3
4
5
6
Name: Active Customers (90-day)
Model: Customer 360
Definition: Count of distinct customer_id WHERE orders_last_90d > 0
Description:
지난 90일 내 1회 이상 구매한 고객 수
Use: 월간 활성 사용자 추적
Metric 3: Average Order Value (AOV)
1
2
3
4
5
6
7
Name: Average Order Value
Model: Clean Orders
Definition: Average of order_total
Description:
주문 건당 평균 금액
Calculation: Total Revenue / Number of Orders
Benchmark: Industry average $75
Metric 4: Customer Lifetime Value (LTV)
1
2
3
4
5
6
7
Name: Customer Lifetime Value
Model: Customer 360
Definition: Average of lifetime_value
Description:
고객 1명당 평균 총 구매액
Use: CAC와 비교하여 ROI 계산
Target: LTV:CAC ratio > 3:1
Metric 5: Conversion Rate
1
2
3
4
5
6
7
Name: Checkout Conversion Rate
Model: Funnel Events
Definition:
(Count of purchases / Count of checkout starts) * 100
Description:
체크아웃 시작 대비 구매 완료 비율
Optimization target: > 70%
Metric 사용하기
Question에서:
1
2
3
4
5
1. New Question
2. Data: Clean Orders
3. Summarize: "Total Revenue" (미리 정의된 Metric)
4. Group by: order_date (Month)
5. Visualization: Line chart
장점:
1
2
3
✅ 정의 일관성: 모두가 같은 계산식 사용
✅ 업데이트 간편: Metric 정의 변경 시 모든 Question 자동 반영
✅ 문서화: 계산 로직이 명시적
Metric Catalog
조직의 Metric 카탈로그 구축:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# Revenue Metrics
## Total Revenue
- **Definition**: Sum(order_total) WHERE status = 'completed'
- **Owner**: Finance Team
- **Update**: Real-time
- **Target**: $1M/month
## Net Revenue
- **Definition**: Total Revenue - Returns - Refunds
- **Owner**: Finance Team
- **Update**: Daily
- **Target**: 95% of Total Revenue
# Customer Metrics
## Active Customers
- **Definition**: Distinct customers with orders in last 90 days
- **Owner**: Growth Team
- **Update**: Daily
- **Target**: 10% MoM growth
## Customer Retention Rate
- **Definition**: (Customers this month who ordered last month) / Customers last month
- **Owner**: CRM Team
- **Update**: Monthly
- **Target**: > 80%
Segments (세그먼트)
개념
Segment는 자주 사용하는 필터 조합을 저장한 것입니다.
1
2
3
4
5
예시:
- VIP Customers (lifetime_value > $1000)
- Recent Orders (created_at >= CURRENT_DATE - 30)
- High-Value Products (price > $100)
- Churned Customers (days_since_last_order > 180)
Segment 생성
1
2
3
4
5
1. Model 선택
2. "Add a segment" 클릭
3. 필터 조건 설정
4. 이름 및 설명 작성
5. Save
Segment 예제
Segment 1: VIP Customers
1
2
3
4
5
6
7
8
9
10
11
Name: VIP Customers
Model: Customer 360
Filter:
customer_segment = 'VIP'
OR lifetime_value >= 1000
Description:
고가치 고객 세그먼트
Criteria: 총 구매액 $1,000 이상
Count: ~500 customers (5% of total)
Special treatment: 전용 할인, 우선 배송
Segment 2: At-Risk Customers
1
2
3
4
5
6
7
8
9
10
11
12
Name: At-Risk Customers
Model: Customer 360
Filter:
total_orders >= 3
AND days_since_last_order > 90
AND days_since_last_order <= 180
Description:
이탈 위험 고객
과거 활동: 3회 이상 구매 (loyal)
현재 상태: 90-180일 미구매
Action: 재참여 캠페인 대상
Segment 3: High-Value Orders
1
2
3
4
5
6
7
8
9
Name: High-Value Orders
Model: Clean Orders
Filter:
order_total >= 200
Description:
고액 주문 세그먼트
Threshold: $200 이상
Use: 특별 배송 추적, 감사 메시지 발송
Segment 4: New Customers (First 30 Days)
1
2
3
4
5
6
7
8
9
Name: New Customers
Model: Customer 360
Filter:
DATEDIFF('day', signup_date, CURRENT_DATE) <= 30
Description:
신규 가입 고객 (30일 이내)
Use: 온보딩 모니터링, 초기 경험 최적화
Target conversion: 첫 구매 전환율 > 30%
Segment 5: Mobile Shoppers
1
2
3
4
5
6
7
8
9
10
Name: Mobile Shoppers
Model: Clean Orders
Filter:
device_type = 'mobile'
OR device_type = 'tablet'
Description:
모바일 디바이스 주문
Use: 모바일 UX 최적화 분석
Trend: 전체 주문의 60% (증가 추세)
Segment 사용하기
Question에서:
1
2
3
4
5
6
7
1. New Question
2. Data: Customer 360
3. Segment: "VIP Customers" 선택 (자동으로 필터 적용됨)
4. Summarize: Count
5. Group by: state
→ VIP 고객의 지역별 분포
조합 사용:
1
2
3
1. Data: Clean Orders
2. Segment: "High-Value Orders" + "Mobile Shoppers"
3. → 모바일에서 발생한 고액 주문만 분석
데이터 모델링 Best Practices
1. 명명 규칙
Models:
1
2
3
4
5
6
7
8
9
✅ 좋은 이름:
- clean_orders (상태: clean, 대상: orders)
- customer_360 (컨셉: 360도 뷰, 대상: customer)
- product_performance (컨셉: 성과, 대상: product)
❌ 나쁜 이름:
- model1
- temp_query
- johns_analysis
Metrics:
1
2
3
4
5
6
7
8
9
✅ 좋은 이름:
- Total Revenue (명확한 비즈니스 용어)
- Customer Lifetime Value
- Monthly Active Users
❌ 나쁜 이름:
- sum_total (기술적 용어)
- metric_2
- revenue_v3
Segments:
1
2
3
4
5
6
7
8
9
✅ 좋은 이름:
- VIP Customers (명확한 기준)
- At-Risk Customers
- Recent Orders (Last 30 Days)
❌ 나쁜 이름:
- segment_a
- test_filter
- customers_1
2. 문서화 템플릿
Model Documentation:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# Model: Customer 360
## Purpose
통합된 고객 프로필 및 행동 지표
## Data Sources
- customers (primary)
- orders (aggregated)
- customer_events (behavioral)
## Update Schedule
Daily at 2:00 AM UTC
## Key Fields
- customer_id: Unique identifier
- lifetime_value: Total purchase amount (completed orders only)
- customer_segment: VIP / Regular / Casual
- days_since_last_order: Recency indicator
## Business Rules
- Only includes customers with verified email
- lifetime_value excludes refunds and returns
- customer_segment updates daily based on total spend
## Usage Examples
- Customer segmentation analysis
- LTV prediction models
- Churn risk scoring
## Owner
Analytics Team (analytics@company.com)
## Version History
- v1.0 (2025-01-01): Initial release
- v1.1 (2025-02-15): Added customer_segment field
- v1.2 (2025-03-01): Optimized for better performance
Metric Documentation:
1
2
3
4
5
6
7
# Metric: Monthly Recurring Revenue (MRR)
## Definition
```sql
SUM(subscription_amount)
WHERE subscription_status = 'active'
AND billing_period = 'monthly'
Business Logic
- Includes only active monthly subscriptions
- Excludes trial periods and annual plans (use ARR for those)
- Calculated at the end of each month
Targets
- Q1 2025: $100K
- Q2 2025: $150K
- Annual: $1.2M
Related Metrics
- Annual Recurring Revenue (ARR)
- Customer Lifetime Value (LTV)
- Churn Rate
Owner
Revenue Operations Team
Approved By
CFO, 2025-01-15
1
2
3
### 3. 폴더 구조
Models/ ├── Core/ │ ├── clean_orders │ ├── customer_360 │ └── product_catalog ├── Marketing/ │ ├── campaign_performance │ ├── attribution_model │ └── lead_scoring ├── Finance/ │ ├── revenue_recognition │ └── cost_analysis └── Experimental/ ├── ml_predictions └── test_models
Metrics/ ├── Revenue/ │ ├── Total Revenue │ ├── Net Revenue │ └── MRR ├── Customer/ │ ├── Active Customers │ ├── LTV │ └── CAC └── Product/ ├── Conversion Rate └── Average Order Value
1
2
3
4
5
### 4. 버전 관리
**Metric 변경 시:**
-
새 버전 생성: Old: “Total Revenue” New: “Total Revenue v2”
- 테스트 기간:
- 두 버전 병행 사용 (1-2주)
- 결과 비교 및 검증
-
공지: “Total Revenue 정의 변경 예정: 변경 사항: 환불 제외 로직 추가 적용일: 2025-04-01 영향: 약 3% 감소 예상 문의: analytics@company.com”
- 마이그레이션:
- 모든 Question 업데이트
- Old version deprecate
- 문서 업데이트
- Old version 삭제 (3개월 후) ```
5. 성능 최적화
Model 최적화:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
-- ❌ 느린 Model
CREATE MODEL slow_model AS
SELECT *
FROM orders o
LEFT JOIN customers c ON o.customer_id = c.id
LEFT JOIN products p ON o.product_id = p.id
-- 모든 컬럼, 모든 행
-- ✅ 빠른 Model
CREATE MODEL fast_model AS
SELECT
o.id,
o.created_at,
o.total,
c.name,
p.category
FROM orders o
JOIN customers c ON o.customer_id = c.id -- INNER JOIN (필요한 것만)
JOIN products p ON o.product_id = p.id
WHERE o.created_at >= '2024-01-01' -- 필터링
AND o.status = 'completed'
-- 필요한 컬럼만, 필요한 행만
캐싱 전략:
1
2
3
4
5
6
7
8
9
10
11
자주 사용하는 Model:
- Cache TTL: 1 hour
- Update: 매 시간
일일 리포트 Model:
- Cache TTL: 24 hours
- Update: Daily at 2 AM
실시간 Model:
- Cache TTL: 5 minutes
- Update: 실시간
6. 거버넌스
Approval 프로세스:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
1. 제안:
Analyst가 새 Metric 제안
2. 리뷰:
Analytics team 리뷰
- 정의 명확성
- 비즈니스 가치
- 기술적 타당성
3. 승인:
Stakeholder 승인 (Finance, Marketing 등)
4. 배포:
공식 Metric catalog에 추가
5. 교육:
팀 교육 및 문서화
정기 감사:
1
2
3
4
5
6
7
8
9
분기별:
- 사용되지 않는 Model/Metric 제거
- 중복 제거
- 성능 리뷰
연간:
- 비즈니스 목표 정렬 확인
- Metric 정의 업데이트
- 사용자 만족도 조사
실전 연습 문제
연습 1: Model 생성 (초급)
과제: 판매 분석을 위한 “Sales Summary” Model 생성
요구사항:
- Orders, Customers, Products 테이블 조인
- 완료된 주문만
- 2024년 이후 데이터만
해답 보기
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
CREATE MODEL sales_summary AS
SELECT
o.id as order_id,
o.created_at as order_date,
o.total as order_total,
c.id as customer_id,
c.name as customer_name,
c.state as customer_state,
p.id as product_id,
p.name as product_name,
p.category as product_category,
oi.quantity,
oi.price as unit_price,
oi.quantity * oi.price as line_total
FROM orders o
JOIN customers c ON o.customer_id = c.id
JOIN order_items oi ON o.id = oi.order_id
JOIN products p ON oi.product_id = p.id
WHERE o.status = 'completed'
AND o.created_at >= '2024-01-01'
-- Column descriptions:
-- order_total: 주문 총액 (세금 포함)
-- line_total: 상품 라인별 금액
-- quantity: 구매 수량
연습 2: Metrics 정의 (중급)
과제: 핵심 비즈니스 Metrics 정의
- Gross Merchandise Value (GMV)
- Average Items per Order
- Repeat Purchase Rate (30일 내 재구매 비율)
해답 보기
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
Metric 1: Gross Merchandise Value
Name: GMV
Model: Sales Summary
Definition: SUM(order_total)
Description:
총 거래액 (환불 전)
Use: 플랫폼 전체 규모 측정
Note: Net Revenue와 구분 (환불 제외는 Net Revenue)
Metric 2: Average Items per Order
Name: Avg Items per Order
Model: Sales Summary
Definition: AVG(quantity)
Description:
주문당 평균 상품 개수
Benchmark: 2.5 items
Optimization: Cross-sell, Bundle 제안
Metric 3: Repeat Purchase Rate
Model: Customer 360
Definition:
COUNT(DISTINCT customer_id WHERE orders_last_30d >= 2)
/ COUNT(DISTINCT customer_id WHERE orders_last_30d >= 1)
* 100
Description:
30일 내 2회 이상 구매한 고객 비율
Target: > 25%
Driver: Customer satisfaction, loyalty programs
연습 3: Segments 활용 (고급)
과제: 고객 라이프사이클 Segments 생성
- New (첫 구매 후 30일 이내)
- Active (30-90일 내 구매)
- At Risk (90-180일 미구매)
- Churned (180일 이상 미구매)
해답 보기
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
Segment 1: New Customers
Model: Customer 360
Filter:
DATEDIFF('day', first_order_date, CURRENT_DATE) <= 30
Description:
첫 구매 후 30일 이내
Action: 온보딩 캠페인, 첫 리뷰 유도
Segment 2: Active Customers
Model: Customer 360
Filter:
days_since_last_order <= 90
AND DATEDIFF('day', first_order_date, CURRENT_DATE) > 30
Description:
최근 90일 내 구매, 신규 아님
Action: 정기 프로모션, 추천 상품
Segment 3: At-Risk Customers
Model: Customer 360
Filter:
days_since_last_order > 90
AND days_since_last_order <= 180
AND total_orders >= 2
Description:
과거 구매 있으나 90-180일 미구매
Action: Win-back 캠페인, 특별 할인
Segment 4: Churned Customers
Model: Customer 360
Filter:
days_since_last_order > 180
Description:
180일 이상 미구매
Action: 대대적 재참여 캠페인 or 리스트 정리
-- Dashboard 활용:
각 세그먼트별:
- 고객 수
- 비율
- 평균 LTV
- 추세 (지난 분기 대비)
다음 단계
데이터 모델링을 마스터했습니다. 다음 포스트에서는:
- 자동화와 알림: Pulses, Alerts로 정기 리포트 자동화
- Subscriptions: 이메일, Slack으로 대시보드 전송
- Scheduled Exports: 정기 데이터 내보내기
요약
Semantic Layer 구성 요소
graph TD
A[Semantic Layer] --> B[Models]
A --> C[Metrics]
A --> D[Segments]
B --> B1[데이터 단순화]
B --> B2[조인 추상화]
C --> C1[지표 일관성]
C --> C2[비즈니스 정의]
D --> D1[필터 재사용]
D --> D2[세그먼트 분석]
체크리스트
Model 생성:
- 명확한 비즈니스 목적 정의
- 필요한 필드만 포함
- 필터로 데이터 범위 제한
- Column descriptions 작성
- Caching 설정
- 권한 설정
Metric 정의:
- 비즈니스 용어로 명명
- 계산 로직 문서화
- 목표치 설정
- Owner 지정
- 관련 Metrics 연결
- Stakeholder 승인
Segment 생성:
- 명확한 기준 정의
- 비즈니스 가치 검증
- 사용 사례 문서화
- 정기 리뷰 계획
다음 포스트에서는 이렇게 만든 분석을 자동화하고 팀과 공유하는 방법을 배웁니다!
📚 시리즈 전체 목차
🚀 기초편 (1-5화)
💪 활용편 (6-10화)
- 필터와 파라미터
- SQL 네이티브 쿼리
- [데이터 모델링] (현재 글)
- 자동화와 알림
- 권한과 보안