데이터 플랫폼에서 팀 운영이 기술 문제가 되는 순간
CI/CD의 마지막 병목은 종종 도구가 아니라 팀 운영이다. dbt run은 빠르게 끝나고, Airflow DAG validation도 통과했는데, 정작 배포는 “누가 approve해야 하지?”, “이 변경은 데이터 계약 breaking change인가?”, “운영 DB 권한을 가진 사람이 직접 눌러도 되나?” 같은 질문에서 멈춘다.
데이터 플랫폼 변경은 애플리케이션 코드보다 영향 범위가 늦게 드러나는 편이다. 컬럼 하나를 삭제하면 빌드는 성공할 수 있지만, 다음 날 아침 대시보드와 ML feature job이 동시에 깨질 수 있다. DAG schedule을 바꾸면 태스크는 정상 완료되지만 downstream freshness SLO가 밀릴 수 있다. 그래서 팀 운영 규칙은 “회의를 늘리기 위한 절차”가 아니라 작은 변경을 빠르게 합치되, 위험한 변경은 자동으로 더 강한 검토를 받게 하는 제어면(control plane) 이어야 한다.
이 장에서는 데이터 플랫폼 팀이 쓸 수 있는 브랜치 전략, PR 리뷰 규칙, CODEOWNERS, 배포 환경 권한, 예외 처리 방식을 하나의 운영 모델로 묶어본다.
기본 원칙: 긴 승인 체인보다 짧은 피드백 루프
좋은 팀 운영은 두 목표를 동시에 만족해야 한다.
- 변경 lead time을 줄인다. 작은 수정이 며칠 동안 리뷰 대기열에 묶이면 배포 단위가 커지고, 충돌과 롤백 비용도 커진다.
- 고위험 변경을 놓치지 않는다. 권한, 스키마, 파티션, lineage, 비용, 개인정보 관련 변경은 일반 코드 스타일 리뷰와 같은 강도로 보면 안 된다.
DORA는 소프트웨어 전달 성과를 change lead time, deployment frequency, change fail rate, failed deployment recovery time, deployment rework rate 같은 지표로 본다. 중요한 점은 속도와 안정성을 따로 최적화하지 않는다는 것이다. 배포를 자주 하려면 테스트, 리뷰, 권한 경계가 자동화되어야 하고, 안정성을 높이려면 변경 단위를 작게 유지해야 한다.
데이터 플랫폼 팀의 실무 원칙은 다음처럼 정리할 수 있다.
main은 항상 배포 가능한 상태로 유지한다.- 모든 변경은 PR을 통과한다. 단, 리뷰 강도는 위험도에 따라 다르게 한다.
- CI가 확인할 수 있는 것은 사람이 보지 않는다. format, lint, DAG import, dbt compile/test, contract check는 자동화한다.
- 사람은 CI가 판단하기 어려운 것만 본다. 모델 grain 변경, 개인정보 노출, 비용 폭증, 복구 가능성, downstream 영향도, 롤백 플랜이다.
- production 배포 권한은 repository write 권한과 분리한다.
브랜치 전략: GitFlow보다 짧은 feature branch
데이터 플랫폼에서는 보통 GitFlow식 장기 브랜치보다 짧은 feature branch + 보호된 main이 낫다. 이유는 단순하다. SQL 모델, DAG, Terraform, Helm chart는 서로 다른 파일처럼 보여도 실제로는 같은 운영 그래프를 바꾼다. 브랜치가 오래 살아 있으면 “각자 CI는 통과했지만 main에서 합치면 깨지는” 상황이 늘어난다.
작은 diff
lineage 영향도
위험도별 승인
status check 필수
smoke check
self-review 차단
언제 trunk-based에 가깝게 운영할 수 있나
다음 조건이 있으면 trunk-based에 가깝게 운영할 수 있다.
- PR diff가 작고, 하루 안에 리뷰와 merge가 끝난다.
main기준 CI가 빠르고 안정적이다.- 기능 토글, 환경 분리, backward-compatible schema change가 자리 잡혀 있다.
- production 배포는 artifact promotion으로 분리되어 있다.
반대로 다음 상황에서는 release branch가 필요할 수 있다.
- 외부 고객 또는 규정 때문에 배포 창이 정해져 있다.
- 동일 코드베이스에서 여러 운영 환경 버전을 동시에 유지해야 한다.
- 데이터 마이그레이션과 애플리케이션 배포가 여러 단계로 묶여 있어 freeze 기간이 필요하다.
하지만 release branch를 쓰더라도 장기 브랜치를 “개발 공간”으로 쓰면 안 된다. release branch는 검증과 hotfix를 위한 짧은 안정화 공간이어야 한다.
PR 리뷰 프로세스: 모든 PR을 같은 방식으로 보지 않는다
데이터 플랫폼 PR은 위험도가 다르다. README 수정과 fct_revenue grain 변경을 같은 승인 규칙으로 처리하면, 둘 중 하나는 항상 틀린 절차가 된다. 리뷰 프로세스는 변경 유형을 먼저 분류해야 한다.
| 변경 유형 | 예시 | 자동 체크 | 사람 리뷰 포인트 |
|---|---|---|---|
| 저위험 | 문서, 주석, dashboard description | markdown lint, link check | 의미가 맞는지 |
| 일반 코드 | Airflow task 함수, dbt staging 모델 | unit test, DAG import, dbt compile | 유지보수성, 실패 처리 |
| 데이터 계약 | 컬럼 추가/삭제, type 변경, model grain 변경 | contract check, downstream lineage diff | 하위 호환성, 소비자 공지 |
| 운영 위험 | schedule 변경, retry 정책, pool/queue 변경 | integration test, dry run | backfill 영향, 중복 처리 |
| 보안·권한 | IAM, secret, masking, PII 접근 | policy-as-code, secret scan | least privilege, 감사 가능성 |
| 비용 위험 | 대형 backfill, partition 변경, cluster size 변경 | cost estimate, row count estimate | 제한 시간, kill switch |
리뷰어가 볼 질문도 바뀌어야 한다.
- 이 변경은 실패했을 때 어디까지 전파되는가?
- 이전 버전으로 되돌릴 수 있는가, 아니면 forward fix만 가능한가?
- downstream owner에게 공지가 필요한가?
- backfill이 기존 파티션을 덮어쓰는가, append하는가?
- production credential 또는 PII column에 접근하는가?
- 배포 후 어떤 SLO/품질 지표를 확인해야 하는가?
리뷰 템플릿은 이 질문을 PR 작성자에게 미리 묻는 장치다.
## 변경 유형
- [ ] 일반 코드
- [ ] 데이터 계약 변경
- [ ] 운영 파라미터 변경
- [ ] 권한/보안 변경
- [ ] 대량 backfill 또는 비용 영향
## 영향 범위
- 변경되는 테이블/DAG:
- downstream dashboard/job:
- owner 공지 필요 여부:
## 검증
- 로컬/CI에서 실행한 명령:
- 샘플 row count 또는 reconciliation 결과:
## 롤백/완화
- 롤백 방법:
- 실패 시 중단 기준:
- 배포 후 확인할 지표:이 템플릿의 목적은 서류 작업이 아니다. 리뷰어가 “무엇을 봐야 하는지”를 매번 추측하지 않게 하는 것이다.
CODEOWNERS: 사람 이름보다 팀 경계로 설계한다
GitHub의 CODEOWNERS는 특정 경로가 바뀌면 책임 있는 사용자나 팀을 자동으로 리뷰어로 요청하는 기능이다. branch protection 또는 ruleset에서 code owner review를 필수로 설정하면, 해당 owner의 승인이 있어야 merge할 수 있다.
데이터 플랫폼 저장소에서는 경로가 곧 운영 책임 경계인 경우가 많다.
# .github/CODEOWNERS
# 기본 fallback: 어떤 변경도 owner 없이 지나가지 않게 한다.
* @org/data-platform-maintainers
# Airflow 운영 경계
/dags/payments/ @org/payments-data-eng @org/data-platform-ops
/dags/marketing/ @org/marketing-analytics
# dbt mart는 도메인 owner와 플랫폼 owner가 함께 본다.
/dbt/models/marts/finance/ @org/finance-analytics @org/data-platform-maintainers
/dbt/models/marts/growth/ @org/growth-analytics
# 보안·권한·배포 설정은 더 좁게 보호한다.
/infra/terraform/ @org/platform-infra @org/security
/.github/workflows/deploy*.yml @org/platform-infra
/policies/ @org/security @org/data-governance운영에서 중요한 점은 세 가지다.
- 개인보다 팀을 owner로 둔다. 한 명이 휴가 가면 배포가 멈추는 구조는 운영 리스크다.
- fallback owner를 둔다. 새 디렉터리가 생겼는데 아무도 owner가 아니면, 가장 위험한 변경이 가장 쉽게 지나간다.
- 권한을 실제로 확인한다. GitHub CODEOWNERS에서 owner가 되려면 write 권한이 필요하다. 팀 owner는 visible이어야 하고, 팀 자체가 명시적인 write 권한을 가져야 한다.
CODEOWNERS는 만능이 아니다. 파일 경로 기반이므로 “이 PR이 production 배포를 포함하는가”, “이 변경이 10TB backfill인가” 같은 문맥은 알지 못한다. 그래서 label, CI risk classifier, environment protection rule과 함께 써야 한다.
Branch protection과 ruleset: main을 사람 손에서 떼어놓기
main을 보호하지 않으면 모든 절차는 권고사항으로 끝난다. GitHub branch protection은 protected branch에 대해 PR 리뷰, status check, conversation resolution, signed commits, linear history, merge queue, successful deployment 같은 조건을 강제할 수 있다. 기본적으로 force push와 branch deletion도 막는다.
데이터 플랫폼 팀의 최소 권장값은 다음과 같다.
main 보호 규칙
- Require a pull request before merging
- Require approvals: 1~2명
- Require review from Code Owners
- Dismiss stale pull request approvals when new commits are pushed
- Require status checks to pass
- lint
- unit/integration tests
- dbt compile/test 또는 DAG validation
- secret scan / policy check
- Require conversation resolution before merging
- Do not allow bypassing the above settings
- Block force pushes and deletions조직 단위로 여러 repository를 관리한다면 branch protection rule보다 ruleset이 운영하기 쉽다. 개별 repo 설정이 drift되는 문제를 줄이고, “모든 production 배포 repo는 동일한 최소 보호 규칙을 가진다”는 표준을 만들 수 있기 때문이다.
주의할 점도 있다. GitHub 문서에 따르면 branch protection rule은 한 번에 하나만 적용된다. 여러 규칙이 같은 branch를 겨냥하면 어떤 규칙이 적용되는지 헷갈릴 수 있다. 따라서 main, release/*, hotfix/*처럼 명확하게 나누고, 예외 규칙은 문서화해야 한다.
배포 권한: merge 권한과 production 권한을 분리한다
PR을 merge할 수 있는 사람과 production 배포를 승인할 수 있는 사람은 같을 수도 있지만, 권한 모델에서는 분리해서 생각해야 한다. 특히 데이터 플랫폼은 배포가 곧 외부 시스템 권한 사용을 의미하는 경우가 많다.
GitHub Actions environment는 배포 대상별 보호 규칙과 secret을 나눌 수 있다. 예를 들어 staging은 main merge 후 자동 배포하고, production은 required reviewer와 branch/tag restriction을 둔다.
# .github/workflows/deploy.yml
name: deploy-data-platform
on:
push:
branches: [main]
workflow_dispatch:
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: ./scripts/build_artifact.sh
deploy-staging:
needs: build
runs-on: ubuntu-latest
environment: staging
steps:
- run: ./scripts/deploy.sh staging
deploy-production:
needs: deploy-staging
runs-on: ubuntu-latest
environment:
name: production
url: https://data-platform.example.internal
steps:
- run: ./scripts/deploy.sh productionproduction environment에는 다음 규칙을 권장한다.
- required reviewers를 개인이 아니라 운영 팀 또는 release manager 팀으로 둔다.
- prevent self-review를 켠다. 배포를 시작한 사람이 자기 배포를 승인하지 못하게 한다.
- deployment branches/tags를
main또는release/*로 제한한다. - production secret은 repository secret이 아니라 environment secret으로 둔다.
- 가능한 경우 OIDC role도 environment 기준으로 분리한다.
이렇게 하면 “PR은 합쳐졌지만 production credential은 아직 열리지 않은” 상태를 만들 수 있다. 이 분리가 중요하다. 리뷰는 코드 품질과 위험 검토이고, production gate는 실제 운영 환경에 영향을 주는 행위의 승인이다.
위험도 기반 승인 매트릭스
팀 규모가 커질수록 “누가 승인해야 하는가”를 매번 Slack에서 정하면 병목이 된다. 승인 매트릭스를 미리 정해두면 자동화하기 쉽고, 예외 처리도 투명해진다.
| 위험도 | 조건 | 필요한 승인 | 배포 방식 |
|---|---|---|---|
| Low | 문서, 테스트, non-prod 설정 | 1명 또는 auto-merge | main merge 후 자동 |
| Medium | 일반 DAG/dbt 모델 변경 | CODEOWNER 1명 + CI 통과 | staging 자동, prod 자동 또는 팀 승인 |
| High | contract breaking 가능성, schedule 변경, 대량 backfill | domain owner + platform owner | production required reviewer |
| Critical | PII, 권한, secret, Terraform state, warehouse admin role | security/governance + platform lead | change window + 수동 승인 + 감사 로그 |
이 매트릭스는 policy-as-code로 일부 자동화할 수 있다.
# 예시: PR label 기반 위험도 게이트
rules:
- match:
paths: ["infra/terraform/**", "policies/**"]
require_labels: ["risk:critical"]
require_reviewers: ["security", "platform-infra"]
- match:
paths: ["dbt/models/marts/**"]
require_checks: ["dbt-test", "lineage-impact"]
require_labels: ["owner-notified"]
- match:
paths: ["dags/**"]
require_checks: ["dag-import", "dag-test"]
require_reviewers: ["data-platform-ops"]자동화는 완벽할 필요가 없다. 목표는 “리뷰어가 위험도를 놓치지 않게 하는 것”이다. 의심스러운 PR에 risk:needs-triage를 붙이고 merge를 막는 것만으로도 사고 가능성이 크게 줄어든다.
예외와 긴급 배포: bypass를 없애지 말고 기록하게 한다
운영에서 예외는 반드시 생긴다. 새벽 장애 중에 primary DAG를 멈춰야 하거나, 잘못 배포된 권한 정책을 즉시 되돌려야 할 수 있다. 중요한 것은 예외를 불가능하게 만드는 것이 아니라, 예외가 감사 가능하고 사후 검토 가능한 형태로만 일어나게 하는 것이다.
긴급 절차는 다음 정보를 남겨야 한다.
- 누가 bypass를 요청했는가
- 어떤 incident 또는 ticket과 연결되는가
- 어떤 보호 규칙을 우회했는가
- 우회가 필요한 시간 범위는 얼마인가
- 배포 후 어떤 검증을 했는가
- 정상 절차로 되돌리는 follow-up PR은 무엇인가
Emergency deploy checklist
1. Incident commander가 emergency label 부여
2. on-call platform owner가 변경 diff 확인
3. production reviewer 1명이 승인 (self-review 금지 유지)
4. 배포 후 smoke check / freshness / row count 확인
5. incident timeline에 commit SHA, workflow run, 승인자 기록
6. 24시간 안에 postmortem 또는 follow-up PR 작성“관리자는 언제든 bypass 가능”한 설정은 편하지만 위험하다. GitHub environment와 branch protection 모두 bypass 제한 옵션을 제공하므로, 평소에는 우회를 막고 break-glass 계정을 별도로 관리하는 편이 낫다. break-glass 사용은 알림과 감사 로그가 붙어야 한다.
데이터 플랫폼 팀 운영 체크리스트
마지막으로 실무에서 바로 점검할 수 있는 체크리스트다.
Repository
- [ ]
main직접 push가 막혀 있다. - [ ] 필수 CI check 이름이 중복되지 않는다.
- [ ] stale approval dismiss가 켜져 있다.
- [ ] CODEOWNERS가 팀 단위로 작성되어 있다.
- [ ] fallback owner가 있다.
- [ ] 보안/infra/workflow 경로는 별도 owner가 있다.
CI
- [ ] dbt compile/test, DAG import/test, secret scan이 PR에서 돈다.
- [ ] schema/contract 변경은 별도 check 또는 label을 요구한다.
- [ ] lineage 영향도 또는 downstream owner 확인 절차가 있다.
- [ ] 대량 backfill은 비용/범위 estimate를 남긴다.
Deployment
- [ ] staging과 production environment가 분리되어 있다.
- [ ] production secret은 environment secret으로 제한되어 있다.
- [ ] production required reviewer가 팀 단위로 지정되어 있다.
- [ ] self-review가 금지되어 있다.
- [ ] 배포 가능한 branch/tag가 제한되어 있다.
- [ ] workflow run, 승인자, artifact version이 추적된다.
Operation
- [ ] emergency bypass 절차가 문서화되어 있다.
- [ ] release manager 또는 on-call owner가 명확하다.
- [ ] 반복되는 리뷰 지연 원인을 DORA 지표와 함께 본다.
- [ ] change fail rate가 높아지면 승인 단계를 늘리기보다 테스트와 blast radius 축소를 먼저 본다.
마무리: 권한은 느리게 만들기 위해서가 아니라 작게 실패하기 위해서다
팀 운영 규칙이 잘못 설계되면 CI/CD는 “자동화된 배포”가 아니라 “자동화 주변의 수동 승인 지옥”이 된다. 반대로 규칙이 잘 설계되면 대부분의 작은 변경은 빠르게 지나가고, 정말 위험한 변경만 더 강한 검토를 받는다.
데이터 플랫폼의 좋은 운영 모델은 다음 문장으로 요약된다.
작은 변경은 자주 합치고, production 권한은 분리하며, 위험도는 사람이 기억하지 말고 시스템이 드러내게 한다.
브랜치 전략, CODEOWNERS, branch protection, environment protection, 승인 매트릭스는 각각 따로 보면 설정 항목이다. 하지만 함께 묶으면 팀이 빠르게 움직이면서도 데이터 품질, 보안, 비용, 복구 가능성을 잃지 않게 하는 운영 체계가 된다.
References
- GitHub Docs, About protected branches
- GitHub Docs, Deployments and environments
- GitHub Docs, About code owners
- Google SRE Book, Release Engineering
- DORA, DORA’s software delivery performance metrics