LabHub
学习 学习路径 课程

处理客户数据

第 13 周营收变成 0 — 把接收契约写进代码

在 LabHub 中继续学习

한국어 원문으로 표시합니다.

목표

주마다 오는 파일에서 스키마를 뽑아 지문으로 굳히고, 칼럼 추가·삭제·이름 변경·타입 변경을 분류해 호환 규칙으로 자동 판정하는 도구 schema.py 를 만든다. 마지막에는 이름도 타입도 그대로인 채 뜻만 바뀐 칼럼을 값 분포로 잡아 낸다.

왜 중요한가

남이 주는 파일의 스키마는 통보 없이 바뀐다. 보내는 쪽은 자기 시스템의 필드를 정리한 것이고, 받는 쪽은 그것을 계약으로 쓰고 있었을 뿐이다. 우리가 바꾸는 쪽을 통제할 수 없으므로, 할 수 있는 일은 바뀌었다는 사실을 파이프라인이 먼저 알아채게 만드는 것뿐이다. 알아챈 다음이 더 중요하다. 모르는 칼럼이 하나 늘어난 것 때문에 적재를 멈추면 아무도 그 경고를 신뢰하지 않게 되고, 필수 칼럼이 사라졌는데 그냥 넘어가면 숫자가 조용히 틀린다. 그래서 무엇이 깨지고 무엇이 안 깨지는지를 규칙으로 못박아 둔다. 기본은 두 줄이다 — 모르는 칼럼은 통과, 없어진 필수 칼럼은 중단. 그리고 스키마 검사가 절대 못 보는 것이 하나 있다. 금액의 단위가 원에서 천원으로 바뀌면 칼럼 이름도 타입도 그대로다. 검사는 전부 통과하고 매출만 1000분의 1이 된다. 이런 변화는 값의 분포로만 보이고, 분포는 증거가 아니라 단서다. 채점기는 여러분의 문구를 믿지 않는다. 임시 디렉터리에 채점기가 만든 주간 파일을 차려 놓고 여러분의 도구를 실제로 실행해 분류와 판정을 대조한다. 상호와 금액은 실행마다 바뀐다.

단계

  1. /root/drift/gen_weeks.py 를 만들어 실행해 /root/drift/weeks 아래 w01.csv 부터 w07.csv 까지 만드세요. 주문 30건은 내내 같고 스키마만 달라집니다.
  2. /root/drift/schema.pyfingerprint 를 만들어 칼럼 이름·타입·값 표본과 지문을 내게 하고, w01.csv 의 지문을 /root/drift/baseline.json 에 저장하세요.
  3. diff <기준 JSON> <파일> 을 더해 칼럼 추가와 삭제를 분류하게 하세요.
  4. diff 가 값 표본이 크게 겹치는 짝을 찾아 이름 변경으로 분류하게 하세요. 이름 변경으로 잡힌 칼럼은 추가·삭제 목록에서 빠집니다.
  5. diff 가 같은 칼럼의 타입 변경을 분류하게 하세요. 이름이 바뀌면서 타입도 바뀐 경우까지 봅니다.
  6. /root/drift/contract.json 에 필수·선택 칼럼과 규칙을 선언하고, gate <기준 JSON> <파일> 이 pass·warn·stop 을 판정하게 하세요.
  7. watch <기준 CSV> <파일> 을 더해 숫자 칼럼의 중앙값 변화를 재게 하고, 단위가 바뀐 주차를 /root/drift/meaning.json 에 적으세요.
  8. 일곱 주차를 한 번에 판정해 /root/drift/drift_report.json/root/drift/drift_report.md 를 만드세요.

참고

일곱 주치 수신 파일 만들기

/root/drift/gen_weeks.py 를 만들어 실행해 /root/drift/weeks 아래 w01.csv 부터 w07.csv 까지 만드세요. 주문 30건은 내내 같고 칼럼만 주차마다 달라집니다.

기준 주차의 행을 딕셔너리 목록으로 만들어 두고, 주차마다 칼럼 목록과 값만 손봐 다시 쓰면 됩니다. 값이 내내 같아야 나중에 값 표본으로 이름 변경을 찾을 수 있습니다. 단위가 바뀌는 주차만 값을 고칩니다.

스키마를 지문으로 굳히기

/root/drift/schema.pyfingerprint <파일> 을 만들어 rows·columns·digest 를 내게 하고, w01.csv 의 지문을 /root/drift/baseline.json 에 저장하세요.

