티스토리 뷰

1. 문제 - "건강한지 어떻게 알지?"

평가 기준에 이런 항목이 있었다.

"운영자가 매일 5분 안에 파이프라인 헬스체크를 할 수 있는가"
- Iceberg 메타테이블 기반 헬스 체크 쿼리 5~10개 + BI 대시보드 운영 메트릭 탭(신선도, 일자별 행수, 파일 수, 평균 크기)

 

근데 지금까지 만든 파이프라인엔 흩어진 체크용 SQL 몇 개만 있었지,

'운영자가 실제로 돌려서 건강한지 판단하는' 부분은 없었다. 

그래서 제대로 만들어 보고 싶었다.


2. 그래서 헬스체크 쿼리가 뭔가?

데이터 자체가 아니라 Iceberg 메타테이블을 보는 쿼리다.

Iceberg는 테이블마다 숨은 메타 테이블을 준다:

  • `$snapshots` - 언제 무엇이 커밋됐나(=신선도, 이력)
  • `$files` - 데이터 파일 몇 개, 평균 크기(=small file 여부)
  • `$manifests` - 매니페스트 누적.

이걸로 파이프라인이 건강한가 를 1분 내 판별한다:

최근 적재됐나? · 파일이 잘게 안 쪼개졌나? · 스냅샷 안 쌓였나? · 행수 이상 없나? · 중복 0인가? · 집계 안 깨졌나?

3. 산출물

3-1. 산출물 ① - `pipline_health.py` (한 명령 자동 리포트)

운영자가 한 명령으로 돌려 자동 판정 리포트를 받는 구조이다.

 

아래 표와 같이 총 8개의 체크가 있다. 

각각 OK/WARN/FAIL로 판정한다.

# 체크 근거 판정
1 신선도 bronze=$snapshots 최신 커밋, silver/gold=max(updated_at) 임계(분) 초과
2 small file $files 파일수, 평균 크기 평균<32MB & 파일>5 → compaction
3 스냅샷 누적 $snapshots count 임계 초과 (expire)
4 처리량 silver 처리 행수 0이면
5 중복 count(*)-count(distinct event_id) >0
6 퍼널 정합 requests >= impressions >= clicks >= conversion 위반
7 비율 범위 fill_rate/ctr/cvr 이 0과 1사이어야함 이탈
8 cost 정합 gold cost==silver click cost 합 불일치

다르 근거들은 보면 바로 이해될 것들인데 이해가 힘들 수 있는것만 따로 설명해보자면:

#5 count(*)-count(distinct event_id)

→ 전체행 에서 서로 다른 event_id 개수(중복 배고 센것)
→ event_id는 이벤트마다 유일한거니까 중복이 없다면 두개를 뺐을때 0이 나온다.

#8 gold cost == silver click cost 합

cost(광고비) 정의 == SUM(cost) WHERE event_type='click' (클릭만비용 발생, CPC 모델)

Gold의 총 cost와 Silver의 click 이벤트들의 cost 합이 같아야 하는거다. 

 

핵심= `FAIL` 이면 `exit 1` → 나중에 Airflow/Slack 게이트로 자동 확장할 발판이다. (뒤에도 적을거임)

 

실제 출력(라이브로 돌린 결과):

==============================================================================
 파이프라인 헬스체크 리포트
==============================================================================
 ⚠️  WARN | 신선도 bronze.ad_clicks    | 1038분 전 (임계 30분)
 ✅ OK   | 신선도 gold.campaign_daily  | 2분 전 (임계 30분)
 ✅ OK   | 파일 silver.processed       | 3개·평균 30.78MB
 ✅ OK   | 중복 event_id (silver)      | 0건 (0이어야 정상)
 ✅ OK   | cost 정합성                 | gold=9309.45 vs silver_click=9309.45 (차이 0.00)
==============================================================================
 종합: 29개 체크 | ❌ 0 FAIL · ⚠️ 5 WARN · ✅ 24 OK
==============================================================================

이런걸 보고 운영자는 판단할 수있는거다.

참고로 위에 있는 WARN은 내가 지금 라이브 스트리밍을 안 켜놔서 최근적재가 없어서 나오는거다.

 

그리고 한 가지 문제. 이 긴 `spark-submit` 명령을 운영자가 매번 손으로 칠 순 없다.

운영자가 개발자일 수 있지만, 진짜 광고 지표를 보면서 판단이 필요한건 퍼블리셔 프로젝트의 PM일 수도 있기 때문이다.

