
AI 에이전트를 프로덕션에서 돌린다면 격리(isolation)는 선택이 아니라 기본입니다. 에이전트는 코드를 실행하고, 파일 시스템을 건드리고, 외부 서비스를 호출합니다. 제대로 된 샌드박스가 없으면 단 한 번의 잘못된 출력으로도 되돌리기 힘든 피해가 발생할 수 있습니다.
Puppyone은 서로 다른 워크로드를 위한 두 가지 샌드박스 환경을 지원합니다. 풀 기능 + 자유로운 실행이 가능한 Docker 기반 샌드박스, 그리고 빠르고 가볍고 글로벌하게 분산되는 Cloudflare 기반 샌드박스입니다. 이 글에서는 각각이 실제로 무엇이고, 어디서 갈리며, 어떻게 골라야 하는지 정리합니다.
샌드박스는 에이전트가 하는 모든 행위 — 코드 실행, 파일 접근, 도구 호출 — 가 가두어지고 통제되는 격리된 실행 환경입니다. 좋은 샌드박스는 다음과 같은 경계를 명확하게 강제합니다.
두 샌드박스 모두 이 경계를 강제합니다. 흥미로운 건 어떻게 강제하느냐, 그리고 그 방식이 가져오는 트레이드오프입니다.
전체 비교는 한 문장으로 압축됩니다. Docker 샌드박스는 통째로 Linux 머신을 한 대 주는 것이고, Cloudflare 샌드박스는 JavaScript를 돌릴 수 있는 슬롯을 한 자리 주는 것입니다.
Docker 샌드박스는 컨테이너 위에 만들어집니다. 각 샌드박스는 사실상 독립된 Linux 서버입니다. 패키지를 설치하고(apt install, pip install), 어떤 런타임이든 돌리고(Python, Node, Go), 서브프로세스를 띄우고, 진짜 파일 시스템을 읽고 쓰고, 작업을 몇 시간씩 돌릴 수 있습니다. 대가는 수 초 단위의 콜드 스타트, 그리고 살아 있는 동안 실제 CPU·메모리를 계속 잡아먹는다는 점입니다.
Cloudflare 샌드박스는 V8 Isolate 위에 만들어집니다. Chrome이 브라우저 탭을 격리하는 데 쓰는 그 기술입니다. 돌릴 수 있는 건 JavaScript / WebAssembly뿐입니다. 패키지 설치 불가, 서브프로세스 불가, 로컬 파일 시스템 없음, 단일 실행은 보통 CPU 30초로 잘립니다. 대신 콜드 스타트는 5밀리초 미만이고, 한 머신에 수천 개의 isolate가 올라가며, Cloudflare의 300개가 넘는 글로벌 엣지 거점에 자동으로 배포됩니다.
| 하고 싶은 일 | 선택 |
|---|---|
| Python 스크립트 돌리기, 라이브러리 설치, 데이터 처리 | Docker |
에이전트가 파일을 편집하거나 리포트를 만들고 git을 실행 | Docker |
| 수 분 ~ 수 시간 돌아가는 작업 | Docker |
| 밀리초 단위로 응답해야 하는 요청 | Cloudflare |
| 고동시성 JavaScript 로직 (라우팅, 변환, 필터링) | Cloudflare |
| 여러 리전의 사용자 가까운 곳에서 실행 | Cloudflare |
이제부터 각각을 자세히 풀어보겠습니다.
각 에이전트 작업은 자기 전용 컨테이너 안에서 돌아갑니다. namespace와 cgroup으로 호스트와 격리된 Linux 환경입니다. 작업이 들어오면 Puppyone이 미리 빌드된 이미지로부터 새 컨테이너를 띄우고, 입력을 마운트하고, 작업 디렉터리를 할당하고, 리소스 쿼터를 적용합니다. 작업이 끝나면 컨테이너 전체가 폐기됩니다. 모든 실행은 알려진 깨끗한 상태에서 시작되며, 이전 실행의 프로세스·파일·환경 변수가 남지 않습니다.
커스터마이징 가능한 이미지. 기본 이미지는 Python·Node·Git·curl이 미리 깔린 Ubuntu입니다. 부족하면 직접 만든 Dockerfile을 가져오면 됩니다. Puppyone은 표준 명령(FROM, RUN, COPY, WORKDIR, ENV)을 지원하며, 팀에 필요한 런타임·CLI 도구·사내 의존성을 전부 굽어둘 수 있습니다. 에이전트는 자기 워크플로우에 맞게 다듬어진 환경에서 곧장 시작됩니다.
조정 가능한 리소스 한도. 기본은 2 vCPU와 512MB RAM이고, 작업당 최대 8 vCPU와 8GB까지 올릴 수 있습니다. 샌드박스가 메모리를 다 써도 컨테이너만 깔끔히 죽고, 호스트는 영향을 받지 않습니다.
통제된 실행 시간. 기본 타임아웃은 작업당 5분, 최대 24시간까지 설정 가능합니다. 더 긴 워크플로우를 위해 pause / resume도 지원합니다. 일시 정지 시점에 파일 시스템과 메모리 상태가 스냅샷으로 저장되고 재개 시 복원되므로, 환경을 처음부터 다시 띄우는 비용을 낼 필요가 없습니다.
세밀한 아웃바운드 트래픽 제어. 외부로 나가는 트래픽은 기본적으로 모두 차단됩니다. 에이전트가 도달해도 되는 도메인이나 포트(예: api.openai.com, *.github.com)만 명시적으로 Allowlist에 올리고, 나머지는 거부합니다. 프롬프트 인젝션을 당한 에이전트가 데이터를 몰래 빼돌리는 걸 막는 방식이 바로 이것입니다.
파일 시스템과 직접 연결된 워크스페이스. 각 샌드박스는 Puppyone 파일 시스템 안의 namespace를 마운트합니다. 임시 스크래치 디렉터리가 아닙니다. 에이전트가 컨테이너 안에서 파일을 쓰면, 그것이 사실상 Puppyone에 대한 커밋입니다. 버전 관리되고, 권한이 붙고, 감사 가능합니다. 롤백할 수도 있고, 다른 에이전트로 넘길 수도 있고, 그것을 만든 정확한 작업과 단계까지 추적할 수도 있습니다.
컨테이너 수명 기준 과금. 컨테이너가 살아 있는 1초마다 과금되며, CPU가 일을 하는지 여부는 무관합니다. 이는 "돌리고 즉시 폐기" 패턴을 권장하는 설계입니다. 작업 시작, 종료, 컨테이너 종료. 만약 에이전트가 대부분의 시간을 LLM 응답이나 사용자 입력 대기에 쓴다면, 그 대기 시간에도 비용이 발생한다는 뜻입니다.
Puppyone의 Docker 샌드박스는 E2B와 API 호환입니다. 이미 에이전트를 E2B에서 돌리고 있다면, 비즈니스 로직은 한 줄도 안 건드리고 Puppyone으로 향만 바꾸면 됩니다. Sandbox.create(), runCode(), commands.run(), 파일 I/O — 전부 그대로 매핑됩니다. 추가로 얻는 건, 샌드박스와 파일 시스템이 한 몸이라는 점입니다. "샌드박스 안 파일 → 오브젝트 스토리지에 저장 → 다음 샌드박스로 동기화"라는 어색한 사슬을 더 이상 관리하지 않아도 됩니다. 모든 쓰기는 Puppyone 파일 시스템에 떨어지며, 버전 히스토리·권한·감사 로그가 함께 따라옵니다. 같은 상태가 작업·에이전트·심지어 샌드박스 종류를 넘어서도 보입니다.
에이전트 코드는 Cloudflare의 글로벌 엣지 네트워크 위에 있는 V8 Isolate 안에서 돌아갑니다. Chrome이 탭을 격리하는 데 쓰는 바로 그 기술입니다. 각 isolate는 밀폐된 JavaScript 실행 컨텍스트로, 밀리초 단위로 시작되고(부팅할 OS가 없습니다) 요청이 끝나면 폐기됩니다. 요청은 사용자에게 가장 가까운 엣지 거점으로 라우팅되며, 왕복 지연을 수십 밀리초 이내로 유지합니다.
밀리초 콜드 스타트. Isolate 하나가 5ms 미만에 뜹니다. 컨테이너보다 약 세 자릿수 빠른 셈입니다. 요청마다 새 샌드박스를 띄우는 사치가 가능합니다. 워밍업 풀이나 상시 인스턴스가 필요 없습니다.
JavaScript / WebAssembly 전용. Python도, shell도, 네이티브 바이너리도 안 됩니다. 로직은 JS/TS이거나 WASM으로 컴파일되어야 합니다. Node.js 내장 기능 대부분은 사용 가능하지만, 시스템 콜에 의존하는 것들(fs, child_process, 네이티브 C 확장)은 안 됩니다.
메모리 128MB 상한, 요청당 CPU 30초. 각 요청은 최대 128MB 메모리와 30초의 CPU 시간을 받습니다(유료 플랜에서 최대 5분까지 설정 가능). 알아둘 점: 계산되는 건 활성 CPU 시간뿐입니다. fetch()나 데이터베이스 쿼리를 기다리는 시간은 카운트되지 않으므로, CPU 30초로 묶인 요청도 실제 시계 기준으로는 몇 분간 열려 있을 수 있습니다.
로컬 파일 시스템 없음. Isolate는 무상태입니다. 영속화가 필요한 건 모두 외부 스토리지로 — Cloudflare KV, R2, D1, 또는 자체 데이터베이스. 요청 간에 중간 상태를 공유하려면 직렬화해서 내보내고 다시 읽어 들이거나, 별도의 상태 보관 서비스를 앞에 두어야 합니다.
글로벌 엣지 실행 + 오토스케일링. 코드는 Cloudflare의 300+ 엣지 거점에 자동 배포되어 사용자에게 가장 가까운 곳에서 실행됩니다. 0에서 수만 QPS까지, 용량 계획은 필요 없습니다 — 플랫폼이 처리합니다.
Cloudflare의 보안 레이어가 기본 제공. DDoS 방어, 레이트 리미팅, 봇 관리, TLS 종단 — 모두 네트워크에 내장되어 있습니다. 별도 레이어를 따로 세울 필요가 없습니다.
활성 CPU 밀리초만 과금. Isolate가 fetch(), 데이터베이스, 사용자 이벤트를 기다리는 동안에는 과금되지 않습니다. V8이 실제로 코드를 실행한 밀리초만 청구됩니다. LLM을 부르고 API 응답을 모으는 게 일의 전부인 I/O 위주 워크로드에서는 대기 시간 비용이 사실상 0에 가깝습니다.
Cloudflare 샌드박스는 현재 개발 중이며, 아직 외부에 공개되지 않았습니다. Docker 샌드박스와 같은 방식으로 Puppyone 파일 시스템과 결합하는 작업을 진행 중입니다. Isolate 안의 JS 코드가 "파일을 쓰면" 그것은 Puppyone에 대한 버전 관리·권한·감사 가능한 커밋이 되고, Docker 샌드박스와도 상태를 공유합니다. 같은 에이전트가 무거운 연산은 Docker 샌드박스에서 돌리고, 엣지에서의 응답은 Cloudflare 샌드박스에서 처리하면서, 양쪽 모두 같은 워크스페이스를 바라보는 — 그런 구성이 가능해집니다.
엣지 실행이 필요하다면 업데이트 구독을 부탁드립니다. 공개되는 즉시 알려드리겠습니다.
위에서 다룬 모든 내용을 한 번에 훑어볼 수 있는 표로 정리합니다.
| 항목 | Docker 샌드박스 | Cloudflare 샌드박스 |
|---|---|---|
| 기반 기술 | Linux 컨테이너 (namespace + cgroup) | V8 Isolate |
| 콜드 스타트 | 2~10초 | < 5밀리초 |
| 런타임 | Python, Node, Go, shell — 모든 Linux 바이너리 | JavaScript / TypeScript / WebAssembly |
| 패키지 설치? | ✅ apt, pip, npm, 사용자 Dockerfile | ❌ 사전에 번들링 필요 |
| 서브프로세스? | ✅ | ❌ |
| 로컬 파일 시스템 | ✅ POSIX 완전 지원, Puppyone에 마운트 | ❌ 외부 스토리지만 (KV / R2 / D1) |
| 기본 리소스 | 2 vCPU + 512 MB | 128 MB 메모리 |
| 리소스 상한 | 8 vCPU + 8 GB (조정 가능) | 128 MB (고정) |
| 1회 실행 시간 | 기본 5분, 최대 24시간 | 기본 CPU 30초, 유료 시 최대 5분 |
| 상태 보존 | pause / resume 스냅샷 (메모리 + FS) | 없음 (요청마다 새 isolate) |
| 동시성 모델 | 샌드박스당 컨테이너 1개 (실 자원 소모) | 머신당 수천 isolate |
| 지리적 분산 | 단일 리전 | 300+ 엣지 거점, 자동 라우팅 |
| 아웃바운드 제어 | 도메인/포트 Allowlist | Workers로 설정 |
| 플랫폼 보안 | 직접 구축 | DDoS / 레이트 리밋 / 봇 / TLS 내장 |
| 과금 단위 | 컨테이너 수명 초당 (대기 시간 포함) | 활성 CPU 밀리초당 (대기 미포함) |
| 프로세스 모델 | 돌리고 폐기 | 온디맨드, 유지보수 불필요 |
| API 호환성 | E2B와 호환 | Cloudflare Workers API |
| Puppyone 상태 | ✅ 제공 중 | 🚧 개발 중, 미공개 |
| 대표 사례 | 5분짜리 데이터 처리, 패키지 포함된 Python, 다단계 워크플로우 | 밀리초 단위 라우팅, 고동시성 JS 로직, 엣지 API |
| 10분 동안 도는 에이전트는? | 실제로 계산 중이라면 Docker | 90%가 LLM/API 대기라면 Cloudflare |
샌드박스를 고르는 건 "어느 쪽이 더 좋은가"의 문제가 아니라, "내 워크로드가 실제로 어떻게 생겼는가"의 문제입니다. 아래 다섯 가지 차원이면 현실의 의사결정 대부분이 커버됩니다.
에이전트가 Python, shell, Go, 네이티브 바이너리(ffmpeg, pandoc, git 같은 것들)를 돌려야 한다면 — Docker밖에 답이 없습니다. Cloudflare는 JavaScript / TypeScript / WebAssembly만 가능합니다. pip install조차 못 합니다.
비즈니스 로직이 이미 JS / TS이고 시스템 콜로 들어가지 않는다면 — 둘 다 후보입니다. 계속 읽어 주세요.
| 작업 시간 | 선택 | 이유 |
|---|---|---|
| < CPU 30초 | Cloudflare | 밀리초 시작 + ms 단위 과금 — 압도적으로 저렴 |
| CPU 30초 ~ 5분 | Cloudflare (유료 플랜에서 5분까지 가능) | 한도 안 |
| 수 분 ~ 수 시간 | Docker | Cloudflare가 CPU 천장에 부딪힘 |
| 며칠짜리 워크플로우 | Docker + pause / resume 스냅샷 | 상태를 얼려뒀다 나중에 이어 쓰기 |
두 과금 모델은 본질적으로 다릅니다 — 같은 워크로드라도 잘못 고르면 비용이 한 자릿수 차이가 날 수 있습니다.
fetch(), 데이터베이스, LLM 스트리밍 응답을 기다리는 동안에는 과금되지 않습니다. V8이 실제로 코드를 실행하는 밀리초만 청구됩니다.구체적으로:
시간당 단가를 비교하면 안 됩니다. 비교해야 할 것은 워크로드의 실제 시계 시간 중 실제로 계산하고 있는 비율입니다. 그 비율이 어느 모델이 이기는지를 결정합니다.
그래도 모르겠다면? 기본은 Docker입니다. Docker의 능력은 Cloudflare의 엄밀한 상위집합 — 거의 잘못 고를 수 없습니다. 극단적인 고동시성·I/O 집약 시나리오에서 비용이 다소 더 들 뿐입니다. 트래픽이 진짜로 커져 신경 써야 할 시점이 되면 그때 핫패스를 Cloudflare로 옮기면 됩니다.
Cloudflare 샌드박스가 공개된 뒤의 이상적인 아키텍처: 두 가지가 협력하는 모습입니다. Cloudflare 샌드박스는 에이전트의 현관 역할 — 밀리초 단위 라우팅, 파라미터 추출, 가벼운 결정. 진짜로 무거운 연산이 필요해지면 Docker 샌드박스로 디스패치합니다. Cloudflare는 빠른 경로, Docker는 무거운 일, 그리고 둘을 같은 Puppyone 파일 시스템이 잇는 — 그런 그림입니다.
이미 에이전트가 E2B 위에서 돌고 있다면, Puppyone으로 향만 돌리면 됩니다 — Sandbox.create(), runCode(), commands.run()은 모두 API 호환이고, 비즈니스 로직 변경이 필요 없으며, 즉시 파일 시스템 수준의 버전 관리·권한·감사 로그를 얻습니다.
처음부터 시작하신다면, Puppyone 문서의 퀵 스타트 가이드가 몇 줄의 코드로 버전 관리되는 파일 시스템 샌드박스를 띄워줍니다.
Cloudflare 엣지 샌드박스가 필요하다면, 업데이트 구독을 해두세요 — 공개되는 즉시 알려드리겠습니다.