에이전트는 소스 제어, 파일 시스템, 그리고 지속적인 상태 유지에 관한 우리의 생각 방식 자체를 바꿔 놓았습니다. 개발자와 에이전트는 그 어느 때보다 많은 코드를 생성하고 있습니다. 앞으로 5년 동안 작성될 코드의 양은 프로그래밍 역사 전체를 통틀어 지금까지 작성된 코드의 총량보다 많아질 것이며, 이 흐름은 오늘날의 수요를 감당하기 위해 필요한 시스템 규모를 차원이 다른 수준으로 끌어올렸습니다. 특히 소스 제어 플랫폼은 이런 변화에 버거워하고 있습니다. 이들은 사람이 쓰는 환경을 기준으로 만들어졌지, 잠도 자지 않고, 여러 이슈를 동시에 처리하고, 지치지도 않는 에이전트가 만들어내는 10배 규모의 트래픽을 감당하도록 설계된 것이 아니기 때문입니다.
우리는 여기에 새로운 기본 요소가 필요하다고 생각합니다. 에이전트를 최우선으로 고려해 설계된 분산형 버전 관리 파일 시스템, 그리고 오늘날 구축되고 있는 애플리케이션 유형을 지원할 수 있는 파일 시스템 말이죠.
저희는 이것을 Artifacts라고 부릅니다. Git을 사용하는 버전 관리 파일 시스템이죠. 리포지토리를 프로그래밍 방식으로 생성할 수 있으며, 이를 에이전트, 샌드박스, Workers 또는 다른 어떤 컴퓨팅 패러다임과도 함께 사용하고, 일반적인 Git 클라이언트 어디서든 여기에 연결할 수 있습니다.
모든 에이전트 세션에 각각 하나의 리포지토리를 부여하고 싶으신가요? Artifacts로 가능합니다. 모든 샌드박스 인스턴스에 각각 하나씩 붙이고 싶으신가요? 그것도 Artifacts로 가능합니다. 검증된 시작점에서 포크 10,000개를 만들고 싶으신가요? 맞습니다. 또 Artifacts입니다. Artifacts는 REST API와 기본 Workers API를 제공하여, Git 클라이언트가 적합하지 않은 환경, 즉 어떤 서버리스 함수에서든 리포지토리를 만들고, 자격 증명을 생성하고, 커밋할 수 있도록 해줍니다.
Artifacts는 유료 Workers 플랜을 사용하는 개발자를 대상으로 현재 비공개 베타로 제공되고 있으며, 5월 초까지는 이를 공개 베타로 공개하는 것을 목표로 하고 있습니다.
// Create a repo
const repo = await env.AGENT_REPOS.create(name)
// Pass back the token & remote to your agent
return { repo.remote, repo.token }
# Clone it and use it like any regular git remote
$ git clone https://x:${TOKEN}@123def456abc.artifacts.cloudflare.net/git/repo-13194.git
바로 이겁니다. 아무것도 없는 상태의 리포지토리가 즉시 생성되어 바로 사용할 수 있고, 어떤 Git 클라이언트에서도 그대로 작업할 수 있습니다.
그리고 기존 Git 리포지토리를 기반으로 Artifacts 리포지토리를 부트스트랩해서, 에이전트가 독립적으로 작업하고 별도의 변경 사항을 푸시하도록 하고 싶다면, .import()로 그것도 가능합니다.
interface Env {
ARTIFACTS: Artifacts
}
export default {
async fetch(request: Request, env: Env) {
// Import from GitHub
const { remote, token } = await env.ARTIFACTS.import({
source: {
url: "https://github.com/cloudflare/workers-sdk",
branch: "main",
},
target: {
name: "workers-sdk",
},
})
// Get a handle to the imported repo
const repo = await env.ARTIFACTS.get("workers-sdk")
// Fork to an isolated, read-only copy
const fork = await repo.fork("workers-sdk-review", {
readOnly: true,
})
return Response.json({ remote: fork.remote, token: fork.token })
},
}
지금 바로 시작하려면 문서를 확인하세요. Artifacts가 실제로 어떻게 활용되는지, 어떻게 만들어졌는지, 그리고 내부적으로 어떻게 동작하는지 알고 싶다면 아래 내용을 계속 읽어보세요.
왜 Git일까요? 그리고 버전 관리 파일 시스템이란 무엇일까요?
에이전트는 Git을 잘 압니다. 대부분의 모델 학습 데이터에 깊이 포함되어 있기 때문입니다. 일반적인 사용 흐름뿐 아니라 예외적인 케이스까지도 에이전트에게 이미 익숙하며, 특히 코드에 최적화된 모델(또는 실행 환경)은 Git을 매우 능숙하게 다룹니다.
또한 Git의 데이터 모델은 단순한 소스 제어를 넘어, 상태를 추적하고, 특정 시점으로 되돌리고, 대량의 작은 데이터를 지속적으로 저장해야 하는 모든 경우에 잘 맞습니다. 코드, 설정, 세션 프롬프트, 에이전트 히스토리까지, 이런 것들은 모두 작은 단위(“커밋”)로 저장하고, 필요할 때 이전 상태(“히스토리”)로 되돌릴 수 있어야 하는 데이터(“오브젝트”)입니다.
물론 완전히 새로운 맞춤형 프로토콜을 만들 수도 있었을 겁니다. 하지만 그러면 바로 부트스트랩 문제가 생깁니다. AI 모델이 그걸 모르기 때문에, 별도의 사용 방법을 학습시키거나, CLI를 배포하거나, 사용자가 문서나 MCP에 의존하도록 만들어야 합니다. 결국 이런 과정들은 모두 불필요한 마찰만 늘리게 됩니다.
에이전트에게 인증된 보안 HTTPS Git 원격 URL만 제공하고, 이를 일반적인 Git 리포지토리처럼 다루도록 하면 어떨까요? 실제로 꽤 잘 작동합니다. 그리고 Git을 직접 다루지 않는 클라이언트, 예를 들어 Cloudflare Worker, Lambda 함수, 또는 Node.js 애플리케이션 같은 경우를 위해 REST API와 (곧 제공될) 언어별 SDK도 함께 제공합니다. 이런 클라이언트들은 isomorphic-git을 사용할 수도 있지만, 많은 경우 더 단순한 TypeScript API를 사용하는 것이 필요한 API 범위를 줄이고 구현을 더 간결하게 만들어 줍니다.
Artifacts의 Git API를 보면 단순히 소스 제어용이라고 생각할 수 있습니다. 하지만 실제로는 Git의 API와 데이터 모델 자체가, 어떤 데이터든 상태를 저장하면서 포크(fork), 특정 시점으로 되돌리기(time travel), 상태 간 차이 비교(diff)를 가능하게 하는 매우 강력한 방식이라는 점이 핵심입니다.
Cloudflare 내부에서는 Artifacts를 내부 에이전트에 활용하고 있습니다. 각 세션마다 별도의 Artifacts 리포지토리를 생성해 파일 시스템의 현재 상태와 세션 히스토리를 자동으로 저장하고 있습니다. 이를 통해 다음과 같은 것들이 가능해집니다.
블록 스토리지를 별도로 프로비저닝하고 계속 유지하지 않아도 샌드박스 상태를 지속적으로 저장할 수 있습니다.
세션을 다른 사람과 공유하고, 실제 리포지토리(소스 제어)에 커밋이 있었는지와 관계없이 세션(프롬프트) 상태와 파일 상태를 모두 포함해 특정 시점으로 되돌아갈 수 있도록 할 수 있습니다.
그리고 가장 중요한 점은, 어떤 시점에서든 세션을 포크(fork)할 수 있다는 것입니다. 이를 통해 팀원이 세션을 공유하고, 다른 사람이 그 지점부터 이어서 작업할 수 있습니다. 문제를 디버깅하다가 다른 사람의 도움이 필요하신가요? URL만 공유하고 포크하면 됩니다. API를 가지고 이것저것 시도해보고 싶으신가요? 동료에게 포크를 맡기고, 내가 작업하던 지점부터 이어서 진행하게 하면 됩니다.
또한 Git 프로토콜 자체는 필요 없지만, 되돌리기(revert), 복제(clone), 변경 비교(diff) 같은 동작 방식이 필요한 사용 사례에서는 Artifacts를 활용해 보고 싶다는 팀들과도 이야기를 나눴습니다. 고객별 설정을 제품의 일부로 저장하면서, 필요할 때 롤백할 수 있기를 원하시나요? Artifacts는 이를 표현하는 데 매우 적합한 방식이 될 수 있습니다.
팀들이 Artifacts를 Git 중심 사용 사례뿐만 아니라, Git에 의존하지 않는 다양한 사용 사례로도 적극적으로 확장해 나가는 모습을 기대하고 있습니다.
Artifacts는 Durable Objects 위에 구축되었습니다. 상태를 유지하는 격리된 컴퓨트 인스턴스를 수백만 개(또는 수천만 개 이상)까지 생성할 수 있는 능력은 현재 Durable Objects의 핵심 특성이며, 이는 네임스페이스당 수백만 개의 Git 리포지토리를 지원하기 위해 정확히 필요한 요소였습니다.
Major League Baseball(실시간 경기 팬아웃), Confluence Whiteboards, 그리고 Cloudflare의 자체 Agents SDK는 모두 대규모 환경에서 Durable Objects를 내부적으로 활용하고 있으며, 그렇기 때문에 이미 일정 기간 프로덕션에서 검증된 기본 구성 요소 위에 이를 구축하고 있습니다.
하지만 우리에게 정말 필요했던 것은 Cloudflare Workers에서 실행될 수 있는 Git 구현체였습니다. 이 구현체는 작아야 했고, 가능한 한 완전해야 했으며, 확장 가능해야 했고(notes, LFS), 효율적이어야 했습니다. 그래서 우리는 Zig로 구현체를 만들고, 이를 Wasm으로 컴파일했습니다.
왜 Zig를 사용했을까요? 이유는 세 가지입니다.
전체 Git 프로토콜 엔진은 순수 Zig로 작성되었으며(libc 없이), 약 100KB 크기의 WASM 바이너리로 컴파일됩니다(여전히 최적화 여지도 있습니다!). 이 구현체는 SHA-1, zlib inflate/deflate, 델타 인코딩/디코딩, pack 파싱, 그리고 Git smart HTTP 프로토콜 전체를 모두 처음부터 직접 구현했으며, 표준 라이브러리를 제외하고는 외부 의존성이 전혀 없습니다.
Zig는 메모리 할당을 수동으로 제어할 수 있게 해주며, 이는 Durable Objects처럼 제약이 있는 환경에서 매우 중요합니다. 또한 Zig Build System을 통해 WASM 런타임(프로덕션)과 네이티브 빌드(libgit2와의 정합성 검증 테스트용) 간에 코드를 쉽게 공유할 수 있습니다.
WASM 모듈은 얇은 콜백 인터페이스를 통해 JS 호스트와 통신합니다. 스토리지 작업을 위한 11개의 호스트 import 함수(host_get_object, host_put_object 등)와 스트리밍 출력을 위한 하나의 함수(host_emit_bytes)로 구성되어 있습니다. WASM 측은 완전히 독립적으로 테스트할 수 있습니다.
내부적으로 Artifacts는 R2(스냅샷 저장용)와 KV(인증 토큰 추적용)도 함께 사용합니다.
Artifacts 작동 방식(Workers, Durable Objects, WebAssembly)
Worker는 프런트엔드 역할을 하며, 인증 및 권한 부여를 처리하고, 주요 지표(오류, 대기 시간)를 수집하며, 각 Artifacts 리포지토리(Durable Object)를 요청 시점에 동적으로 조회합니다.
구체적으로는 다음과 같습니다.
파일은 Durable Object의 기본 SQLite 데이터베이스에 저장됩니다.
Durable Object 스토리지는 행당 최대 2MB 크기 제한이 있기 때문에, 큰 Git 오브젝트는 여러 행에 나누어 저장됩니다.
우리는 내부적으로 SQLite를 기반으로 하는 sync KV API(state.storage.kv)를 활용합니다.
Durable Objects는 약 128MB의 메모리 제한이 있습니다. 이 덕분에 빠르고 가벼운 인스턴스를 수천만 개까지 생성할 수 있지만, 동시에 이러한 제한 내에서 동작하도록 설계해야 합니다.
우리는 fetch와 push 경로 모두에서 스트리밍을 적극적으로 활용하며, WASM에서 생성된 원시 출력 청크를 기반으로 `ReadableStream<Uint8Array>`를 직접 반환합니다.
우리는 자체적으로 Git 델타를 계산하지 않고, 대신 원시 델타와 베이스 해시를 실제 오브젝트와 함께 저장합니다. fetch 시 요청한 클라이언트가 이미 베이스 오브젝트를 가지고 있다면, Zig는 전체 오브젝트 대신 델타를 반환하여 대역폭과 메모리를 절약합니다.
Git 프로토콜 v1과 v2를 모두 지원합니다.
우리는 ls-refs, shallow clone(deepen, deepen-since, deepen-relative), 그리고 have/want 협상을 통한 증분 fetch 등 다양한 기능을 지원합니다.
우리는 Git 클라이언트와의 적합성 테스트와 프로토콜 지원을 검증하기 위한 libgit2 서버 기반 검증 테스트를 포함한 광범위한 테스트 스위트를 갖추고 있습니다.
여기에 더해, 우리는 git-notes를 네이티브로 지원합니다. Artifacts는 에이전트 중심으로 설계되었으며, notes를 통해 에이전트가 Git 오브젝트에 메모(메타데이터)를 추가할 수 있습니다. 여기에는 프롬프트, 에이전트 출처 정보, 기타 메타데이터가 포함되며, 오브젝트 자체를 변경하지 않고도 리포지토리에서 읽고 쓸 수 있습니다.
리포지토리가 커질수록 문제도 커지시나요? ArtifactFS를 만나보세요.
대부분의 리포지토리는 그렇게 크지 않으며, Git은 스토리지 측면에서 매우 효율적으로 설계되어 있습니다. 대부분의 리포지토리는 많아야 몇 초면 클론이 완료되며, 이 시간의 대부분은 네트워크 설정, 인증, 그리고 체크섬 계산에 의해 좌우됩니다. 대부분의 에이전트 또는 샌드박스 시나리오에서는 이것이 가능합니다. 샌드박스가 시작될 때 저장소를 복제하기만 하면 됩니다.
하지만 수 GB 규모의 리포지토리나 수백만 개의 오브젝트를 가진 리포지토리는 어떨까요? 에이전트가 몇 분씩 대기하면서 컴퓨트를 소모하지 않고도, 그런 리포지토리를 어떻게 빠르게 클론해 바로 작업을 시작할 수 있을까요?
인기 있는 한 웹 프레임워크는(2.4GB 규모에 긴 히스토리까지 포함되어 있어) 클론하는 데 거의 2분이 걸립니다. shallow clone이 더 빠르기는 하지만, 한 자릿수 초까지 줄이기에는 충분하지 않고, 우리도 항상 히스토리를 생략하고 싶은 것은 아닙니다(에이전트는 히스토리를 유용하게 활용합니다).
대규모 리포지토리도 10~15초 정도로 줄여서 에이전트가 바로 작업을 시작하게 할 수 있을까요? 가능합니다. 몇 가지 요령만 쓰면 됩니다.
Artifacts 출시와 함께, 우리는 ArtifactFS를 오픈소스로 공개합니다. 이는 대규모 Git 리포지토리를 가능한 한 빠르게 마운트하도록 설계된 파일 시스템 드라이버로, 초기 클론에서 대기하는 대신 파일 내용을 필요할 때 즉시 로드(hydrate)합니다. 이는 에이전트, 샌드박스, 컨테이너 등 시작 시간이 중요한 환경에 매우 적합합니다. 대규모 리포지토리 하나당 샌드박스 시작 시간을 약 90~100초 줄일 수 있고, 이런 샌드박스 작업을 한 달에 10,000번 실행한다면 총 2,778시간의 샌드박스 시간을 절약할 수 있습니다.
ArtifactFS는 “비동기 Git 클론”이라고 생각하면 됩니다.
ArtifactFS는 Git 리포지토리를 blobless clone 방식으로 가져옵니다. 즉, 파일 트리와 ref는 가져오지만 파일 내용 자체는 가져오지 않습니다. 이 작업은 샌드박스 시작 단계에서 수행되며, 그 덕분에 에이전트 실행 환경이 바로 작업을 시작할 수 있습니다.
백그라운드에서는 경량 데몬을 통해 파일 내용을 동시에 로드(hydrate, 다운로드)하기 시작합니다.
에이전트가 먼저 다루는 경향이 있는 파일들, 즉 패키지 매니페스트(package.json, go.mod), 설정 파일, 코드를 우선적으로 로드하고, 가능한 경우 바이너리 블롭(이미지, 실행 파일 및 기타 비텍스트 파일)은 우선순위를 낮춰 처리합니다. 이를 통해 파일이 로드(hydrate)되는 동안에도 에이전트가 파일 트리를 스캔할 수 있습니다.
에이전트가 파일을 읽으려 할 때 해당 파일이 아직 완전히 로드(hydrate)되지 않았다면, 로드가 완료될 때까지 읽기 작업이 대기하게 됩니다.
파일 시스템은 원격 리포지토리로 파일을 “동기화”하려고 시도하지 않습니다. 수천 개에서 수백만 개의 오브젝트가 있는 환경에서는 일반적으로 매우 느리기 때문이며, Git을 사용하고 있기 때문에 그럴 필요도 없습니다. 에이전트는 일반적인 리포지토리와 마찬가지로 commit과 push만 하면 됩니다. 새롭게 배워야 할 API도 없습니다.
중요한 점은, ArtifactFS는 우리 Artifacts뿐만 아니라 모든 Git 원격 저장소와 함께 동작한다는 것입니다. GitHub, GitLab, 또는 자체 호스팅 Git 인프라에서 대규모 리포지토리를 클론하는 경우에도 ArtifactFS를 그대로 사용할 수 있습니다.
오늘 공개된 것은 아직 베타 버전일 뿐이며, 앞으로 몇 주 동안 추가될 다양한 기능들을 이미 개발 중입니다.
우리가 제공하는 사용 가능한 메트릭을 확장할 계획입니다. 오늘은 수백만 개의 Artifacts를 관리하는 작업이 번거롭지 않도록 네임스페이스별 및 리포지토리별 주요 작업 횟수와 리포지토리별 저장된 바이트 수에 대한 메트릭을 제공하여 합니다.
push, pull, clone, fork와 같은 리포지토리 수준 이벤트를 네임스페이스 내 모든 리포지토리에서 발생시킬 수 있도록 Event Subscriptions 지원을 추가할 계획입니다. 이를 통해 이벤트를 소비하고, 웹훅을 작성하며, 해당 이벤트를 활용해 최종 사용자에게 알림을 보내거나, 제품 내 라이프사이클 이벤트를 트리거하거나, post-push 작업(CI/CD 등)을 실행할 수 있을 것입니다.
Artifacts API와 상호작용하기 위한 TypeScript, Go, Python용 네이티브 클라이언트 SDK를 제공할 것입니다.
리포지토리 단위 검색 API와 네임스페이스 전체 검색 API를 제공할 것입니다(예: “package.json 파일이 있는 모든 리포지토리를 찾아라”. )
우리는 또한 Workers Builds용 API도 계획하고 있으며, 이를 통해 모든 에이전트 기반 워크플로에서 CI/CD 작업을 실행할 수 있게 할 예정입니다.
우리는 아직 Artifacts 초기 단계에 있지만, 가격 정책은 에이전트 규모에 맞게 설계하려고 합니다. 수백만 개의 리포지토리를 보유해도 비용 효율적이어야 하고, 사용되지 않거나 드물게 사용되는 리포지토리가 부담이 되어서는 안 되며, 에이전트의 사실상 단일 테넌트 구조에 맞는 가격 모델을 제공해야 합니다.
또한 리포지토리가 실제로 사용될지, 핫 상태인지 콜드 상태인지, 또는 에이전트가 이를 활성화할지 여부를 고민할 필요도 없어야 합니다. 우리는 각 리포지토리에 대해 사용한 스토리지와 수행된 작업 (예: clone, fork, push, pull)에 따라 과금할 예정입니다.
| 단위당 비용($) | 포함됨 |
|---|
연산 | 1,000건의 작업당 $0.15 | 최초 10k 포함(매월) |
스토리지 | $0.50/GB-월 | 최초 1GB 포함 |
리포지토리가 1,000개든, 100,000개든, 1,000만 개든 상관없이, 규모가 크고 사용량이 많은 리포지토리는 작고 사용 빈도가 낮은 리포지토리보다 더 많은 비용이 발생합니다.
베타가 진행되는 동안 Artifacts를 Workers Free 플랜에도(일정한 합리적 제한과 함께) 제공할 예정이며, 과금이 적용되기 전과 가격 정책이 변경될 경우 베타 기간 내내 지속적으로 안내드릴 예정입니다.
Artifacts는 현재 비공개 베타로 출시되었으며, 공개 베타는 5월 초에 선보이려고 준비 중입니다(아, 2026년입니다!). 앞으로 몇 주에 걸쳐 고객을 점진적으로 확대할 예정이며, 관심이 있으신 분들은 비공개 베타 참여를 직접 신청하실 수 있습니다.
그동안 다음을 통해 Artifacts에 대해 더 알아보실 수 있습니다.
베타 진행 상황은 변경 로그를 참고해 주세요.