그래서 같은 헬스 지표를 1) 눈으로 보는 대시보드와 2)자동으로 도는 잡 + 알림으로 구현했다.

3-2. 산출물 ② - 대시보드 운영 메트릭 탭 

Superset → Trino → Iceberg 구조이다. (write=Spark / read=Trino 분리)

Trino를 고른 이유는 Iceberg 메타테이블($files/$snapshots)을 SQL로 그대로 읽기 때문이다.

그래서 비지니스 KPI뿐 아니라 운영 메트릭 탭까지 같은 엔진으로 된다.

 

운영 탭엔 차트 5개를 깔았다.

차트 정상 이상 신호
신선도 최신 시각이 최근 옛날 시각 → 적재 멈춤
일자별 행 수 고르게 0/급증 → 이상 트래픽
중복 event_id 0 0 아님 → dedup 깨짐
파일 상태 평균 크기 적당 작고 많음 → compaction 필요
스냅샷 수 임계 이하 증가 → expire 필요

 

그리고 Superset 대시보드는 보통 UI에서 마우스로 만들어서 남이 재현하기 힘들다.

그리고 내가 Superset 을 한번도 안써봐서 이번엔 AI를 사용하여, API로 데이터셋, 차트, 대시보드를 만들고 export해서 import 번들(zip)을 떴다. 

그리고 그걸 import 해서 운영 탭을 통째로 재현했다.

 

아래가 실제 Superset 대시보드 운영 탭 상태다

Superset 헬스체크 운영 쿼리

 

3-3. 산출물 ③ - 자동화: Airflow 잡 + Slack 실패 경보

긴 명령을 손으로 안치게 이 헬스체크들을 Airflow 잡으로 감쌌다.

health_check DAG (매시간)
   └─ pipeline_health.py 실행
        ├─ 0 FAIL → 태스크 초록 → 조용 (무알림)
        └─ FAIL(exit 1)/크래시 → 태스크 빨강 → Slack 경보 🚨

 

  • 매시간돈다. 헬스체크는 읽기 전용이라 가벼워서 자주 돌려 문제를 빨리 잡는다. 
  • 앞서 만든 `exit 1`이 여기서 사용된다 → 태스크가 자동으로 빨개지고 `on_failure_callback`이 Slack 경보를 쏜다.
  • 이 콜백은 새로 만든건 아니고, medallion, maintenance 잡에도 똑같이 썼다
  • WARN은 알림 안가고, 치명 적인 FAIL/크래시만 - 노이즈 방지

4. 산출물 ④ - 데일리 KPI 리포트 Slack 봇

위까진 '문제 생기면' 발생하는 알림이었다.

근데 운영자 또는 프로젝트 인원들은 문제가 없어도 매일 어제 광고가 어땠나를 궁금해할 수 있다.

그래서 매일 아침 정상 KPI 요약을 Slack에 푸시하는 봇을 더해봤다.

 

광고 도메인 특성상 어제vs오늘 비교는 의미가 약할것 같다.

사실 광고는 요일 계절성(주중/주말)이 세서, 전주 동요일(D-7), 전월 동요일(D-28)대비가 진짜 증감을 보여준다고 생각했다.

📊 데일리 KPI 리포트 — 2026-06-23      ← D-1(어제), 완료된 날 집계
지표        오늘      전주대비    전월대비
──────────────────────────────────
노출       259.7k    ▼-5.1%    ▼-6.2%
클릭        5.7k     ▼-9.1%    ▼-14.2%
광고비     $3,437    ▼-9.9%    ▼-0.9%
...
+ 최근 7일 표 + 4지표 추세 차트(광고비·노출·클릭·전환) 이미지

 

아래와 같이 핵심 지표를 보여주며,

최근 30일동안의 핵심 지표들을 그래프로도 그려서 매일 아침 9시에 잡이 돈뒤, 슬랙에 올라오도록 하였다.


5. 최종 운영자 워크플로우

평소 → 아무것도 안 함 (잡이 매시간 조용히 체크)
매일 아침 → 데일리 리포트가 Slack에 KPI 요약을 던져줌 (← 푸시)
치명 문제 → Slack 경보 핑 → 로그 링크로 원인 (← 푸시)
궁금/WARN → 대시보드 운영 탭 열어 5개 차트 확인 (← 풀)

같은 헬스 지표를 스크립트(자동판정), 대시보드(시각), Slack(알림) 세 곳에서 보고,

운영자는 평소 무 알림 → 문제 시 푸시 → 궁금하면 풀로 5분안에 헬스체크가 끝난다

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2026/07   »
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
글 보관함