Skip to main content

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 RuntimeDeno Runtime
์‹œ์ž‘ ์‹œ๊ฐ„2000ms80ms (25๋ฐฐ ๋น ๋ฆ„)
๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋Ÿ‰250MB30MB (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"
}
}

์ผ๋ฐ˜์ ์ธ ์—๋Ÿฌ ์ฝ”๋“œโ€‹

์ฝ”๋“œ์˜๋ฏธํ•ด๊ฒฐ ๋ฐฉ๋ฒ•
-32600Invalid RequestJSON-RPC ํ˜•์‹ ํ™•์ธ
-32601Method not found๋ฉ”์„œ๋“œ ์ด๋ฆ„ ํ™•์ธ (session.create, session.execute ๋“ฑ)
-32602Invalid paramsํŒŒ๋ผ๋ฏธํ„ฐ ํ˜•์‹ ํ™•์ธ
-32603Internal 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

์ตœ์ ํ™” ํŒโ€‹

  1. ์„ธ์…˜ ์žฌ์‚ฌ์šฉ: ์—ฌ๋Ÿฌ ์‹คํ–‰์ด ํ•„์š”ํ•œ ๊ฒฝ์šฐ ์„ธ์…˜์„ ์œ ์ง€ํ•˜์„ธ์š”
  2. ๋ฐฐ์น˜ ๋ช…๋ น: ์—ฌ๋Ÿฌ ๋ช…๋ น์„ ์ˆœ์ฐจ์ ์œผ๋กœ ์‹คํ–‰ํ•˜์—ฌ ์™•๋ณต ์‹œ๊ฐ„ ์ ˆ์•ฝ
  3. ๋ฉ”๋ชจ๋ฆฌ ๊ด€๋ฆฌ: ํ•„์š”ํ•œ ๋งŒํผ๋งŒ ๋ฉ”๋ชจ๋ฆฌ ํ• ๋‹น (๊ธฐ๋ณธ 512MB)
  4. ์„ธ์…˜ ์ •๋ฆฌ: ์‚ฌ์šฉ ์™„๋ฃŒ ํ›„ session.close๋กœ ๋ช…์‹œ์  ์ข…๋ฃŒ

๐Ÿ”ง ๋ฌธ์ œ ํ•ด๊ฒฐโ€‹

WebSocket ์—ฐ๊ฒฐ ์‹คํŒจโ€‹

  1. API ์„œ๋ฒ„ ์‹คํ–‰ ํ™•์ธ:
curl http://localhost:5000/health
  1. WebSocket ์—”๋“œํฌ์ธํŠธ ํ™•์ธ:
wscat -c ws://localhost:5000/ws/jsonrpc

์„ธ์…˜ ์ƒ์„ฑ ์‹คํŒจโ€‹

  1. Docker ์ด๋ฏธ์ง€ ํ™•์ธ:
docker images | grep codebeaker
  1. Docker ์„œ๋น„์Šค ์ƒํƒœ:
docker ps
docker info

๋ช…๋ น ์‹คํ–‰ ์‹คํŒจโ€‹

  1. ์„ธ์…˜ ์ƒํƒœ ํ™•์ธ:
{
"jsonrpc": "2.0",
"id": 1,
"method": "session.list",
"params": {}
}
  1. ์ปจํ…Œ์ด๋„ˆ ๋กœ๊ทธ ํ™•์ธ:
docker logs <container-id>

์„ธ์…˜ ์ž๋™ ์ข…๋ฃŒโ€‹

์„ธ์…˜์€ ๋‹ค์Œ ์กฐ๊ฑด์—์„œ ์ž๋™ ์ข…๋ฃŒ๋ฉ๋‹ˆ๋‹ค:

  • IdleTimeout (๊ธฐ๋ณธ 30๋ถ„) ๋™์•ˆ ํ™œ๋™์ด ์—†๋Š” ๊ฒฝ์šฐ
  • MaxLifetime (๊ธฐ๋ณธ 120๋ถ„) ์ดˆ๊ณผ

์„ธ์…˜ ์œ ์ง€ ๋ฐฉ๋ฒ•:

  • ์ฃผ๊ธฐ์ ์œผ๋กœ ๋ช…๋ น ์‹คํ–‰
  • IdleTimeout ๊ฐ’ ์กฐ์ •
  • session.list๋กœ ์„ธ์…˜ ์ƒํƒœ ๋ชจ๋‹ˆํ„ฐ๋ง

๐Ÿ›ก๏ธ ๋ณด์•ˆ ๊ณ ๋ ค์‚ฌํ•ญโ€‹

  1. ์ปจํ…Œ์ด๋„ˆ ๊ฒฉ๋ฆฌ: ๊ฐ ์„ธ์…˜์€ ๋…๋ฆฝ๋œ Docker ์ปจํ…Œ์ด๋„ˆ์—์„œ ์‹คํ–‰
  2. ๋„คํŠธ์›Œํฌ ๊ฒฉ๋ฆฌ: ๊ธฐ๋ณธ์ ์œผ๋กœ ๋„คํŠธ์›Œํฌ ๋น„ํ™œ์„ฑํ™” (NetworkMode: "none")
  3. ๋ฆฌ์†Œ์Šค ์ œํ•œ: ๋ฉ”๋ชจ๋ฆฌ์™€ CPU ์ œํ•œ์œผ๋กœ DoS ๋ฐฉ์ง€
  4. ์ž๋™ ์ •๋ฆฌ: ์œ ํœด ์„ธ์…˜ ์ž๋™ ์ข…๋ฃŒ๋กœ ๋ฆฌ์†Œ์Šค ๊ด€๋ฆฌ
  5. ํŒŒ์ผ์‹œ์Šคํ…œ ๊ฒฉ๋ฆฌ: /workspace ๋””๋ ‰ํ† ๋ฆฌ ๋‚ด๋ถ€๋กœ ์ œํ•œ

๐Ÿ“ ๋ผ์ด์„ ์Šคโ€‹

MIT License - ์ž์œ ๋กญ๊ฒŒ ์‚ฌ์šฉ, ์ˆ˜์ •, ๋ฐฐํฌ ๊ฐ€๋Šฅ