C.W.K.
Stream
Lesson 03 of 06 · published

팀 간 Data Contract

~11 min · contracts, production, process

Level 0구경꾼
0 XP0/47 lessons0/11 achievements
0/120 XP to next level120 XP to go0% complete

Contract 가 해결하는 문제

Producer 팀이 schema 변경 ship. Consumer 팀 파이프라인이 새벽 6시에 깨짐. Consumer 팀 화남. Producer 팀은 자기 테이블 누가 읽는지 몰랐어. 데이터 만드는 팀 두 개 이상 가진 회사에서 가장 흔한 cross-team 데이터 outage. Fix 는 data contract.

Contract 가 가지는 것

  • Schema — column 이름, type, nullability, 허용 값.
  • Freshness — "오전 9시까지 가능, 99.5% 일자."
  • 소유권 — 생산 팀 이름과 on-call 채널.
  • Breaking-change 정책 — column 제거 전 얼마나 알림; column rename 마이그레이션 처리법.
  • Versioning — additive vs breaking 변경; downstream consumer 가 opt-in 해야 하나.

Contract 가 아닌 것

Contract 는 아무도 안 읽는 위키 페이지가 아니야. 코드에 의해 enforce 되는 산출물 — producer write 단계에서 schema 검증, 자동화된 freshness 체크, 모든 PR 에 현재 schema 를 선언된 contract 와 비교하는 CI 테스트. 문서의 contract 는 wishful thinking; CI 의 contract 는 load-bearing wall.

Code

Producer repo 에 check-in 된 YAML contract·yaml
# contracts/orders_v1.yaml
name: orders
version: 1
owner:
  team: orders-eng
  oncall: '#orders-data'
  email: orders-eng@example.com
freshness:
  sla_hours: 24
  measured_by: max(ingested_at)
schema:
  - name: order_id
    type: string
    required: true
    unique: true
    pattern: '^O\d{6}$'
  - name: customer_id
    type: string
    required: true
  - name: amount_usd
    type: number
    required: true
    minimum: 0
  - name: status
    type: string
    enum: [pending, completed, cancelled]
breaking_change_policy:
  notice_days: 30
  migration_pattern: |
    옆에 새 column 추가, notice window 동안 둘 다 채움,
    window 끝나면 옛 column 제거.
Producer 의 실제 schema 와 선언된 contract 비교하는 CI 체크·python
import yaml
import pyarrow.parquet as pq

def check_contract(parquet_path: str, contract_path: str) -> list[str]:
    '''실제 Parquet schema 와 contract 비교. 위반 list 반환.'''
    contract = yaml.safe_load(open(contract_path))
    actual = pq.read_schema(parquet_path)
    actual_cols = {f.name: str(f.type) for f in actual}
    declared = {c['name']: c['type'] for c in contract['schema']}

    issues = []
    for name in declared.keys() - actual_cols.keys():
        issues.append(f'필수 column 누락: {name}')
    for name in actual_cols.keys() - declared.keys():
        issues.append(f'예상치 못한 column: {name} (contract 에 추가하거나 제거)')
    return issues

External links

Exercise

본인이 만들고 다른 팀이 consume 하는 데이터 product 하나 골라. 한 페이지 YAML contract 초안: schema, freshness, 소유권, breaking-change 정책. Consuming 팀에 review 위해 초안 공유. Contract 작성 연습이 자체로 문서보다 가치 있을 때 자주 — 양쪽에 obvious 안 했던 모든 가정 surface.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.