PaySim 이상 금융 거래 데이터를 기반으로, dbt를 활용해 FDS 분석 마트를 설계 및 구현했습니다. Data Analytics Engineer 관점에서 다음과 같은 내용을 고려하며 설계했습니다.
⚙️ Materialization 전략 — view / table / incremental / ephemeral 를 용도별로 선택
♻️ 재사용 SQL — Jinja 매크로·패키지로 DRY 원칙 적용, 공통 룰/해시/유틸 중앙화
🧬 Data Lineage — 소스→마트→대시보드까지 추적
📚 문서·카탈로그 — 모델/컬럼 정의와 오너십, 사용처 문서 및 UI화
✅ 데이터 품질 — 제네릭 테스트 + 싱귤러 테스트, 소스 신선도
데이터 출처
Raw 데이터 주요 컬럼(스키마)
step, type, amount, nameOrig, nameDest, oldbalanceOrg, newbalanceOrig, oldbalanceDest, newbalanceDest, isFraud, isFlaggedFraud
데모용 시드 파일
| 파일 | 범위/용도 |
|---|---|
seeds/raw_transactions_day1.csv |
step 0–23 |
seeds/raw_transactions_day2.csv |
step 24–47 |
seeds/rules.csv |
룰/임계값 외부화 |
추가되는 메타 컬럼
-
source_batch: 적재 배치 구분(day1/day2) -
seed_loaded_at: 시드 생성 시각(신선도·중복 방지에 활용)
- 위 그래프는
dbt docs generate후 확인한 결과로, seeds(raw) → staging → intermediate → marts → exposure(account_risk_dashboard)까지 전체 흐름을 나타냅니다. - 룰/시드(
rules.csv,raw_transactions_day*)가 upstream에 있고, core marts가 Metabase 대시보드 노출점과 연결되어 있음을 시각적으로 검증할 수 있습니다.
각 레이어의 역할 → 파일 → 핵심 포인트 순으로 정리했습니다.
| 파일 | 역할 | 핵심 포인트 |
|---|---|---|
models/staging/stg_tx.sql |
거래 정규화/파생 | tx_id, ts 생성, 금액 버킷/플래그, 중복 제거 |
models/staging/stg_accounts.sql |
계정 명부 | 발신/수신/양쪽 역할 분류, 기본 활동지표 |
models/staging/src.yml |
소스 선언 | source 정의, freshness 규칙, 기본 테스트(not_null 등) |
| 파일 | 역할 | 핵심 포인트 |
|---|---|---|
models/intermediate/int_tx_enriched.sql |
강화된 거래 데이터 | 잔액 일관성, 24h 롤링 카운트(윈도우), 리스크 스코어 |
models/intermediate/int_account_features.sql |
계정 특징량 | 유입/유출 건수/금액, 유니크 상대 수, 최신 리스크 |
models/intermediate/int_edge_daily.sql |
엣지 집계 | origin→dest 일별 건수/금액/신호 |
models/intermediate/schema.yml |
문서/테스트 | 인터미디어트 모델 설명 & 컬럼 테스트 |
| 파일 | 유형 | 역할/포인트 |
|---|---|---|
models/marts/core/dim_account.sql |
Dimension | 서로게이트 키, 계정 위험 상태/활동 집계 |
models/marts/core/dim_tx_type.sql |
Dimension | 거래 유형 코드표(비즈니스 그룹핑) |
models/marts/core/dim_date.sql |
Dimension | 달력 디멘전(활동 기간 커버) |
models/marts/core/fct_tx.sql |
Fact | 거래 팩트 + 리스크 점수/잔액 점검, 디멘전 조인 |
models/marts/core/fct_alerts.sql |
Fact | 룰 트리거 explode, 심각도 메타데이터 포함 |
models/marts/core/mart_account_risk_daily.sql |
Mart | 일별 계정 위험 집계(트렌드 모니터링) |
models/marts/core/schema.yml |
품질 | 관계/무결성 테스트(relationships 등) |
models/marts/exposures.yml |
노출점 | 대시보드/리포트 연결(라인리지 끝단) |
-
테이블 구조 및 컬럼 확인
-
Lineage 아이콘으로 seeds → staging → intermediate → marts → exposure 흐름 확인
-
모델/컬럼 페이지에서 description/owner/tags와 테스트 결과 확인
-
Exposure(
account_risk_dashboard) 노드로 대시보드 링크(설정 시) 이동
-
제네릭
-
dbt의 test 기능 활용해서 각 단계에서 데이터가 특정 조건 만족하는지 확인
-
not null, unique, relationships(무결성 검사), accept_values(미리 정의된 목록)
-
-
싱귤러
- 제네릭으로 검증하기 힘든 복잡한 비즈니스 로직을 검증하기 위한 SQL
-
소스 신선도
-
원본데이터가 최신 상태로 유지되고 있는지 감시하는 기능
-
yml 파일의 freshness 규칙 사용
-
특정 데이터가 몇시간 이상 업데이트 되지 않으면 경고 및 오류
-
macros/hashes.sqlsurrogate_key([...])— 여러 컬럼을 안전하게 결합해 해시 기반 서로게이트 키 생성generate_tx_id(...)— 거래 고유tx_id결정적 생성(리스트 인자 안전 처리)
macros/utils.sqlsafe_cast— 널/형 변환 오류를 예방하는 캐스팅bucket_amount— 금액 구간화(버킷팅) 유틸hours_to_timestamp—step(시간) → 타임스탬프 파생
macros/rules.sqlrules_risk_score—rules.csv임계값을 읽어 위험 점수 계산rules_trigger_list— 룰 트리거 문자열 생성(이후 explode용)- severity 가중치 — 룰 심각도에 따른 가중 합산
- 요구사항: Python,
dbt-core,dbt-duckdb - 프로필 설정:
fds_analytics_platform/profiles.yml를 참고해 로컬~/.dbt/profiles.yml구성
cd fds_analytics_platform
dbt deps
dbt seed --profiles-dir .
dbt build --profiles-dir .- 문서화
dbt docs generate --profiles-dir .
dbt docs serve --profiles-dir . --port 8001- 최근 7일 고위험 계정 Top-N (
mart_account_risk_daily)
select account_id, avg_risk_score, max_risk_score, peak_risk_level
from mart_account_risk_daily
where risk_date >= current_date - interval 7 day
and peak_risk_level in ('high','critical')
order by max_risk_score desc
limit 20;- 룰/Severity별 알림 집계 (
fct_alerts)
select rule_id, severity, count(*) as alert_cnt
from fct_alerts
group by rule_id, severity
order by alert_cnt desc;- 일별 엣지 트래픽 (
int_edge_daily)
select edge_day, origin_account_id, dest_account_id, tx_count, total_amount
from int_edge_daily
order by edge_day desc, tx_count desc
limit 100;
