- **데이터 마트(Data Mart)**는 데이터 웨어하우스에서 특정 업무·부서·주제 영역에 맞게 잘라낸 부분집합(subset)
- 분석 목적별로 미리 가공·집계해 둔 읽기 전용(read-only) 테이블 묶음
- 매번 복잡한 쿼리를 새로 짜는 대신, 대시보드가 그냥 바라보면 되는 “1개의 정제된 테이블”을 제공하는 계층
해당 개념이 필요한 이유
- 쿼리 비용 제거: 운영 DB에 분석 쿼리를 직접 날리면 느리고(중첩 오브젝트 구조라 120초+), 운영 트래픽에도 부담을 준다 → 이는 OLTP vs OLAP 문제의 전형
- 숫자 신뢰성: “전환율 5%다 / 아니다 3%다” 같은 핑퐁은, 매번 쿼리를 다르게 짜기 때문에 생긴다. 집계 로직을 테이블 1개로 고정하면 모두가 같은 정의의 숫자를 본다
- 분석가 진입장벽 제거: 복잡한 JOIN/쿼리를 몰라도, 잘 가공된 테이블 1개만 대시보드로 보면 된다
AS-IS — 운영 DB에 직접 분석 쿼리
sequenceDiagram autonumber participant Analyst as 분석가 participant Mongo as 운영 MongoDB participant Stakeholder as 실무자 Analyst->>Mongo: 중첩 오브젝트 구조에 복잡한 쿼리 Mongo-->>Analyst: 120초+ 후 응답 Analyst->>Stakeholder: "A 기능으로 전환율 5% 상승" Stakeholder->>Analyst: "3% 아니에요?" (정의가 매번 다름) Analyst->>Mongo: 쿼리 다시 작성 (핑퐁 반복)
TO-BE — 데이터 마트의 1개 테이블을 대시보드로
sequenceDiagram autonumber participant Airflow as Airflow(스케줄러) participant Mart as 데이터 마트 (1 테이블) participant Dashboard as Redash 대시보드 participant Stakeholder as 실무자 Airflow->>Mart: 주기적으로 집계·가공해 테이블 갱신 Stakeholder->>Dashboard: 대시보드 열기 Dashboard->>Mart: 정제된 테이블 1개 조회 (빠름) Mart-->>Dashboard: 고정된 정의의 숫자 반환 Note over Dashboard,Stakeholder: 쿼리 핑퐁 없이 같은 숫자를 공유
운영 DB → 데이터 웨어하우스 → 데이터 마트, 3단 구조
| 계층 | 역할 | 성격 |
|---|---|---|
| 운영 DB (OLTP) | 서비스가 실시간으로 읽고 쓰는 원본 (예: 운영 MongoDB) | 트랜잭션 처리, 정규화 |
| 데이터 웨어하우스 (DW) | 여러 소스를 통합해 모아둔 분석용 저장소 (예: Amazon Redshift) | 전사 통합, 이력 보존 |
| 데이터 마트 | DW에서 특정 목적만 떼어내 가공한 테이블 | 부서/주제별, 읽기 전용, 비정규화 |
- 운영 DB는 “쓰기”에 최적화돼 있어 분석 쿼리에 불리하다 → 분석은 별도 계층으로 분리한다 (OLTP vs OLAP)
- 데이터 마트는 보통 비정규화(denormalization) 와 스타 스키마(star schema) 로 조회 속도를 우선한다
실무: 마트 테이블은 어떻게 생기나
핵심 아이디어는 “질문을 미리 계산해서 1행씩 박아둔다” 이다. 분석가가 던질 질문(예: “기능별·일별 전환율”)을 컬럼으로 고정한다.
① 원본(운영 DB) — 분석하기 나쁜 모양: 이벤트가 한 줄씩 쌓이고, 중첩 구조라 매번 풀어야 한다.
events
| user_id | event_type | feature | occurred_at |
|---------|------------|---------|----------------------|
| u_001 | view | A | 2026-06-05 10:21:03 |
| u_001 | signup | A | 2026-06-05 10:24:10 |
| u_002 | view | A | 2026-06-05 11:02:55 |
② ETL 가공(Airflow가 매일 실행) — 집계 SQL: 질문의 정의를 SQL 한 곳에 고정한다.
-- mart_daily_conversion 을 매일 채우는 집계 (정의를 여기서 '한 번만' 박는다)
INSERT INTO mart_daily_conversion (dt, feature, viewers, signups, conversion_rate)
SELECT
DATE(occurred_at) AS dt,
feature,
COUNT(DISTINCT CASE WHEN event_type = 'view' THEN user_id END) AS viewers,
COUNT(DISTINCT CASE WHEN event_type = 'signup' THEN user_id END) AS signups,
ROUND(
COUNT(DISTINCT CASE WHEN event_type = 'signup' THEN user_id END) * 1.0
/ NULLIF(COUNT(DISTINCT CASE WHEN event_type = 'view' THEN user_id END), 0)
, 4) AS conversion_rate
FROM events
GROUP BY DATE(occurred_at), feature;③ 마트 테이블 — 대시보드가 바라보는 “1개의 테이블”: 이미 답이 계산돼 있다.
mart_daily_conversion
| dt | feature | viewers | signups | conversion_rate |
|------------|---------|---------|---------|-----------------|
| 2026-06-05 | A | 1820 | 91 | 0.0500 |
| 2026-06-05 | B | 1340 | 47 | 0.0351 |
④ 소비(Redash) — 더 이상 JOIN/집계가 없다: 그냥 읽기만 한다. 전환율 정의를 두고 핑퐁할 일이 없다.
SELECT dt, feature, conversion_rate
FROM mart_daily_conversion
WHERE dt >= CURRENT_DATE - INTERVAL '30 day'
ORDER BY dt;포인트: 전환율 =
signups / viewers라는 정의가 ②의 SQL 한 곳에만 존재한다. “5%냐 3%냐” 논쟁은 정의가 흩어져서 생기므로, 마트가 그 정의를 단일 출처(single source)로 고정한다.
데이터 마트 종류 2가지
- 종속형(Dependent): 이미 만들어진 데이터 웨어하우스에서 부분집합을 떼어내 구성 — 일관성·거버넌스에 유리
- 독립형(Independent): 운영/외부 시스템에서 직접 가져와 구성 — 빠르게 만들 수 있지만 전사 정의와 어긋날 위험
실제 파이프라인: 공공데이터 → Airflow → Redshift → Redash
flowchart LR A["공공데이터<br/>(외부 소스)"] --> B["Airflow<br/>(수집·가공 스케줄링)"] B --> C["Amazon Redshift<br/>(분석 DW / 데이터 마트)"] C --> D["Redash<br/>(대시보드)"]
| 도구 | 3단 구조에서의 위치 | 하는 일 |
|---|---|---|
| 공공데이터 | 소스 | 외부에서 가져오는 원천 데이터 |
| Airflow | ETL 파이프라인 | 정해진 주기로 추출·가공·적재(ETL) 자동화 |
| Amazon Redshift | DW / 데이터 마트 | 분석 전용 컬럼형 DB, 목적별 테이블 저장 |
| Redash | 소비(대시보드) | 마트 테이블을 시각화, 실무자가 조회 |
- Airflow의 역할과 ETL 단계는 Airflow 노트에서 더 자세히 다룬다