SDK는 샌드박스 REST API를 얇게 감싼 것입니다. 요청을 직접 만드는 일, 플랫폼이 바쁠 때 재시도하는 일, 코드가 예외를 던졌을 때 샌드박스 삭제를 잊는 일, 이 세 가지를 덜어 줍니다. 이 페이지의 내용은 두 패키지의 0.2.0 버전에 해당합니다.
샌드박스를 만들어 본 적이 없다면 5분 연결 가이드에서 먼저 토큰을 받으세요. 샌드박스가 무엇이고 안에 무엇이 있는지는 샌드박스에 있습니다.
설치와 설정
pip install eqvps # Python 3.8+
npm i @eqvps/sdk # Node.js 18+, Deno, Bun
export EQVPS_API_KEY=... # your EQVPS account token
두 언어로 쓴 같은 프로그램: 샌드박스를 만들고, 코드를 실행하고, 삭제합니다.
from eqvps import Sandbox
with Sandbox.create(tariff="small") as sb:
r = sb.run("print(2 + 2)")
print(r.exit_code, r.stdout) # 0 4
import { Sandbox } from "@eqvps/sdk";
await Sandbox.with({ tariff: "small" }, async (sb) => {
const r = await sb.run("print(2 + 2)");
console.log(r.exit_code, r.stdout); // 0 4
});
샌드박스 만들기와 찾기
Sandbox.create(...)는 샌드박스를 시작하며, 보통 약 1초가 걸립니다. Python은 키워드 인수를, TypeScript는 옵션 객체 하나를 받습니다.
| Python | TypeScript | 기본값 | 의미 |
|---|---|---|---|
mode | mode | "ephemeral" | "ephemeral"(초 단위) 또는 "persistent"(시작된 시간 단위, 디스크 유지) |
tariff | tariff | "small" | micro, small, standard, plus, pro, max |
idle_timeout | idleTimeout | 300 | 임시 샌드박스가 삭제되기까지의 무활동 초, 최대 3600 |
ttl | ttl | — | 최대 수명(초): 임시는 86400까지, 영구는 2592000까지 |
env | env | — | 모든 명령에 적용되는 환경 변수, 암호화해 저장 |
api_key, base_url | apiKey, baseUrl | 환경 변수 | EQVPS_API_KEY / EQVPS_API_URL을 대체 |
timeout | timeoutMs | 70초 | 요청별 HTTP 타임아웃 |
max_retries | maxRetries | 3 | 429/503 재시도 횟수 |
Sandbox.connect(id)는 기존 샌드박스에 연결합니다. 보통 어제 만든 영구 샌드박스입니다. Sandbox.list()는 계정의 모든 샌드박스(실행 중, 일시 중지)를 반환합니다.
속성: id(sb_ + 16진수 24자), mode, tariff, state(running, starting, paused, pausing, resuming, deleting, deleted), env_keys / envKeys(이름만, 값은 절대 돌려주지 않음), info(원본 객체). refresh()로 다시 불러옵니다.
kill()은 샌드박스를 삭제하고 과금을 멈춥니다. 이미 없는 샌드박스에 호출해도 오류가 아닙니다.
코드 실행
run(code, language="python", timeout=30)은 stdin으로 코드를 Python 3.12, Node.js 22, bash("python", "node", "bash")에 전달합니다. exec(command, cwd=None, stdin=None, timeout=30)은 셸 명령을 실행합니다. 문자열은 bash -lc를 거치고, 리스트는 셸 없이 argv로 실행됩니다.
둘 다 ExecResult를 반환합니다:
| 필드 | 의미 |
|---|---|
exit_code | 프로세스 종료 코드 |
stdout, stderr | 출력, 스트림당 최대 1 MiB |
timed_out | 명령이 타임아웃에 걸림 |
truncated | 출력이 잘림 |
duration_ms | 실행 시간 |
ok | exit_code == 0이고 타임아웃 없음 |
동기 호출은 최대 55초까지입니다. 두 메서드 모두 그 호출에만 적용되는 env도 받으며, 생성 시 설정한 값을 덮어씁니다.
긴 작업: 백그라운드 작업
background=True(TypeScript: { background: true })를 넘기면 바로 Task를 받습니다. 55초 제한이 없고 샌드박스 수명이 끝날 때까지 실행할 수 있습니다. 샌드박스당 최대 8개 작업입니다.
task = sb.exec("cd /root/app && python3 -m pytest -q", background=True)
result = task.wait(on_output=lambda out, err: print(out, end=""))
print(result.state, result.exit_code) # done 0
const task = await sb.exec("cd /root/app && npm test", { background: true });
const result = await task.wait({ onOutput: (out) => process.stdout.write(out) });
| 메서드 | 하는 일 |
|---|---|
task.logs() | 이전 호출 이후의 새 stdout과 stderr |
task.status() | 출력을 소비하지 않고 상태 확인: running, done, failed, killed, timeout |
task.wait(timeout, poll_interval=2, on_output) | 작업이 끝날 때까지 폴링하고 TaskResult 반환 |
task.kill() | 작업과 그 프로세스를 중지 |
sb.task(id) / sb.tasks() | 작업에 다시 연결 / 작업 목록 |
wait가 자신의 타임아웃에 도달하면 SandboxTimeoutError를 던지지만 작업은 계속 실행됩니다. 실행 중인 작업이 있으면 임시 샌드박스가 무활동으로 삭제되지도 않습니다.
파일과 사용량
upload(path, content, mode=None)는 절대 경로에 파일을 쓰고 크기를 반환합니다. download(path)는 바이트를, download_text(path) / downloadText(path)는 문자열을 반환합니다. 한 번의 전송은 5 MB로 제한됩니다.
usage()는 실행 초, 사용한 CPU 초, 송신 바이트, 시간당 가격, billed_usd, estimated_total_usd를 반환합니다. tariffs()는 키가 필요 없는 일반 함수로 현재 가격과 한도를 반환합니다. 과금 규칙은 샌드박스 한도와 과금에 있습니다.
오류
모든 API 오류는 EqvpsError의 하위 클래스이며 status(HTTP), code(고정 문자열), body를 가집니다. 서버가 보내면 retry_after / retryAfter가 채워집니다.
| 클래스 | HTTP | 대표 code | 할 일 |
|---|---|---|---|
AuthenticationError | 401 | unauthenticated | 토큰 확인 |
InsufficientBalanceError | 402 | insufficient_balance | 잔액 충전 |
NotFoundError | 404 | not_found | id가 틀렸거나 파일이 없음 |
SandboxPausedError | 409 | sandbox_paused | 잔액이 떨어져 일시 중지됨, 충전하면 재개 |
SandboxDeletedError | 410 | sandbox_deleted | 영구 삭제됨 |
FileTooLargeError | 413 | file_too_large | 전송을 5 MB 미만으로 유지 |
ValidationError | 422 | invalid_request | 매개변수 수정 |
RateLimitError | 429 | too_many_concurrent, too_many_tasks, rate_limited | 기다렸다가 재시도 |
BudgetExceededError | 429 | budget_exceeded | 샌드박스 일일 또는 월간 지출 한도에 도달 |
CapacityError | 503 | capacity | 잠시 후 재시도하거나 더 작은 요금제 선택 |
SandboxTimeoutError | — | request_timeout, wait_timeout | 명령이 아니라 HTTP 요청(또는 wait)이 시간 초과됨 |
429의 대부분은 두 가지 한도에서 옵니다. 한 계정은 동시에 2개의 명령을 실행하고 최대 20개의 샌드박스를 보유할 수 있습니다. 서버가 대기 시간을 알려 주면 SDK가 재시도하고, 세 번 실패하면 예외가 발생합니다.
SDK가 필요 없을 때
HTTP 클라이언트가 있는 언어라면 어떤 언어로든 API를 직접 호출할 수 있습니다. 엔드포인트는 https://eqvps.com/openapi.json의 OpenAPI 파일에 있습니다. Claude, Cursor 등 MCP 클라이언트에서 동작하는 에이전트는 코드조차 필요 없습니다. MCP 서버에 같은 샌드박스 도구가 있습니다. 동작하는 모습만 보고 싶다면 샌드박스 페이지에 요금제와 신규 계정용 $1 체험이 있습니다.
댓글
아직 댓글이 없습니다. 첫 번째가 되세요.