핵심 요약
- OpenAI가 2026년 11월 2일 Scaling Git at OpenAI 글에서 사내 모노레포(Monorepo)의 Git 백엔드를 자체 개발한 Pando로 바꿨다고 밝혔습니다. Git 프로토콜과 클라이언트 호환성은 유지한 채 서버 쪽을 다시 만들었습니다.
- OpenAI에 따르면 전환 후 중간값(median) push 지연이 약 80% 줄었고 병합 신뢰성이 좋아졌습니다. Pando는 하루 약 1PB의 Git 데이터를 전송하고, 한 시간에 57TB 이상을 보낸 적도 있습니다.
- 핵심 설계는 두 가지 포기입니다. 저장소 전체의 시점 일관성 대신 브랜치(ref) 단위 일관성만 보장하고, 클라이언트마다 packfile을 새로 만드는 대신 push 때 받은 packfile을 다른 클라이언트에 그대로 다시 보냅니다.
- OpenAI는 Codex로 착수부터 운영 투입까지 10주 만에 마쳤고, 2026년 4월부터 운영 트래픽을 받고 있습니다. 설계는 엔지니어 한 명이, 구현은 에이전트 팀이 맡았습니다.
- Pando 자체는 아직 공개되지 않았습니다. Git 클라이언트 개선은 openai/git 저장소와 패치 추적 페이지로 공개하고 업스트림에 기여합니다. Git을 아예 대체한 Anthropic Scion과 대비되는 선택입니다.
OpenAI Pando 소개
Git은 클론마다 전체 이력을 갖는 분산 버전 관리 시스템이고, 개발자들은 20년 넘게 Git을 중심으로 도구를 맞춰 왔습니다. 그러나 회사 전체 코드를 한 저장소에 두는 모노레포(Monorepo) 에 코딩 에이전트가 더해지면, Git 서버가 감당해야 하는 push와 fetch의 양이 사람이 일하던 속도와는 다른 수준으로 늘어납니다. OpenAI는 Codex가 엔지니어 한 명이 동시에 진행하는 작업 수를 늘렸고, 그만큼 브랜치와 push와 병합, 그리고 개발 환경과 연구 작업과 CI에서 오는 fetch와 clone이 함께 늘었다고 설명합니다. 한 엔지니어가 CI를 기다리는 변경을 여러 개 동시에 갖게 되고, push 한 번마다 같은 commit을 받는 CI 작업이 여러 개 생깁니다.
OpenAI에 따르면 2025년 말부터 모노레포를 받치던 시스템이 이 부하를 따라가지 못했습니다. fetch와 push가 느려지고 병합이 실패했으며, 신뢰성이 한때 90% 아래로 떨어졌습니다. 여기서 OpenAI가 던진 질문은 Git 자체의 한계인가, 아니면 모노레포를 서비스하는 방식의 한계인가였습니다. OpenAI는 Git을 유지한 채 서비스 방식을 바꾸는 길을 택했습니다. 엔지니어와 에이전트가 쓰는 Git 워크플로우는 그대로 두기로 했습니다. 대신 서로 다른 브랜치로 향하는 push를 병렬로 처리하고, 같은 이력을 많은 독자에게 동시에 보낼 수 있도록 백엔드만 다시 만들기로 했습니다. Git을 기반으로 유지하면 클라이언트 개선을 OpenAI 밖에서도 쓸 수 있다는 점도 이유였습니다.
이번에 소개하는 Pando 는 그렇게 만든 Git 저장소용 새 백엔드이며, 글은 OpenAI의 Aaron Friel, Taylor Blau, Ted Nyman이 썼습니다. 목표는 두 가지였습니다. 여러 브랜치로 동시에 들어오는 push에 맞춰 쓰기를 수평 확장하는 것, 그리고 클라이언트가 자기 네트워크 대역폭을 전부 쓸 만큼 빠르게 데이터를 내려받도록 읽기 처리량을 최대로 높이는 것입니다. OpenAI는 이 목표를 Git 프로토콜과 클라이언트 호환성을 유지한 채 달성했고, 지금은 OpenAI 모노레포의 모든 개발이 Pando 위에서 돌아간다고 밝혔습니다.
같은 문제를 다른 방식으로 푼 사례가 최근에 있었습니다. Anthropic은 2026년 10월 하루 3만 건 병합을 감당하기 위해 Git을 자체 시스템 Scion으로 대체했다고 밝혔습니다. Scion은 클라이언트가 항상 서버에 연결돼 있다고 가정하고 commit과 rebase를 서버에서 처리하는, Git과 다른 저장 형식의 시스템입니다. 반면 Pando는 Git의 객체 형식과 전송 프로토콜을 그대로 쓰고, 그 위에서 서버가 무엇을 보장하고 무엇을 포기할지를 바꿨습니다. 이 글은 원문의 순서를 따라 Git의 저장 구조, 기존 분산 Git 서비스 방식의 한계, Pando의 설계와 구축 과정, Git 프로젝트에 기여한 내용을 정리하고, 마지막에 Scion과의 차이를 표로 비교합니다.
Git 저장소의 두 요소: 객체와 참조
Pando의 설계를 이해하려면 Git 서버가 동기화해야 하는 두 가지, 객체(Object) 와 참조(Reference, ref) 를 먼저 구분해야 합니다. Git 저장소는 파일의 스냅샷과 그 이력을 객체 그래프로 기록합니다. 객체는 blob, tree, commit, tag 네 종류입니다. blob은 파일 하나의 내용을 담고, tree는 이름을 blob이나 다른 tree에 연결해 디렉터리 구조를 만듭니다. commit은 루트 tree 하나와 0개 이상의 부모 commit을 가리켜 이력을 만듭니다.
객체는 종류와 내용의 해시로 식별되며 불변입니다. 파일이 바뀌면 새 blob이 생기고, 바뀌지 않은 파일과 디렉터리는 기존 객체를 다시 씁니다.
위 그림에서 브랜치 refs/heads/main은 commit C2를 가리키고, C2의 부모는 C1입니다. 두 commit의 루트 tree는 parser.py에 대해서는 서로 다른 blob(B1, B2)을 가리키지만, 바뀌지 않은 docs/ 디렉터리는 같은 tree T3를 공유합니다. 브랜치와 태그는 commit을 가리키는 참조입니다. 브랜치에 commit하면 새 commit이 생기고, 브랜치의 ref가 그 commit으로 옮겨집니다.
객체는 두 가지 상태로 저장됩니다. 느슨한(loose) 객체는 객체 ID를 이름으로 하는 개별 파일이고, 묶인(packed) 객체는 packfile 하나에 여러 객체를 모아 둔 것입니다. packfile 안에서는 비슷한 객체를 다른 객체에 대한 델타(delta)로 저장할 수 있어 공간이 줄어듭니다.
fetch와 push는 이 객체와 참조를 양방향으로 옮기는 작업입니다. fetch에서 클라이언트는 서버에 원하는 commit(want)과 이미 가진 commit(have)을 알려 줍니다. 서버는 원하는 commit에서 도달 가능한(Reachable) 객체, 즉 부모와 tree와 blob을 따라가며 찾을 수 있는 객체를 모은 뒤 클라이언트가 이미 가진 것을 빼고 나머지를 packfile로 보냅니다. push는 반대 방향입니다. 클라이언트는 서버가 광고(advertise)한 ref 목록을 보고 서버가 이미 가진 객체를 제외한 packfile을 만들어 보내며, 서버에 ref 갱신을 요청합니다. 그래서 push로 받은 packfile만으로는 새 이력을 복원할 수 없고, 서버에 이미 있는 객체에 의존합니다.
Git 저장소를 여러 서버에 복제하려면 객체와 참조를 모두 여러 서버에서 쓸 수 있게 유지해야 합니다. 복제본이 참조의 새 값을 서비스하려면 그 값에서 도달 가능한 객체를 먼저 갖고 있어야 합니다. 또 같은 브랜치를 같은 이전 끝(tip)에서 서로 다른 새 commit으로 옮기려는 push들, 즉 경쟁하는 참조 갱신도 조정해야 합니다. OpenAI가 지적하는 문제는 여기서 나옵니다. 저장소의 모든 쓰기에 하나의 순서를 매기는 시스템에서는 서로 관계없는 브랜치로 가는 push끼리도 서로를 기다리게 됩니다.
기존 분산 Git 서비스 방식의 한계: 3단계 커밋과 미리 쓰기 로그
OpenAI는 Pando를 설계하면서 Git을 확장하는 일반적인 두 가지 방식을 모델링해 비교했습니다. 하나는 저장소 복제본 사이의 ref 갱신을 3단계 커밋(Three-Phase Commit, 3PC) 으로 조정하는 방식이고, 다른 하나는 블롭 저장소(Blob Storage)에 둔 공유 미리 쓰기 로그(Write-Ahead Log, WAL) 로 갱신 순서를 정하는 방식입니다.
3PC 방식에서는 여러 복제본이 저장소 전체 사본을 갖습니다. 어느 서버가 push를 받으면 들어온 packfile을 모든 복제본에 병렬로 복사하고, 복제본의 과반이 ref 갱신을 받아들여야 push가 공개됩니다. 각 복제본은 자기 ref를 잠그고 클라이언트가 기대한 commit을 아직 가리키는지 확인하며, 조정자(Coordinator)는 사전 커밋 메시지와 실제 갱신 지시를 여러 차례 주고받습니다. 모든 복제본이 전체 사본을 가지므로 읽기는 로컬에서 처리할 수 있고 어느 복제본을 골라도 참조가 일관되게 보입니다. 대신 참조는 한 번에 하나씩 갱신되고, push마다 복제본 사이의 왕복이 여러 번 필요합니다. 쿼럼(Quorum)을 기다리는 동안 복제본의 디스크 성능과 통신 지연이 push 경로에 그대로 더해지고, 쓰기가 늘수록 복제본은 들어오는 pack과 읽기 트래픽을 동시에 감당해야 합니다.
WAL 방식에서는 서버가 push를 받으면 packfile을 블롭 저장소에 올리고, 저장소 전체의 갱신 순서를 기록하는 공유 매니페스트(Manifest)에 ref 갱신과 packfile 위치를 적습니다. 매니페스트 교체는 CAS(Compare-and-Swap, 값이 예상과 같을 때만 바꾸는 원자적 갱신) 로 이뤄집니다. 그 사이 다른 서버가 먼저 갱신했으면, 서버는 중간 항목을 읽고 자기 갱신이 아직 유효한지 확인한 뒤 이미 올린 packfile로 재시도합니다.
packfile 업로드는 병렬로 되지만, 관계없는 브랜치로 가는 push도 같은 매니페스트를 갱신해야 합니다. CAS 한 번의 왕복 시간이 저장소가 새 매니페스트를 공개하는 빈도의 상한이 되고, 여러 ref를 한 매니페스트에 묶는 배칭(Batching)은 대기열과 지연을 늘립니다. 블롭 저장소 용량을 늘려도 이 병목은 풀리지 않습니다. 복제본은 블롭 저장소에서 pack을 읽고 색인해야 서비스할 수 있습니다. 쓰기가 그 속도를 넘으면 복제본이 뒤처지고, 클라이언트는 방금 push된 commit을 기다리게 됩니다.
두 방식과 Pando를 나란히 놓으면 다음과 같습니다. Pando 열의 내용은 아래 절에서 설명합니다.
| 항목 | 3단계 커밋(3PC) | 미리 쓰기 로그(WAL) | Pando |
|---|---|---|---|
| 서버가 갖는 것 | 저장소 전체 사본을 복제본마다 보유 | 로컬 사본과 블롭 저장소의 pack, 매니페스트 | 전체 사본 없음. 블롭 저장소의 불변 packfile과 메타데이터 저장소의 ref 버전 |
| push 공개 조건 | 복제본 과반의 승인, 다단계 왕복 | 공유 매니페스트 CAS 성공 | 해당 ref 포인터의 CAS 성공 (다른 ref와 무관) |
| 관계없는 브랜치 push | 참조를 한 번에 하나씩 갱신 | 같은 매니페스트를 두고 경쟁 | 독립적으로 병렬 처리 |
| 저장소 전체 일관성 | 모든 복제본에서 일관된 참조 | 매니페스트가 전체 순서 보장 | 보장하지 않음 (ref 단위 직렬화만) |
| fetch 응답 | 복제본이 로컬에서 packfile 생성 | 복제본이 pack을 읽고 색인한 뒤 생성 | 저장된 packfile을 그대로 재사용, URI 목록 반환 |
| 부하 시 병목 (원문 시뮬레이션) | 디스크 포화로 쓰기 지연 증가 | 저널 읽기 지연으로 읽기 지연 증가 | 수천 클라이언트 동시 push에도 성능 유지 |
Pando의 설계: 두 가지 전제를 포기하다
OpenAI는 Git을 포기하지 않고도 요구 사항을 맞출 수 있다고 봤지만, 대부분의 Git 시스템이 당연한 요구 사항으로 여기는 두 가지는 포기해야 했습니다. 첫째는 저장소 전체 일관성 입니다. 모든 ref의 특정 시점 스냅샷을 제공하려면 저장소 전체에 걸친 조정이 필요하고, 그 조정 지점 하나에서 관계없는 브랜치의 push가 서로 경합합니다. 둘째는 클라이언트마다 고유한 packfile 입니다. 로컬 이력이 다른 두 클라이언트가 같은 브랜치를 fetch하면, 서버는 각자가 이미 가진 객체를 빼기 위해 서로 다른 pack을 만들어야 합니다. 이 응답 생성에는 CPU와 디스크 I/O가 들고, 독자가 많아질수록 확장이 어렵습니다.
Pando는 그 대신 쓰기를 확장하기 위해 완화된 일관성 모델을, 읽기를 확장하기 위해 packfile 재사용을 택했습니다.
인과적 일관성: ref마다 독립된 버전 기록
클라이언트가 브랜치에 push하면 Pando는 들어온 packfile을 불변 블롭으로 블롭 저장소에 저장합니다. 브랜치가 움직일 때마다 메타데이터 저장소에는 ref 버전(ref version) 이 하나 기록됩니다. ref 버전은 새 끝 commit, 그 commit을 공급한 pack, 그리고 그 pack이 의존하는 이전 ref 버전들을 담습니다. 블롭 저장소와 메타데이터 저장소는 모두 수평 확장이 가능합니다.
commit이나 참조를 fetch한다는 것은 ref 버전들의 집합, 곧 packfile들을 클라이언트에 재생(replay)해서 그 ref 버전을 만든 클라이언트의 상태를 다시 구성하는 일입니다. 이 방식은 저장소 전체에 대해서는 약한 일관성을 주지만, 개별 ref의 갱신에 대해서는 직렬화 가능성(Serializability)을 보장합니다. 클라이언트끼리 충돌하는 경우는 같은 ref에 동시에 push할 때뿐입니다. 대신 여러 브랜치를 읽는 클라이언트는 그 읽기 결과가 저장소의 한 시점을 나타낸다고 가정할 수 없습니다.
위 그림은 trunk 브랜치와 topic 브랜치가 Pando에 어떻게 기록되는지 보여줍니다. trunk로 가는 push는 commit 한 개 이상을 담은 증분 pack을 하나 더합니다. 반면 측면 브랜치(topic)로 가는 push는 그 브랜치의 이전 commit들을 다시 포함합니다. 그래서 광고된 trunk 버전을 가진 클라이언트라면 topic 브랜치를 pack 하나로 받을 수 있습니다.
이것이 OpenAI가 말하는 인과적 일관성(Causal Consistency) 입니다. 참조를 fetch하는 독자는 그 참조를 만든 작성자의 이력을 관찰하게 됩니다. push 과정에서는 Pando가 클라이언트와 서버가 합의하는 공유 이력을 통제해, 클라이언트가 공유하기 쉬운 packfile을 만들도록 합니다.
그 결과 Pando는 Git 작업 중에 모든 참조의 한 시점 상태나 clone 안에서의 ref 갱신 순서를 제공하지 않습니다. 원문의 예를 들면, 전체 clone을 협상하는 동안 브랜치 foo와 bar가 모두 갱신됐을 때 한 클라이언트는 foo 버전 1과 bar 버전 2를, 다른 클라이언트는 foo 버전 2와 bar 버전 1을 볼 수 있습니다. OpenAI는 실제로 사용자와 에이전트가 ref 갱신의 전역 순서에는 관심이 없고 참조 하나의 갱신 순서에만 의존한다고 설명합니다.
1,000개 클라이언트 시뮬레이션
원문에는 세 가지 일관성 모델을 비교하는 인터랙티브 시뮬레이션이 있습니다. 클라이언트 1,000개가 각자 다른 브랜치를 골라 고유한 commit을 반복해서 push하고, 전체 소요 시간과 push에서 fetch까지의 지연을 측정합니다. 후자는 사용자와 에이전트가 서로 협업하거나 버전 관리에 의존하는 다른 시스템을 쓸 때의 왕복 시간이라 OpenAI가 중요하게 보는 지표입니다. 하드웨어는 범용 가상 머신부터 고급 가상 머신과 블롭 저장소까지 선택할 수 있고, 3PC는 저장소 전체 일관성을 완화한 조건으로 모델링했습니다.
OpenAI가 밝힌 결과는 다음과 같습니다. 3PC 시스템은 부하가 커지면 디스크가 포화되면서 쓰기 지연이 크게 늘고, WAL 시스템은 서버가 저널을 읽는 속도를 따라가지 못해 읽기 지연이 크게 늘었습니다. Pando는 모노레포에서의 실제 테스트와 이 시뮬레이션 양쪽에서 수천 개 클라이언트가 동시에 push해도 부하에 따른 성능 저하가 없었다고 합니다. 다만 위젯에는 합성 교육용 모델이며 운영 벤치마크가 아니라는 안내가 표시되어 있으며, 구체 수치는 원문의 위젯에서 직접 볼 수 있습니다.
Pando 서버가 가벼운 이유는 하는 일이 적기 때문입니다. push를 받으면 들어오는 packfile을 로컬 저장소에 풀지 않고 블롭 저장소로 스트리밍하면서 검증합니다. fetch가 시작되면 독자에게 필요한 저장된 pack을 고르고, 독자가 그것을 내려받습니다. 어떤 서버도 packfile을 로컬 저장소에 적용하거나 비용이 큰 unpack과 repack을 수행하지 않습니다. 서버는 주로 협상과 packfile 선택만 하므로 범용 하드웨어에서 돌릴 수 있고, 확장의 한계는 클라이언트, 클라이언트와 Pando 사이의 네트워크, 블롭 저장소 서비스가 정합니다.
push 경로: 광고하는 ref를 trunk 하나로 줄이다
push 한 번의 흐름은 이렇습니다. 에이전트가 파일을 고치고 로컬에서 commit한 뒤 git push를 실행하면 클라이언트가 변경을 담은 packfile을 만듭니다. Pando는 그 pack을 받아 블롭 저장소로 스트리밍하고, 한 번의 디코딩 패스로 검증한 뒤 다중 키 트랜잭션으로 메타데이터 저장소에 ref 버전을 기록하고 ref 포인터를 원자적으로 갱신합니다. 이 덕분에 자기가 쓴 것을 바로 읽을 수 있는 읽기 일관성(read-your-own-write)이 보장됩니다. 쓰기 작업 전체에 필요한 메타데이터 읽기와 쓰기는 O(1) 입니다.
여기서 중요한 선택이 하나 있습니다. 일반적인 Git 서버는 push하는 클라이언트에게 자기가 가진 모든 브랜치를 광고하고, 클라이언트는 그 정보를 바탕으로 서버가 이미 가진 객체를 제외한 packfile을 만듭니다. 원문은 이를 패를 모두 펼쳐 보이는 포커 선수에 비유합니다. 광고하는 ref가 많을수록 pack은 작아지지만, 다른 클라이언트가 그 pack에서 빠진 객체를 갖고 있지 않을 수 있어 pack을 재사용하기 어려워집니다. 반대로 ref를 하나도 광고하지 않으면 클라이언트는 저장소 전체 이력을 담은 packfile을 만들게 되어, 어느 클라이언트든 쓸 수 있지만 브랜치 하나를 fetch하는 일이 사실상 전체 clone이 됩니다.
Pando는 push하는 클라이언트에게 선별된 일부 브랜치만 광고합니다. 이유는 두 가지입니다. 첫째, 모든 ref의 일관된 뷰를 제공하는 비용이 큽니다. 브랜치가 수백만 개면 ref 광고만으로 100MiB를 넘을 수 있고, 이를 위해 서버마다 현재 매핑을 유지하거나 ref 수에 비례하는 데이터베이스 질의를 해야 합니다. 둘째, 클라이언트에게 ref의 일부만 주면 클라이언트는 서버가 명시적으로 제외를 허용한 것에만 의존하는 pack을 만듭니다. Pando는 그 의존성을 추적해 한 push에서 받은 packfile을 다음 fetch의 응답으로 다시 쓸 수 있습니다.
기본값으로 Pando는 새 기능 브랜치를 push할 때 지정된 trunk 브랜치 하나만 기준으로 광고합니다. 저장소에 브랜치가 늘어도 광고 크기가 같게 유지되지만 대가도 있습니다. 한 브랜치에 여러 번 push하거나 기능 브랜치 위에 다른 기능 브랜치를 쌓으면, 클라이언트는 trunk 밖의 내용을 매번 다시 보내야 합니다. 그래서 연속된 브랜치 push는 중복 객체를 담아 커지고 클라이언트 대역폭을 더 씁니다. OpenAI 모노레포에서 이렇게 만들어진 packfile의 중간값은 20KiB 미만, 99번째 백분위는 3MiB 미만이었습니다. 광고된 trunk 이력을 가진 독자가 pack 하나로 브랜치를 받을 수 있으므로 OpenAI는 이를 합리적인 트레이드 오프(Trade-off)로 봤습니다.
메타데이터 갱신은 동기와 비동기 부분으로 나뉩니다. 동기 갱신은 새 ref 버전을 쓰고 ref 포인터를 거기로 옮겨, 클라이언트가 방금 갱신된 commit을 바로 fetch할 수 있게 합니다. 컴팩션 예약 같은 비동기 작업은 같은 트랜잭션에 기록만 해 둡니다. 아주 큰 push에서는 commit의 일부만 동기적으로 쓰기 때문에, push 크기와 관계없이 메타데이터 저장소 읽기와 쓰기 수가 상수로 유지됩니다. 경합하는 키는 ref 포인터 하나뿐이고 이것은 CAS와 비슷한 원자 연산으로 보호합니다. 쓰기 처리량을 더 늘리려면 Pando 서버, 메타데이터 저장소의 확장 단위, 블롭 저장소를 더하면 됩니다.
fetch 경로: packfile-uri와 지역 캐시 Express
fetch에서 클라이언트는 have와 want 두 집합의 commit ID를 보냅니다. 일반적인 Git 서버는 두 집합에서 도달 가능한 객체의 차집합을 계산하고 압축해서 보냅니다. 오픈소스 Git 서버는 이를 가속하는 여러 로컬 색인을 갖고 있지만, 그래도 이 packfile은 계산 비용이 크고 캐시하기 어렵습니다. Pando는 push 때 기록해 둔 commit 매핑으로 have와 want를 그 commit을 담은 ref 버전들로 해석하고, 각 ref 버전이 가리키는 기존 packfile 중에서 클라이언트에게 필요한 객체를 덮는 집합을 고릅니다. 측면 브랜치를 원한다는 것은 그 브랜치가 의존하는 trunk 버전까지 원한다는 뜻이므로, 빠진 trunk 의존성도 함께 선택됩니다. 이 선택에 필요한 메타데이터 읽기는 O(\log \Delta) 이며, 여기서 \Delta 는 클라이언트가 가진 것과 원하는 것 사이의 가장 짧은 ref 버전 거리입니다.
Git 프로토콜은 clone이나 fetch의 HTTP 응답에 packfile 하나만 실어 보낼 수 있습니다. 그런데 Git 프로토콜에는 잘 알려지지 않은 기능인 packfile-uri가 있어, 서버가 추가 pack을 따로 내려받을 수 있는 링크를 돌려줄 수 있습니다. Pando는 이 기능만 사용하고 응답 본문에는 빈 packfile을 넣습니다. OpenAI는 이 기능을 지원하기 위해 packfile-uri 관련 개선 여러 건을 업스트림 Git에 기여했습니다.
OpenAI 시스템은 여러 지역에서 운영되므로, 지역마다 로컬 캐시를 둔 Pando 클러스터를 유지합니다. pack 전달 서비스 Express 가 블롭 저장소를 캐시하고, 별도 서비스가 메타데이터 저장소를 캐시합니다. 이 캐시 덕분에 commit ID 요청이나 ref의 특수 읽기를 그 클러스터의 캐시 상태만으로 처리할 수 있습니다. packfile 요청은 일관된 해싱(Consistent Hashing)으로 Express 서버에 라우팅하며 캐시 적중률은 99%를 넘습니다. OpenAI는 표준 클라우드 가상 머신만으로 clone과 fetch가 10Gbps 네트워크 링크를 포화시키는 것을 확인했다고 밝혔습니다.
컴팩션: LSM 트리 방식의 L0부터 L4까지의 packfile cover
대부분의 Git 서버는 저장소가 커질수록 성능을 유지하기 위해 repack과 가비지 컬렉션(Garbage Collection)을 돌립니다. 둘 다 공간을 회수하지만 연산과 I/O 비용이 큽니다. Pando의 문제는 조금 다릅니다. OpenAI 모노레포처럼 빠르게 움직이는 저장소에서는 마지막 fetch 이후 일어난 push마다 packfile URI를 하나씩 보내는 것이 불가능합니다. 그렇게 하면 클라이언트가 trunk를 따라잡기 위해 하루에 수만 개의 packfile을 내려받아야 합니다.
그래서 Pando는 로그 구조 병합 트리(Log-Structured Merge-tree, LSM 트리)의 컴팩션(Compaction) 과 비슷한 설계로 pack을 백그라운드에서 합칩니다. push 하나는 Pando가 전송할 수 있는 가장 작은 단위인 L0 packfile을 만듭니다. 백그라운드 워커가 이 packfile들을 ref 버전의 연속 구간을 덮는 cover로 모으고, cover의 크기는 L0에서 기하급수적으로 커집니다. 현재 OpenAI 모노레포는 L4 cover까지 씁니다.
cover의 역할은 두 가지입니다. cover가 충분히 차면 컴팩션 워커가 그것을 가져가 packfile 하나로 만드는데, 안의 객체를 다시 배치하므로 압축률이 좋아집니다. 동시에 cover는 ref 버전 위의 스킵 리스트(Skip List)처럼 동작해 fetch 협상 성능을 높입니다. 각 레벨의 색인을 동시에 훑으면 Pando는 클라이언트에게 보낼 pack 집합을 로그 시간에 고를 수 있습니다.
많은 Git 서버와 달리 Pando는 모든 레벨의 packfile을 버리거나 가비지 컬렉션하지 않고 그대로 둡니다. 모든 레벨의 pack이 fetch의 have와 want에 따라 계속 클라이언트 서비스에 쓰이고, Pando를 API로 쓰는 클라이언트가 임의 객체 하나를 읽을 때는 압축이 덜 된 L0에서 읽는 편이 L4보다 데이터를 적게 읽습니다. OpenAI는 컴팩션 덕분에 클라이언트에게 보내는 총 전송량이 크게 줄고, pack 계획이 클라이언트가 뒤처진 정도에 대해 선형보다 느리게 늘어난다고 설명합니다.
구축과 배포: Codex로 10주, 프록시로 무중단 전환
OpenAI는 Pando를 Codex로 만들었고, 착수부터 운영 투입까지 10주가 걸렸습니다. Pando의 핵심은 엔지니어 한 명이 설계했고, 구현은 에이전트 팀이, 배포는 소수의 엔지니어가 맡았습니다. Pando는 2026년 4월부터 운영 트래픽을 받기 시작했으며, OpenAI가 쓰는 더 큰 소스 관리 도구 체계의 한 부분입니다.
검증 방법은 여러 겹입니다. OpenAI는 더 안전한 소프트웨어 기반을 만들기 위한 원칙을 적용했고, 새로 시작하는 프로젝트였으므로 Rust로 기존 의존성 없이 구현했습니다. 에이전트가 자기 변경을 표준 Git 동작과 대조해 시험할 수 있도록 적합성 테스트(Conformance Test) 스위트를 만들었습니다. 또 시스템의 불변식과 속성을 확인하는 결정론적 시뮬레이션 테스트(Deterministic Simulation Testing) 하네스를 개발해, 협상과 pack 계획에서 미묘한 경쟁 조건(Race Condition)과 회귀를 찾아 고쳤습니다.
모델도 여럿이 참여했습니다. 새 모델이 나올 때마다 Pando의 성능과 신뢰성 개선에 썼고, GPT-6 Astra를 쓰는 에이전트는 Lean과 TLA+로 Pando의 이론을 형식화했습니다. OpenAI는 이것으로 구현의 버그를 찾아 고치고 시스템의 속성을 증명했다고 밝혔습니다. 연속 세션 여러 개가 수백 시간 동안 Pando의 경계 사례를 찾아 고쳤고, Daybreak 수준의 능력을 가진 모델을 쓰는 에이전트가 Git과 Pando를 상시 레드팀(Red Team)합니다. Daybreak은 OpenAI가 프런티어 사이버 모델과 Codex Security, 파트너 생태계를 묶어 운영하는 사이버 방어 제품군이며, Astra 발표 정리 글에서 소개한 바 있습니다.
프록시로 시작한 전환
첫 배포는 기존 소스 관리 시스템 앞에 둔 읽기와 쓰기 통과(read- and write-through) 프록시였습니다. Pando와 이전 시스템을 동기화 상태로 유지하면서 다운타임 없이 트래픽을 옮길 수 있었습니다. Pando의 캐시 설계는 프록시하기 전에 요청을 중복 제거하고 합칠 수 있어서, 시스템을 하나씩 옮기는 동안 기존 도구가 정상 상태로 유지됐습니다. 더 많은 워크로드가 Pando로 옮겨 올수록 그 push가 Pando의 캐시를 채웠고, 이전 백엔드의 신뢰성도 함께 좋아졌습니다.
클라이언트 쪽에서는 OpenAI의 공개 Git 배포판을 개발자 기기와 ChatGPT 데스크톱 앱 안에 배포하기 시작했고, Git CLI를 감싼 사내 래퍼(Wrapper)로 클라이언트를 단계별로 옮겼습니다. 변경 요청, 코드 리뷰, 자동화용 API를 다루는 도구를 여럿 만들었고, 레거시 API와 웹훅과 저장소 다운로드에 의존하던 통합 수백 개를 Git 트래픽과 함께 이전했습니다. Codex도 이전을 도왔습니다. 기존 체크아웃을 준비하는 스킬과 에이전트가 새 시스템을 쓰도록 안내하는 스킬을 만들어, 개발자가 Codex에게 개발 환경과 서비스의 이전을 맡길 수 있었습니다.
OpenAI가 밝힌 전환 결과는 다음과 같습니다.
| 지표 | 수치 |
|---|---|
| 중간값 push 지연 | 약 80% 감소 (약 5분의 1) |
| 병합 신뢰성 | 개선 (구체 수치 없음) |
| 하루 Git 데이터 전송량 | 약 1PB, 소수의 CPU 코어로 처리 |
| 한 시간 최대 전송량 | 57TB 이상, 그중 99% 이상이 로컬 디스크 캐시에서 |
| Express 캐시 적중률 | 99% 이상 |
| clone과 fetch 처리량 | 표준 클라우드 VM에서 10Gbps 링크 포화 |
이 수치는 모두 OpenAI가 자사 모노레포 하나에서 측정해 밝힌 값이며, 측정 기간과 이전 시스템의 절대 지연 같은 비교 기준은 원문에 없습니다. OpenAI는 Pando가 저장소 여러 개를 지원하도록 설계됐고, 수요가 늘면 데이터 전달과 Git 협상을 독립적으로 확장할 수 있다고 설명합니다.
Git 프로젝트에 되돌려준 것: openai/git과 패치 50건
Git 프로토콜과 클라이언트 위에 Pando를 만든 덕분에 Git 자체의 버그와 성능 개선 지점도 드러났습니다. Pando는 재사용 가능한 pack을 클라이언트에 직접 보내므로, 그 pack을 내려받고 색인하는 과정이 시스템 속도와 신뢰성의 중심이 됐습니다. 이 과정에서 동시 다운로드, 중단된 전송 뒤의 정리, 이미 완료된 다운로드의 재개에서 경계 사례가 드러났습니다. OpenAI는 이 경로들을 고치고 fetch에서 기존 pack을 받아들일 때의 검증을 더해 업스트림에 기여했습니다. 느린 fetch가 pack 생성에 시간을 쓰는지 전송에 쓰는지 구분하기 위해 packfile-uri 다운로드 추적과 pack 생성 바이트 수 계측도 추가했습니다.
OpenAI의 Git 빌드에서는 클라이언트가 독립적인 pack 여러 개를 병렬로 내려받고 색인할 수 있습니다. 또 명시적 have(explicit haves) 개념을 더해, 서버가 브랜치의 현재 끝을 push 클라이언트가 pack에서 뺄 수 있는 이력과 별도로 광고할 수 있게 했습니다. Pando에서는 이 덕분에 클라이언트가 --force-with-lease로 기능 브랜치가 움직이지 않았는지 확인하면서 pack은 trunk만 기준으로 만들 수 있고, 그 trunk 이력을 가진 누구나 같은 pack으로 브랜치를 fetch할 수 있습니다.
OpenAI는 이 개선 중 여러 건이 이미 업스트림 Git에 들어갔고, 나머지는 공개 저장소에 있다고 밝혔습니다. 패치 추적 페이지는 2026년 10월 31일 확인 기준으로 업스트림 대상 패치 50건을 나열하며, 각 패치가 업스트림의 master, next, seen 브랜치 중 어디에 있는지 표시합니다. 공개 빌드는 저장소의 codex 브랜치에 있습니다.
Anthropic Scion과 OpenAI Pando: 같은 문제, 다른 답
두 회사는 모두 코딩 에이전트 때문에 모노레포 소스 관리가 병목이 됐다는 같은 출발점에서 시작했습니다. Anthropic 글을 정리한 커뮤니티 글과 OpenAI 원문을 대조하면 차이는 다음과 같습니다.
| 항목 | Anthropic Scion | OpenAI Pando |
|---|---|---|
| Git과의 관계 | Git을 대체. 자체 저장 형식, packfile 없음 | Git 프로토콜과 클라이언트 유지. 서버 백엔드만 교체 |
| 클라이언트 전제 | 항상 서버에 연결된 에이전트를 전제로 commit, rebase, 병합을 서버에서 처리 | 표준 Git 클라이언트(OpenAI 빌드)가 로컬에서 commit한 뒤 push |
| 서버가 갖는 것 | 저장소 전체 사본이 서버에도 없음. Spanner에 메타데이터 | 전체 사본 없음. 블롭 저장소의 불변 packfile과 메타데이터 저장소의 ref 버전 |
| 참조 갱신 | Spanner 행 하나의 CAS | ref 포인터의 CAS. 저장소 전체는 인과적 일관성 |
| 체크아웃 | sparse 체크아웃과 가상화된 체크아웃이 기본 | 원문에 언급 없음 |
| 개발 기간과 인원 | 7명 팀, 5개월에 이전 완료 | 엔지니어 1명 설계와 에이전트 구현, 10주 |
| 공개 여부 | 비공개. 범용 Git 대체재가 아니라고 밝힘 | 비공개. 사용자와 공유할 방법을 모색 중 |
| 생태계 기여 | 서버 측 API와 sparse 기능 같은 아이디어 공유 | Git 클라이언트 개선 공개, 업스트림 패치 기여 |
두 접근의 차이는 Git의 어디까지를 전제로 삼는가에 있습니다. Scion은 오프라인 클론이라는 Git의 전제 자체를 버렸고, Pando는 저장소 전체 일관성이라는 서버의 전제를 버렸습니다. Anthropic은 Scion이 범용 Git 대체재가 아니라고 밝혔고, OpenAI는 Pando가 자사의 확장 요구에 맞춘 설계라고 설명합니다. Scion의 설계를 Git 서버 위에 구현한 비공식 오픈소스 프로젝트는 gitai 소개 글에서 다뤘습니다.
원문이 밝히지 않은 것과 적용 시 고려할 점
- 직접 쓸 수 없습니다: Pando는 아직 공개되지 않았습니다. OpenAI는 많은 에이전트가 하나의 공유 저장소에서 협업하는 워크로드 등 사내의 다른 용도를 검토 중이며, Pando를 가능하게 한 기술을 사용자와 공유할 방법을 찾고 있다고만 밝혔습니다. 지금 가져다 쓸 수 있는 것은 openai/git의 클라이언트 개선과 업스트림에 들어간 패치입니다.
- 저장소 구성 요소: 블롭 저장소와 메타데이터 저장소가 어떤 제품인지, Pando 서버와 Express 서버가 몇 대인지, 모노레포의 이력 용량과 브랜치 수와 하루 push 수는 원문에 없습니다. 브랜치 수백만 개라는 수치는 ref 광고 비용을 설명하는 예시로 등장합니다.
- 일관성 완화의 영향: 여러 브랜치를 한 시점으로 읽어야 하는 도구가 있다면 인과적 일관성 모델에서 어떻게 동작하는지 따로 검토해야 합니다. 원문은 사용자와 에이전트가 전역 순서에 의존하지 않는다고 설명하지만, 그 근거는 OpenAI 내부 워크플로우입니다.
- 쌓인 브랜치의 비용: trunk만 광고하는 기본 설정에서는 한 브랜치에 반복 push하거나 브랜치를 쌓을수록 클라이언트가 보내는 pack이 커집니다. OpenAI는 중간값 20KiB 미만이라 합리적인 트레이드 오프였다고 밝혔지만, 큰 바이너리를 자주 고치는 저장소에서도 같을지는 원문에 없습니다.
- 비교 대상의 범위: 3PC와 WAL 비교는 OpenAI가 모델링한 설계와 시뮬레이션에 근거합니다. 실제 상용 Git 호스팅 서비스나 오픈소스 Git 서버와의 측정 비교는 원문에 없습니다.
여러분의 팀에서는 코딩 에이전트가 늘면서 Git 서버나 CI에서 어떤 병목을 먼저 겪으셨나요? 댓글로 사례를 나눠 주시면 다른 분들의 판단에 도움이 됩니다.
Scaling Git at OpenAI 블로그 글
https://openai.com/index/scaling-git-at-openai/
OpenAI Git 빌드 GitHub 저장소 (openai/git)
OpenAI Git 패치 추적 페이지 (patches & notes)
더 읽어보기
-
Anthropic Scion: 하루 3만 건 병합을 감당하려 Git을 대체한 버전 관리 시스템 (및 Mononoke와의 출처 표기 논쟁😵)
-
gitai: 한 브랜치에 몰린 코딩 에이전트들의 변경을 서버가 대신 rebase해 반영하는 Git 서버 (Anthropic Scion 설계 참고)
-
OpenAI GPT-6 Astra 출시: 사이버보안 Critical 등급 첫 도달과 낮아진 CoT 모니터링 가능성
-
Path to Astra, OpenAI의 Critical 사이버보안 임계선을 넘은 첫 모델 Astra에 대한 발표
-
OpenAI Codex 팀이 권하는 GPT-6 Astra 전환 준비, 스킬 설명은 좁게 AGENTS.md는 조건부로
-
Gas Town: 20-30개 AI 코딩 에이전트를 안정적으로 조율하는 Git 기반 멀티 에이전트 오케스트레이션 시스템
이 글은 GPT 모델로 정리한 초안을 바탕으로 한 것으로, 원문의 내용 또는 의도와 다르게 정리된 내용이 있을 수 있습니다. 관심있는 내용이시라면 원문도 함께 참고해주세요! 읽으시면서 어색하거나 잘못된 내용을 발견하시면 댓글로 알려주시기를 부탁드립니다. ![]()
이 글은 파이토치 한국 사용자 모임
이 직접 정리한 글입니다. 새 글을 놓치지 않으시려면 텔레그램(Telegram)이나 Slack/Discord/Teams/Dooray/GoogleChat 등으로 알림을 받으시고, 회원으로 가입하시면 주요 글들을 이메일
로도 보내드립니다! ![]()
아래
쪽에 좋아요
를 눌러주시면 새로운 소식들을 정리하고 공유하는데 힘이 됩니다~ ![]()





