LabHub
배우기 러닝패스 코스

데이터 파이프라인 · 스키마 변화와 계약 판 · 실습

판을 매겨 바꾸고 양쪽을 다 살린다

LabHub 에서 이어서 보기

목표

판 번호가 붙은 스키마로 JSON Lines 를 다루는 계약 도구 contract.py 를 만든다. 판 사이의 변화를 갈래별로 분류하고, 뒤로 호환과 앞으로 호환을 Avro 의 스키마 해석 규칙대로 판정하고, 여러 판이 섞여 흐르는 전환 기간을 읽기 스키마 하나로 넘긴다.

왜 중요한가

쓰는 쪽과 읽는 쪽은 같은 순간에 바뀌지 않는다. 그 사이에는 반드시 한쪽만 새 코드인 기간이 있고, 그 기간에도 자료는 계속 흐른다. 그래서 스키마 변경을 설계할 때 물어야 할 것은 "이 변경이 맞는가" 가 아니라 "어느 순서로 배포해도 살아남는가" 다.
답은 세 가지로 갈린다. 기본값이 있는 필드를 더하는 것은 양방향으로 안전하고, 기본값 없는 필수 필드를 더하는 것은 새 읽기 코드가 옛 자료를 못 읽게 만들고, 타입 변경은 넓히는 방향과 좁히는 방향이 정확히 반대의 결과를 낸다. 이름 변경은 스키마만 보면 추가 하나와 삭제 하나이고, 별칭으로만 한 사건으로 되돌아온다. 그런데 별칭은 읽는 쪽 스키마의 것만 쓰이므로 이름 변경은 한쪽 방향으로만 산다.
전환 기간을 넘기는 방법은 하나뿐이다. 읽기 스키마에 기본값을 넉넉히 달아 옛 판까지 읽히게 만드는 것이다. 이 실습은 그 기본값 하나가 몇 건을 살리는지를 숫자로 보인다.
채점기는 여러분의 문구를 믿지 않는다. 임시 디렉터리에 채점기가 만든 스키마와 줄을 차려 놓고 여러분의 도구를 실제로 실행해 분류와 판정을 채점기가 따로 구현한 값과 대조한다. 필드 이름과 타입과 금액은 실행마다 바뀝니다.

단계

1. /root/evolve/gen_stream.py 를 만들어 실행해 /root/evolve/schemasv1.json 부터 v5.json 까지, /root/evolve/stream 에 판마다 12줄짜리 v1.jsonl 부터 v5.jsonl 까지와 다섯 판이 섞인 mixed.jsonl 을 만드세요.
2. /root/evolve/contract.pyfields <스키마> 를 만들어 판 번호와 필드 이름, 필수·선택, 기본값을 내게 하세요.
3. diff <옛 스키마> <새 스키마> 를 더해 추가와 삭제를 분류하게 하세요. 추가는 기본값이 있는 것과 없는 것으로 갈라 냅니다.
4. diff 가 새 판의 aliases 를 보고 이름 변경을 한 사건으로 묶게 하세요. 묶인 이름은 추가와 삭제 목록에서 빠집니다.
5. diff 가 타입 변경을 넓히기와 좁히기로 갈라 내게 하세요. 승격 표에 있으면 넓히기, 없으면 좁히기입니다.
6. compat <옛 스키마> <새 스키마> 를 더해 뒤로 호환과 앞으로 호환을 판정하고 사유를 고정된 코드로 내게 하세요.
7. read <읽기 스키마> <스키마폴더> <파일> 을 더해 여러 판이 섞인 줄을 한 판으로 읽게 하고, 너그러운 읽기 스키마 /root/evolve/reader.json 을 만들어 두 읽기의 차이를 /root/evolve/window.json 에 적으세요.
8. 다섯 판의 이력을 /root/evolve/evolve_report.json/root/evolve/evolve_report.md 로 남기세요.

참고

단계 8개

  1. 다섯 판을 만들어 내보내기
  2. 필수와 선택을 기본값으로 가르기
  3. 더해진 것과 없어진 것 가르기
  4. 이름 변경을 한 사건으로 묶기
  5. 넓히기와 좁히기 갈라 내기
  6. 뒤로와 앞으로를 따로 판정하기
  7. 전환 기간을 읽기 스키마 하나로 넘기기
  8. 판 이력을 한 장으로 남기기