에이전트가 각각 자기 브랜치에 푸시하는 일과, 모두 같은 브랜치를 바꾸는 일은 다릅니다. 서버가 수천 개의 푸시를 받아도 같은 기준 커밋에서 출발한 변경이 모두 같은 참조의 다음 값이 될 수는 없습니다.
GitHub의 11월 5일 Rubicon 설명은 내부 시험에서 동시 에이전트 5,000개와 초당 7,200회 푸시를 보고합니다. 11월 8일 확인했으며 독립 측정이나 모든 저장소에 대한 보장으로 해석하지 않습니다.
큰 데이터보다 작은 포인터에 합의가 필요하다
공식 설계에서 pack 데이터는 Azure Blob Storage에, 참조와 pack manifest는 Ref-CAS에 저장됩니다. 가상 복제본은 캐시를 가지며, 쓰기는 pack 업로드 후 참조 트랜잭션으로 이어집니다. 참조 비교·갱신은 quorum으로 확정됩니다. 공식 글의 구조·쓰기 경로 설명을 바탕으로 다시 그린 아래 개념도는 배포 토폴로지나 프로토콜 명세가 아닙니다.
Git push
│
▼
가상 복제본 ── pack 업로드 ──▶ Blob Storage
│ │
│ 객체가 영속화된 뒤 │ 불변 객체
▼ │
Ref-CAS: 예상 참조 확인 + manifest/참조 갱신
│
▼
새 참조를 읽는 클라이언트
여기서 두 비용을 구별할 수 있습니다. 바이트를 저장하고 전달하는 비용은 데이터 양에 민감합니다. 다음 참조 값을 정하는 비용은 어떤 쓰기들이 같은 상태를 건드리는지에 민감합니다. 작업자 수만 세면 두 종류의 병목이 섞입니다.
예상한 이전 값이 틀리면 갱신을 거부한다
Git의 update-ref는 새 값뿐 아니라 예상 이전 객체 ID도 받을 수 있습니다. 다음은 임시 저장소에서 두 작성자가 같은 이전 값을 알고 있을 때의 순서를 보여주는 명령 패턴입니다.
# 설명용 패턴. OID는 해당 저장소에 존재하는 실제 커밋이어야 합니다.
git update-ref refs/heads/demo "$writer_a_oid" "$base_oid"
git update-ref refs/heads/demo "$writer_b_oid" "$base_oid"
첫 갱신이 성공한 뒤 참조는 더 이상 base_oid가 아닙니다. 두 번째 갱신은 거부되어야 이전 결과를 조용히 덮어쓰지 않습니다. 이 비교는 파일 내용이 병합 가능한지 판단하지 않습니다. 서버에서 동일 참조의 새 값을 결정하는 문제입니다.
이를 확인하려고 CodeBridge는 Node.js 18 이상과 로컬 Git으로 빈 임시 저장소를 만들고, 빈 트리의 세 커밋을 생성했습니다. A 갱신 성공, 오래된 기준의 B 갱신 실패, 최종 참조가 A인지를 검사했습니다. 실행 결과:
writer A: accepted; writer B with stale base: rejected; ref still A
Local Git semantics only; not Rubicon or a throughput test.
재현은 이 프로젝트 루트에서 아래 명령으로 실행할 수 있습니다. 실험 파일은 docs/editorial/2026-11-08/evidence/ref-race.mjs에 있으며 외부 서비스를 호출하지 않습니다.
node docs/editorial/2026-11-08/evidence/ref-race.mjs
원격 저장소·사용자 브랜치를 변경하지 않았습니다. 실험은 순차 실행으로 stale-write 거부를 확인하며 실제 분산 경쟁이나 Rubicon 내부 성능을 재현하지 않습니다.
브랜치를 나누면 무엇이 남는가
서로 다른 브랜치로 쓰기를 분산하면 참조의 경쟁은 줄일 수 있습니다. 그러나 동일한 파일·API·스키마를 바꾼 패치는 나중에 통합해야 합니다. 이 지점부터는 저장 계층 밖의 작업입니다.
| 관측할 지연 | 시작과 끝 | 실패를 분리하는 이유 |
|---|---|---|
| 푸시 처리 | 요청 → 서버 수락 | 전송·저장 비용 |
| 참조 갱신 재시도 | 거부 → 새 기준에서 성공 | 같은 참조의 경합 |
| CI 대기 | 큐 진입 → 실행 시작 | 실행 자원 부족 |
| 통합 검증 | 후보 준비 → 회귀 검사 완료 | 코드 의미의 충돌 |
| 사람 검토 | 검토 요청 → 결정 | 검토 처리 능력 |
이 표는 운영 계측 제안입니다. GitHub의 시험에서 측정한 항목이나 결과가 아닙니다. 작업자 수를 늘리기 전에 각 시간을 따로 남겨야, 느린 병합을 저장소 성능 문제로 오진하지 않습니다.
처리량에서 추론할 수 없는 생산성
공식 시험의 저장소 크기, push 크기 분포, 브랜치 집중도와 우리 팀의 조건이 같다고 확인하지 않았습니다. 따라서 7,200으로 우리 작업량을 나눠 용량을 계산할 수 없습니다. 장기 GC 비용과 대규모 변경의 사용자 체감도 이 로컬 실험에서는 알 수 없습니다.
Rubicon에서 가져올 설계 판단은 “에이전트를 5,000개 켜자”가 아닙니다. 큰 불변 데이터와 작은 합의 상태를 구별하고, 팀에서는 참조 경합과 통합 검증을 따로 관측하세요. 서버가 쓰기를 더 많이 받아줄수록, 검토 가능한 변경을 어떤 순서로 합칠지가 다음 제한이 될 수 있습니다.