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 - ์์ ๋กญ๊ฒ ์ฌ์ฉ, ์์ , ๋ฐฐํฌ ๊ฐ๋ฅ