API Usage Guide
🚀 빠른 시작
1. Docker 이미지 빌드
# Windows
.\scripts\build-runtime-images.ps1
# Linux/Mac
./scripts/build-runtime-images.sh
2. API 서버 실행
방법 1: 개발 환경
# API 서버 실행 (WebSocket + JSON-RPC)
cd src/CodeBeaker.API
dotnet run
방법 2: Docker Compose (프로덕션)
docker-compose up -d
📡 WebSocket 연결
기본 URL
- Development:
ws://localhost:5000/ws/jsonrpc - Production:
ws://your-domain/ws/jsonrpc
WebSocket 클라이언트 예제
JavaScript (브라우저):
const ws = new WebSocket('ws://localhost:5000/ws/jsonrpc');
ws.onopen = () => {
console.log('Connected to CodeBeaker');
};
ws.onmessage = (event) => {
const response = JSON.parse(event.data);
console.log('Response:', response);
};
ws.onerror = (error) => {
console.error('WebSocket error:', error);
};
// JSON-RPC 요청 전송
function sendRequest(method, params, id = 1) {
ws.send(JSON.stringify({
jsonrpc: '2.0',
id: id,
method: method,
params: params
}));
}
Node.js:
const WebSocket = require('ws');
const ws = new WebSocket('ws://localhost:5000/ws/jsonrpc');
ws.on('open', () => {
// 세션 생성
ws.send(JSON.stringify({
jsonrpc: '2.0',
id: 1,
method: 'session.create',
params: { language: 'python' }
}));
});
ws.on('message', (data) => {
const response = JSON.parse(data);
console.log('Response:', response);
});
Python:
import asyncio
import websockets
import json
async def codebeaker_client():
uri = "ws://localhost:5000/ws/jsonrpc"
async with websockets.connect(uri) as ws:
# 세션 생성
request = {
"jsonrpc": "2.0",
"id": 1,
"method": "session.create",
"params": {"language": "python"}
}
await ws.send(json.dumps(request))
response = await ws.recv()
print(json.loads(response))
asyncio.run(codebeaker_client())
🎯 세션 기반 실행 (권장)
세션 기반 실행은 컨테이너를 재사용하여 50-75% 성능 향상을 제공합니다.
1. 세션 생성
요청:
{
"jsonrpc": "2.0",
"id": 1,
"method": "session.create",
"params": {
"language": "python",
"idleTimeoutMinutes": 30,
"maxLifetimeMinutes": 120,
"memoryLimitMB": 512
}
}
응답:
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"sessionId": "abc123def456",
"containerId": "xyz789",
"language": "python",
"createdAt": "2025-10-27T12:00:00Z",
"state": "Active",
"config": {
"idleTimeoutMinutes": 30,
"maxLifetimeMinutes": 120
}
}
}
2. 파일 작성
요청:
{
"jsonrpc": "2.0",
"id": 2,
"method": "session.execute",
"params": {
"sessionId": "abc123def456",
"command": {
"type": "write_file",
"path": "/workspace/hello.py",
"content": "print('Hello, World!')",
"mode": "Create"
}
}
}
응답:
{
"jsonrpc": "2.0",
"id": 2,
"result": {
"success": true,
"result": {
"path": "/workspace/hello.py",
"bytes": 22
},
"error": null,
"durationMs": 45
}
}
3. 코드 실행
요청:
{
"jsonrpc": "2.0",
"id": 3,
"method": "session.execute",
"params": {
"sessionId": "abc123def456",
"command": {
"type": "execute_shell",
"commandName": "python3",
"args": ["/workspace/hello.py"],
"workingDirectory": "/workspace"
}
}
}
응답:
{
"jsonrpc": "2.0",
"id": 3,
"result": {
"success": true,
"result": {
"exitCode": 0,
"stdout": "Hello, World!\n",
"stderr": "",
"durationMs": 120
},
"error": null,
"durationMs": 125
}
}
4. 파일 읽기
요청:
{
"jsonrpc": "2.0",
"id": 4,
"method": "session.execute",
"params": {
"sessionId": "abc123def456",
"command": {
"type": "read_file",
"path": "/workspace/hello.py"
}
}
}
응답:
{
"jsonrpc": "2.0",
"id": 4,
"result": {
"success": true,
"result": {
"content": "print('Hello, World!')",
"bytes": 22
},
"error": null,
"durationMs": 35
}
}
5. 세션 목록 조회
요청:
{
"jsonrpc": "2.0",
"id": 5,
"method": "session.list",
"params": {}
}
응답:
{
"jsonrpc": "2.0",
"id": 5,
"result": {
"count": 1,
"sessions": [
{
"sessionId": "abc123def456",
"containerId": "xyz789",
"language": "python",
"createdAt": "2025-10-27T12:00:00Z",
"lastActivity": "2025-10-27T12:15:30Z",
"state": "Idle",
"executionCount": 3,
"idleMinutes": 2.5,
"lifetimeMinutes": 15.5
}
]
}
}
6. 세션 종료
요청:
{
"jsonrpc": "2.0",
"id": 6,
"method": "session.close",
"params": {
"sessionId": "abc123def456"
}
}
응답:
{
"jsonrpc": "2.0",
"id": 6,
"result": {
"sessionId": "abc123def456",
"closed": true
}
}
🔥 언어별 사용 예제
Python 예제
const ws = new WebSocket('ws://localhost:5000/ws/jsonrpc');
ws.onopen = async () => {
// 1. 세션 생성
ws.send(JSON.stringify({
jsonrpc: '2.0',
id: 1,
method: 'session.create',
params: { language: 'python' }
}));
};
ws.onmessage = (event) => {
const response = JSON.parse(event.data);
if (response.id === 1) {
// 세션 생성 완료
const sessionId = response.result.sessionId;
// 2. Python 코드 작성
ws.send(JSON.stringify({
jsonrpc: '2.0',
id: 2,
method: 'session.execute',
params: {
sessionId: sessionId,
command: {
type: 'write_file',
path: '/workspace/script.py',
content: 'for i in range(5):\n print(f"Count: {i}")'
}
}
}));
} else if (response.id === 2) {
// 파일 작성 완료, Python 실행
const sessionId = 'abc123def456'; // 실제로는 저장된 값 사용
ws.send(JSON.stringify({
jsonrpc: '2.0',
id: 3,
method: 'session.execute',
params: {
sessionId: sessionId,
command: {
type: 'execute_shell',
commandName: 'python3',
args: ['/workspace/script.py']
}
}
}));
} else if (response.id === 3) {
// 실행 완료
console.log('Output:', response.result.result.stdout);
// Output: Count: 0\nCount: 1\nCount: 2\nCount: 3\nCount: 4\n
}
};
JavaScript (Node.js) 예제
// 1. 세션 생성
{
"jsonrpc": "2.0",
"id": 1,
"method": "session.create",
"params": { "language": "javascript" }
}
// 2. JavaScript 코드 작성
{
"jsonrpc": "2.0",
"id": 2,
"method": "session.execute",
"params": {
"sessionId": "abc123",
"command": {
"type": "write_file",
"path": "/workspace/app.js",
"content": "const numbers = [1, 2, 3, 4, 5];\nconst sum = numbers.reduce((a, b) => a + b, 0);\nconsole.log(`Sum: ${sum}`);"
}
}
}
// 3. Node.js 실행
{
"jsonrpc": "2.0",
"id": 3,
"method": "session.execute",
"params": {
"sessionId": "abc123",
"command": {
"type": "execute_shell",
"commandName": "node",
"args": ["/workspace/app.js"]
}
}
}
Go 예제
// 1. 세션 생성
{
"jsonrpc": "2.0",
"id": 1,
"method": "session.create",
"params": { "language": "go" }
}
// 2. Go 코드 작성
{
"jsonrpc": "2.0",
"id": 2,
"method": "session.execute",
"params": {
"sessionId": "abc123",
"command": {
"type": "write_file",
"path": "/workspace/main.go",
"content": "package main\n\nimport \"fmt\"\n\nfunc main() {\n fmt.Println(\"Hello from Go\")\n}"
}
}
}
// 3. Go 실행
{
"jsonrpc": "2.0",
"id": 3,
"method": "session.execute",
"params": {
"sessionId": "abc123",
"command": {
"type": "execute_shell",
"commandName": "go",
"args": ["run", "/workspace/main.go"]
}
}
}
C# (.NET) 예제
// 1. 세션 생성
{
"jsonrpc": "2.0",
"id": 1,
"method": "session.create",
"params": { "language": "csharp" }
}
// 2. C# 코드 작성
{
"jsonrpc": "2.0",
"id": 2,
"method": "session.execute",
"params": {
"sessionId": "abc123",
"command": {
"type": "write_file",
"path": "/workspace/Program.cs",
"content": "using System;\n\nclass Program\n{\n static void Main()\n {\n Console.WriteLine(\"Hello from C#\");\n }\n}"
}
}
}
// 3. C# 컴파일 및 실행
{
"jsonrpc": "2.0",
"id": 3,
"method": "session.execute",
"params": {
"sessionId": "abc123",
"command": {
"type": "execute_shell",
"commandName": "dotnet",
"args": ["script", "/workspace/Program.cs"]
}
}
}
Deno Runtime 예제 ⚡ NEW
Deno는 JavaScript/TypeScript용 경량 런타임으로 25배 빠른 시작 속도를 제공합니다.
기본 TypeScript 실행
// 1. 세션 생성 (Deno 런타임)
{
"jsonrpc": "2.0",
"id": 1,
"method": "session.create",
"params": {
"language": "deno",
"idleTimeoutMinutes": 30
}
}
// 2. TypeScript 코드 직접 실행 (ExecuteCodeCommand)
{
"jsonrpc": "2.0",
"id": 2,
"method": "session.execute",
"params": {
"sessionId": "abc123",
"command": {
"type": "execute_code",
"code": "const greeting: string = 'Hello from Deno!';\nconsole.log(greeting);\nconst sum = (a: number, b: number): number => a + b;\nconsole.log(`Sum: ${sum(10, 20)}`);"
}
}
}
// 응답:
// {
// "jsonrpc": "2.0",
// "id": 2,
// "result": {
// "success": true,
// "result": "Hello from Deno!\nSum: 30",
// "durationMs": 50
// }
// }
파일 기반 실행
// 1. TypeScript 파일 작성
{
"jsonrpc": "2.0",
"id": 1,
"method": "session.execute",
"params": {
"sessionId": "abc123",
"command": {
"type": "write_file",
"path": "calculator.ts",
"content": "interface Calculator {\n add(a: number, b: number): number;\n}\n\nconst calc: Calculator = {\n add: (a, b) => a + b\n};\n\nconsole.log('Result:', calc.add(15, 25));"
}
}
}
// 2. Deno로 TypeScript 실행
{
"jsonrpc": "2.0",
"id": 2,
"method": "session.execute",
"params": {
"sessionId": "abc123",
"command": {
"type": "execute_code",
"code": "// Import from file\nimport('./calculator.ts');"
}
}
}
권한 제어 예제
// 1. 제한된 권한으로 세션 생성
{
"jsonrpc": "2.0",
"id": 1,
"method": "session.create",
"params": {
"language": "deno",
"permissions": {
"allowRead": ["/workspace"],
"allowWrite": ["/workspace"],
"allowNet": false, // 네트워크 차단
"allowEnv": false // 환경 변수 접근 차단
}
}
}
// 2. 파일 읽기/쓰기 (허용됨)
{
"jsonrpc": "2.0",
"id": 2,
"method": "session.execute",
"params": {
"sessionId": "abc123",
"command": {
"type": "execute_code",
"code": "await Deno.writeTextFile('/workspace/data.txt', 'Hello!');\nconst content = await Deno.readTextFile('/workspace/data.txt');\nconsole.log(content);"
}
}
}
// 3. 네트워크 접근 시도 (차단됨)
{
"jsonrpc": "2.0",
"id": 3,
"method": "session.execute",
"params": {
"sessionId": "abc123",
"command": {
"type": "execute_code",
"code": "const response = await fetch('https://api.github.com');"
}
}
}
// 응답: PermissionDenied: Requires net access to "api.github.com"
성능 비교: Docker vs Deno
// Docker Runtime (기존 방식)
// 세션 생성: ~2000ms
// 코드 실행: ~100ms
// 총 시간: ~2100ms
{
"jsonrpc": "2.0",
"id": 1,
"method": "session.create",
"params": { "language": "javascript" } // Docker 사용
}
// Deno Runtime (경량 방식)
// 세션 생성: ~80ms
// 코드 실행: ~50ms
// 총 시간: ~130ms (25배 빠름!)
{
"jsonrpc": "2.0",
"id": 1,
"method": "session.create",
"params": { "language": "deno" } // Deno 사용
}
AI 에이전트 시나리오
// AI가 10번 연속 코드 실행 요청
for (let i = 0; i < 10; i++) {
// Docker: ~3초 소요 (환경 생성 오버헤드)
// Deno: ~1초 소요 (빠른 프로세스 시작)
ws.send(JSON.stringify({
jsonrpc: '2.0',
id: i,
method: 'session.create',
params: { language: 'deno' }
}));
ws.send(JSON.stringify({
jsonrpc: '2.0',
id: i + 100,
method: 'session.execute',
params: {
sessionId: sessionId,
command: {
type: 'execute_code',
code: `console.log('Iteration ${i}');`
}
}
}));
}
// 결과: 3배 빠른 응답 속도 🚀
Deno Runtime 장점
| 특징 | Docker Runtime | Deno Runtime |
|---|---|---|
| 시작 시간 | 2000ms | 80ms (25배 빠름) |
| 메모리 사용량 | 250MB | 30MB (8배 적음) |
| TypeScript 지원 | 별도 컴파일 필요 | 네이티브 지원 |
| 격리 수준 | 9/10 (컨테이너) | 7/10 (권한 기반) |
| 권한 제어 | 네트워크/파일 모두 격리 | 세밀한 권한 제어 |
| 추천 용도 | 복잡한 의존성 | 빠른 실행, AI 에이전트 |
📦 Command 타입 상세
1. WriteFileCommand
파일 작성 또는 생성
{
"type": "write_file",
"path": "/workspace/file.txt",
"content": "파일 내용",
"mode": "Create"
}
모드:
Create: 새 파일 생성 (기존 파일 덮어쓰기)Append: 기존 파일에 추가
2. ReadFileCommand
파일 읽기
{
"type": "read_file",
"path": "/workspace/file.txt"
}
3. ExecuteShellCommand
Shell 명령 실행
{
"type": "execute_shell",
"commandName": "python3",
"args": ["/workspace/script.py"],
"workingDirectory": "/workspace"
}
4. CreateDirectoryCommand
디렉토리 생성
{
"type": "create_directory",
"path": "/workspace/data"
}
5. CopyFileCommand
파일 복사
{
"type": "copy_file",
"sourcePath": "/workspace/file1.txt",
"destinationPath": "/workspace/file2.txt"
}
6. DeleteFileCommand
파일 삭제
{
"type": "delete_file",
"path": "/workspace/file.txt"
}
7. ListDirectoryCommand
디렉토리 목록 조회
{
"type": "list_directory",
"path": "/workspace"
}
🎬 실전 시나리오
시나리오 1: 멀티턴 대화 (파일시스템 상태 유지)
// 1. 세션 생성
ws.send(JSON.stringify({
jsonrpc: '2.0',
id: 1,
method: 'session.create',
params: { language: 'python' }
}));
// 2. 첫 번째 코드 실행 (변수 정의)
ws.send(JSON.stringify({
jsonrpc: '2.0',
id: 2,
method: 'session.execute',
params: {
sessionId: sessionId,
command: {
type: 'write_file',
path: '/workspace/data.py',
content: 'x = 10\ny = 20'
}
}
}));
// 3. 두 번째 코드 실행 (변수 사용)
ws.send(JSON.stringify({
jsonrpc: '2.0',
id: 3,
method: 'session.execute',
params: {
sessionId: sessionId,
command: {
type: 'write_file',
path: '/workspace/calc.py',
content: 'from data import x, y\nprint(f"Sum: {x + y}")'
}
}
}));
// 4. 실행
ws.send(JSON.stringify({
jsonrpc: '2.0',
id: 4,
method: 'session.execute',
params: {
sessionId: sessionId,
command: {
type: 'execute_shell',
commandName: 'python3',
args: ['/workspace/calc.py']
}
}
}));
// Output: Sum: 30
시나리오 2: 패키지 설치 및 사용
// 1. 세션 생성
ws.send(JSON.stringify({
jsonrpc: '2.0',
id: 1,
method: 'session.create',
params: { language: 'python' }
}));
// 2. pip 패키지 설치
ws.send(JSON.stringify({
jsonrpc: '2.0',
id: 2,
method: 'session.execute',
params: {
sessionId: sessionId,
command: {
type: 'execute_shell',
commandName: 'pip',
args: ['install', '--no-cache-dir', 'requests']
}
}
}));
// 3. 패키지 사용 코드 작성
ws.send(JSON.stringify({
jsonrpc: '2.0',
id: 3,
method: 'session.execute',
params: {
sessionId: sessionId,
command: {
type: 'write_file',
path: '/workspace/api_test.py',
content: 'import requests\nprint("requests version:", requests.__version__)'
}
}
}));
// 4. 실행
ws.send(JSON.stringify({
jsonrpc: '2.0',
id: 4,
method: 'session.execute',
params: {
sessionId: sessionId,
command: {
type: 'execute_shell',
commandName: 'python3',
args: ['/workspace/api_test.py']
}
}
}));
시나리오 3: 데이터 파일 처리
// 1. CSV 데이터 작성
ws.send(JSON.stringify({
jsonrpc: '2.0',
id: 1,
method: 'session.execute',
params: {
sessionId: sessionId,
command: {
type: 'write_file',
path: '/workspace/data.csv',
content: 'name,age\nAlice,30\nBob,25\nCharlie,35'
}
}
}));
// 2. 데이터 처리 코드
ws.send(JSON.stringify({
jsonrpc: '2.0',
id: 2,
method: 'session.execute',
params: {
sessionId: sessionId,
command: {
type: 'write_file',
path: '/workspace/process.py',
content: `
import csv
with open('/workspace/data.csv', 'r') as f:
reader = csv.DictReader(f)
total_age = sum(int(row['age']) for row in reader)
print(f"Total age: {total_age}")
`
}
}
}));
// 3. 실행
ws.send(JSON.stringify({
jsonrpc: '2.0',
id: 3,
method: 'session.execute',
params: {
sessionId: sessionId,
command: {
type: 'execute_shell',
commandName: 'python3',
args: ['/workspace/process.py']
}
}
}));
// 4. 결과 파일 읽기
ws.send(JSON.stringify({
jsonrpc: '2.0',
id: 4,
method: 'session.execute',
params: {
sessionId: sessionId,
command: {
type: 'read_file',
path: '/workspace/data.csv'
}
}
}));
⚙️ 세션 설정 옵션
SessionConfig 파라미터
{
"language": "python",
"idleTimeoutMinutes": 30,
"maxLifetimeMinutes": 120,
"memoryLimitMB": 512,
"cpuShares": 1024,
"dockerImage": "codebeaker-python:latest"
}
파라미터 설명:
language: 언어 선택 (python, javascript, go, csharp)idleTimeoutMinutes: 유휴 타임아웃 (기본: 30분)maxLifetimeMinutes: 최대 생명 주기 (기본: 120분)memoryLimitMB: 메모리 제한 (기본: 512MB)cpuShares: CPU 점유율 (기본: 1024)dockerImage: 커스텀 Docker 이미지 (선택 사항)
🔍 에러 처리
에러 응답 형식
{
"jsonrpc": "2.0",
"id": 1,
"error": {
"code": -32600,
"message": "Invalid Request",
"data": "Additional error details"
}
}
일반적인 에러 코드
| 코드 | 의미 | 해결 방법 |
|---|---|---|
| -32600 | Invalid Request | JSON-RPC 형식 확인 |
| -32601 | Method not found | 메서드 이름 확인 (session.create, session.execute 등) |
| -32602 | Invalid params | 파라미터 형식 확인 |
| -32603 | Internal error | 서버 로그 확인 |
명령 실행 에러
{
"jsonrpc": "2.0",
"id": 2,
"result": {
"success": false,
"result": null,
"error": "File not found: /workspace/missing.py",
"durationMs": 15
}
}
📊 성능 특성
세션 기반 vs 단일 실행
단일 실행 (Stateless):
- Container create: ~200ms
- Code execution: 100-500ms
- Container cleanup: ~100ms
- Total: ~400-800ms
세션 실행 (Stateful):
- First execution: ~400ms (세션 생성)
- Subsequent: ~100-200ms (컨테이너 재사용)
- Improvement: 50-75% faster
최적화 팁
- 세션 재사용: 여러 실행이 필요한 경우 세션을 유지하세요
- 배치 명령: 여러 명령을 순차적으로 실행하여 왕복 시간 절약
- 메모리 관리: 필요한 만큼만 메모리 할당 (기본 512MB)
- 세션 정리: 사용 완료 후 session.close로 명시적 종료
🔧 문제 해결
WebSocket 연결 실패
- API 서버 실행 확인:
curl http://localhost:5000/health
- WebSocket 엔드포인트 확인:
wscat -c ws://localhost:5000/ws/jsonrpc
세션 생성 실패
- Docker 이미지 확인:
docker images | grep codebeaker
- Docker 서비스 상태:
docker ps
docker info
명령 실행 실패
- 세션 상태 확인:
{
"jsonrpc": "2.0",
"id": 1,
"method": "session.list",
"params": {}
}
- 컨테이너 로그 확인:
docker logs <container-id>
세션 자동 종료
세션은 다음 조건에서 자동 종료됩니다:
- IdleTimeout (기본 30분) 동안 활동이 없는 경우
- MaxLifetime (기본 120분) 초과
세션 유지 방법:
- 주기적으로 명령 실행
- IdleTimeout 값 조정
- session.list로 세션 상태 모니터링
🛡️ 보안 고려사항
- 컨테이너 격리: 각 세션은 독립된 Docker 컨테이너에서 실행
- 네트워크 격리: 기본적으로 네트워크 비활성화 (NetworkMode: "none")
- 리소스 제한: 메모리와 CPU 제한으로 DoS 방지
- 자동 정리: 유휴 세션 자동 종료로 리소스 관리
- 파일시스템 격리: /workspace 디렉토리 내부로 제한
📝 라이선스
MIT License - 자유롭게 사용, 수정, 배포 가능