CI 실측 데이터 확보 + 운영 규약 표준화 + 커밋 게이트 자동화
주요 결정
PR 템플릿 체크박스 삽입
PR 오픈 시점부터 rebuild_all 계획 여부를 author가 명시하도록 강제 (사후 누락 방지)
금지 사례 명문화
서비스 코드 변경 PR에서 남용 시 GHA 비용 낭비 발생 → path-filter로 충분함을 명시
배경
Sprint 104는 채널톡 CI 리팩토링 레퍼런스 원리 ⑤(확산 단계)를 완료했으나, 실측 데이터 확보에 실패했다. 원인은 명확하다: CI 인프라 PR(.github/workflows/ci.yml 단독 수정)이 detect-changes path-filter를 통과하지 못해 서비스 잡 전체가 skip됐다. Sprint 104 ADR 교훈 1은 이를 "CI 인프라 PR은 detect-changes skip으로 자기 자신의 실측 데이터를 생성하지 못한다"고 기록하고 표준 프로세스화를 Sprint 105로 이월했다.
Sprint 105는 CI 리팩토링 4스프린트 로드맵(102~105)의 마감 스프린트다. 세 가지 과제로 구성된다:
- [A] rebuild_all 운영 규약 표준화 —
workflow_dispatch.inputs.rebuild_all은 Sprint 103 시점부터 존재하나 언제/누가/어떻게 트리거하는지 규약이 부재했다. 이번 스프린트에서 런북과 PR 템플릿 체크박스로 규약을 제도화한다. - [B] github-worker 실측 강제 수집 — rebuild_all 4회 + dummy touch PR 1회로 Post 5건 확보. sprint-103/104 비교표 "측정 불가¹" 칸을 실수값으로 갱신한다.
- [C] commitlint pre-commit 자동화 — CI 단계에서만 검증하던 commitlint를 로컬 commit 단계로 앞당기고, scope-enum을
services/디렉토리 동적 생성 방식으로 전환해 수동 유지 제거.
목표
docs/runbook/ci-rebuild-all.md신규 작성 — CI 인프라 PR 담당자가 따를 표준 절차 제공.github/pull_request_template.md체크박스 추가 — PR 오픈 시점부터 rebuild_all 계획 여부를 명시하도록 강제- github-worker 잡 Post 실측 5건 수집 → sprint-103/104 비교표 소급 갱신
- root
package.json+ husky commit-msg hook + 동적 scope-enum으로 commitlint 로컬 자동화
작업 요약
| 작업 | 담당 | 상태 | 산출물 |
|---|---|---|---|
| [A] rebuild_all 런북 + PR 템플릿 체크박스 | Architect | ✅ 완료 | docs/runbook/ci-rebuild-all.md, .github/pull_request_template.md |
| [A] Sprint 105 ADR | Scribe | ✅ 완료 | 본 문서 |
| [B] dummy touch PR + rebuild_all 트리거 | Sensei | ✅ 완료 | PR #117 (6f42b0f) + run 24703075569 |
| [B] 실측 집계 + 비교표 소급 갱신 | Sensei | ✅ 완료 | sprint-103.md, sprint-104.md 소급 갱신 |
| [B] Sensei 실측 보고서 | Sensei | ✅ 완료 | ~/.claude/oracle/inbox/sensei-sprint-105-timing.md |
| [C] root package.json + husky + 동적 scope-enum | Architect | ✅ 완료 | package.json, .husky/commit-msg, commitlint.config.mjs (PR #116) |
| [C] git-hooks 런북 | Architect | ✅ 완료 | docs/runbook/git-hooks.md (PR #116) |
| PR 생성/머지 | Postman | ✅ 완료 | PR #115 / #116 / #117 / #118 |
[A] 운영 규약 결정 근거
문제 정의 (Sprint 104 교훈 1)
detect-changes path-filter 최적화는 CI 비용을 절감하는 핵심 설계다. 그러나 이 설계는 CI 인프라 파일 자체를 수정하는 PR에서 역설적 공백을 만든다: 워크플로를 수정해도 그 워크플로가 실행하는 서비스 잡이 skip된다. PR #111(Sprint 103)과 PR #113(Sprint 104) 모두 이 경로로 실패했고, github-worker 실측 Post 데이터는 0건으로 남았다.
결정
workflow_dispatch.inputs.rebuild_all=true는 이미 ci.yml:131-139에 구현되어 있었다. 추가 코드 변경 없이 운영 규약 문서화만으로 표준 프로세스를 수립한다.
규약의 핵심 원칙:
- 발동 조건 3개 명문화:
.github/workflows/*.yml단독 변경 /.github/actions/**composite 변경 /scripts/check-coverage.mjs등 CI 공통 스크립트 변경 - PR 템플릿 체크박스 삽입: PR 오픈 시점부터 rebuild_all 계획 여부를 author가 명시하도록 강제 (사후 누락 방지)
- 금지 사례 명문화: 서비스 코드 변경 PR에서 남용 시 GHA 비용 낭비 발생 → path-filter로 충분함을 명시
대안 비교
| 방안 | 장점 | 단점 | 선택 여부 |
|---|---|---|---|
| 런북 + PR 템플릿 (채택) | 구현 없음, 즉시 적용 가능, 의도 명시적 | 사람 의존 (체크리스트 기반) | ✅ 채택 |
| path-filter에 CI 파일 경로 추가 | 자동화 | 전 서비스 빌드가 CI PR마다 자동 발생 → 비용 증가 | ❌ 기각 |
별도 ci-infra.yml 워크플로 분리 | 관심사 분리 명확 | 워크플로 파일 분산, 유지보수 복잡도 증가 | ❌ 이월 검토 |
영향 파일 (커밋 6d6233b)
| 파일 | 작업 | 설명 |
|---|---|---|
docs/runbook/ci-rebuild-all.md | 신규 | 용도·발동조건·실행절차·검증·금지사례 5개 섹션 |
.github/pull_request_template.md | 수정 | 인프라 변경 섹션에 rebuild_all 체크박스 1줄 추가 |
[B] 측정 완료 결론
Sprint 103 파일럿부터 Sprint 105까지 3스프린트에 걸쳐 이월됐던 github-worker 실측이 최종 완료됐다. PR #117(6f42b0f)의 더미 앵커 주석으로 detect-changes를 트리거한 자연 런 2건(run 24702740418·24702828670)과 workflow_dispatch(rebuild_all=true) 합성 런 1건(run 24703075569)을 합쳐 Post n=3을 확보했으며, Pre n=4 대비 Quality +0.4% / Audit -8.9% / Test +3.9%로 전 잡이 ±10% 실용 임계 이내였다. Welch t-test 결과 3잡 모두 |t_obs| < 0.7 (t_crit=2.776) — composite action 확산은 github-worker 개별 잡 런타임에 측정 가능한 영향을 미치지 않음이 확인됐다. sprint-103.md·sprint-104.md 비교표의 측정 불가¹ 셀은 실측 평균으로 소급 갱신됐으며, CI 리팩토링 4스프린트(102~105) 로드맵의 모든 측정 의무가 이로써 종결된다.
[C] commitlint 자동화 결정 근거
문제 정의
Sprint 105 이전까지 commitlint는 CI의 wagoid/commitlint@v6 잡에서만 검증됐다. 개발자가 잘못된 scope/type으로 commit하면 PR 제출 후에야 발견되어 force-push로 재작성해야 했다. 또한 commitlint.config.mjs:18-26의 scope-enum 16개는 정적 하드코딩이라 새 서비스 디렉토리를 추가할 때마다 누락되기 쉬웠다 (feedback-commitlint-scope.md 피드백의 반복 원인).
결정
husky + commit-msg hook + 동적 scope-enum. 대안 비교:
| 방안 | 장점 | 단점 | 선택 여부 |
|---|---|---|---|
| husky + commitlint (채택) | root 단일 설정, 분산 monorepo 자연스러움, ESM config 재사용 | root package.json 신규 필요 | ✅ 채택 |
| lefthook | Go 바이너리로 경량 | 각 서비스 디렉토리에 lefthook.yml 분산 필요, Node 환경과 이질 | ❌ 기각 |
| pre-commit (Python) | 범용 | Python 도구 추가 → Node 중심 레포에 이질 | ❌ 기각 |
scope-enum 동적 생성
fs.readdirSync('./services', { withFileTypes: true }) + isDirectory() 필터로 런타임에 서비스 목록을 생성. 정적 scope 10개(ci, docs, blog, frontend, infra, deps, security, adr, e2e, runbook)와 병합 후 .sort(). 이로써 새 서비스 디렉토리 생성만으로 scope가 자동 등록된다. feedback-commitlint-scope.md의 "새 디렉토리 추가 시 scope-enum도 함께 등록"이라는 사람 의존 피드백이 구조적 자동화로 승격됐다.
CI 영향
root package.json 추가에도 기존 CI 잡은 모두 working-directory 지정 또는 composite action 경유라 영향 없음 (PR #116 전체 잡 SUCCESS로 검증).
영향 파일 (커밋 0b916cf)
| 파일 | 작업 | 설명 |
|---|---|---|
package.json | 신규 | root devDependencies: @commitlint/cli + config-conventional + husky |
.husky/commit-msg | 신규 | npx --no -- commitlint --edit "$1" |
commitlint.config.mjs | 수정 | scope-enum 정적 16개 → 동적 services/ + static 10 |
docs/runbook/git-hooks.md | 신규 | 설치·트러블슈팅·CI 영향 분석 |
레퍼런스
- Sprint 104 ADR:
docs/adr/sprints/sprint-104.md§주요 교훈 1 - Sprint 104 ADR:
docs/adr/sprints/sprint-104.md§이월 항목 - rebuild_all 런북:
docs/runbook/ci-rebuild-all.md - 승인된 Sprint 105 실행 계획:
/Users/leokim/.claude/plans/eventual-hugging-cocke.md - 채널톡 CI 리팩토링: https://channel.io/ko/team/blog/articles/backend-ci-refactoring-73fca77d
- Sensei Sprint 104 측정 보고서:
~/.claude/oracle/inbox/sensei-sprint-104-timing.md - Sensei Sprint 105 최종 측정 보고서:
~/.claude/oracle/inbox/sensei-sprint-105-timing.md