칼럼마다 값들을 모아 타입을 추론하고, 서로 다른 값을 정렬해 앞 20개를 표본으로 담습니다. 지문은 이름과 타입만 이어 붙여 해시합니다 — 표본까지 넣으면 데이터가 바뀔 때마다 지문이 달라져 쓸모가 없어집니다.

늘어난 칼럼과 없어진 칼럼 가르기

diff <기준 JSON> <파일> 을 더해 added·removed·renamed·retyped 네 목록을 내게 하세요. 이 단계에서는 추가와 삭제만 채워도 됩니다.

기준 지문과 새 파일의 지문에서 이름 집합을 꺼내 차집합을 구하면 추가와 삭제가 나옵니다. 목록은 정렬해서 내세요 — 순서가 실행마다 달라지면 비교할 수 없습니다.

이름만 바뀐 칼럼 찾아내기

diff 가 사라진 칼럼과 생긴 칼럼의 값 표본 자카드 유사도가 0.8 이상이면 이름 변경으로 분류하게 하세요. 이름 변경으로 잡힌 칼럼은 added·removed 에서 빠집니다.

이름만 보면 사라진 것 하나와 생긴 것 하나입니다. 값을 보면 같은 칼럼입니다. 사라진 칼럼마다 생긴 칼럼들과 표본 집합의 교집합 크기를 합집합 크기로 나눠 가장 높은 짝을 고르고, 문턱값을 넘을 때만 이름 변경으로 봅니다.

타입이 바뀐 칼럼 가려내기

diff 가 같은 이름 칼럼의 타입 변경을 retyped[이름, 옛타입, 새타입] 으로 담게 하세요. 이름이 바뀌면서 타입도 바뀐 경우는 새 이름으로 담습니다.

타입은 추론한 값이라 자료가 조금만 달라져도 바뀔 수 있습니다. 그래서 정수가 소수 표기로 바뀐 것과 숫자가 문자열이 된 것을 구별할 수 있게 옛 타입과 새 타입을 함께 담아 두세요. 다음 단계에서 이 둘을 다른 등급으로 다룹니다.

호환 규칙을 코드로 못박기

/root/drift/contract.json 에 required·optional·rules 를 선언하고, gate <기준 JSON> <파일>{"verdict": …, "reasons": [...]} 를 내게 하세요. 모르는 칼럼은 통과, 없어진 필수 칼럼은 stop 입니다.

필수 칼럼 목록은 업무가 정하는 것입니다. order_id·shop_id·qty·amount_krw·ordered_at 이 없으면 집계를 만들 수 없고, shop_name 과 weight 는 없어도 집계는 나옵니다. reasons 는 정렬해서 내고, 사유마다 어떤 칼럼 때문인지 이름을 붙이세요.

스키마가 못 보는 변화 잡기

watch <기준 CSV> <파일> 을 더해 두 파일에 다 있는 숫자 칼럼의 중앙값과 비율을 재게 하세요. 그리고 단위가 바뀐 주차를 /root/drift/meaning.json 에 column·median_before·median_after·ratio·flag·schema_verdict 로 적으세요.

이 변화는 칼럼 이름도 타입도 그대로라 앞 단계의 판정이 전부 통과합니다. 값의 분포만 내려앉습니다. 비율이 3 이상이거나 3분의 1 이하면 사람이 봐야 한다는 표시를 다세요 — 증거가 아니라 단서입니다. schema_verdict 에는 같은 주차에 대한 gate 판정을 함께 적어, 스키마 검사가 이것을 못 본다는 사실을 남기세요.

일곱 주를 한 장으로 보고하기

일곱 주차를 기준 주차와 대조해 /root/drift/drift_report.json 에 baseline·weeks·pass·warn·stop 을 적고, /root/drift/drift_report.md## 무엇이 바뀌었나 ## 무엇이 깨지고 무엇이 안 깨지나 ## 자동으로 잡히지 않는 것 ## 보내는 쪽과 맞출 것 네 절로 쓰세요.

weeks 는 파일 이름을 키로 두고 verdict·added·removed·renamed·retyped 를 담은 객체입니다. 기준 주차 자신도 넣으면 판정이 pass 로 나와 대조가 쉬워집니다. 보고서에는 stop 이 난 주차와 그 이유를 숫자와 함께 적으세요.