7

문지기는 적재 전에 선다

ETL 파이프라인

학습 목표
  • L2 검증의 실행 위치를 판단한다
  • 통과분과 거부분을 사유와 함께 분리한다

L2 검증의 배치 — 문지기는 적재 전에

코스 2에서 설계하고 에디션 한계로 확장된 L2 검증(존재성·형식·범위·카디널리티)의 실행 위치는 정제 단계, 즉 적재 전입니다.

⚠️ DB에 들어간 뒤 청소하는 것(load-then-clean)은 금물입니다. 오염된 그래프 위에서 도는 CQ는 이미 거짓을 답하고 있습니다. 청소하는 동안에도 누군가는 그 그래프에 질문을 던집니다.

def validate_l2(df: pd.DataFrame) -> tuple[pd.DataFrame, pd.DataFrame]:
    """통과분과 거부분(사유 포함)을 분리 반환"""
    df = df.copy(); df["reject_reason"] = None
    df.loc[df["callSign"].isna(), "reject_reason"] = "존재성: callSign 없음"     # L2 이관분
    bad_time = pd.to_datetime(df["arrivalUtc"], errors="coerce").isna()
    df.loc[bad_time & df["reject_reason"].isna(), "reject_reason"] = "형식: 시각 파싱 실패"
    ok = df[df["reject_reason"].isna()].drop(columns=["reject_reason"])
    rejected = df[df["reject_reason"].notna()]
    return ok, rejected

주목할 점 — 첫 번째 검사가 바로 코스 2에서 L1(DB 제약)에 넣었다가 Community 한계로 L2로 이관된 존재성 검사입니다. 설계 문서의 한 줄 개정이 여기서 코드 한 줄이 됐습니다.

거부 리포트는 축적합니다

사유별 건수·비율을 매 적재마다 자동 산출해 쌓습니다. 이 시계열이 "원천 데이터 품질이 좋아지는가"라는 메타 CQ의 답이 됩니다.

한 번의 거부 목록은 오늘의 문제지만, 여섯 달치 거부 시계열은 원천 기관과 협의할 근거입니다.

실습

  1. validate_l2에 자기 매핑 시트의 검증 열을 전부 옮깁니다.
  2. 거부율을 사유별로 집계합니다. ⚠️ 거부율이 30%를 넘으면 검증이 아니라 매핑이 틀렸을 가능성을 먼저 의심하세요.
  3. 거부분을 rejected/ 에 사유와 함께 저장합니다(헌법 2조).
에디터 로딩 중...
용어