Skip to main content

백 엔드 서비스 설정

API, 웹 백 엔드, 마이크로 서비스 및 백그라운드 작업자와 같은 서버 쪽 애플리케이션에서 Copilot SDK를 실행합니다. CLI는 백 엔드 코드가 네트워크를 통해 연결하는 헤드리스 서버로 실행됩니다.

최적 대상: 웹앱 백 엔드, API 서비스, 내부 도구, CI/CD 통합, 모든 서버 쪽 워크로드.

작동 방식

SDK가 CLI 자식 프로세스를 생성하는 대신 헤드리스 서버 모드에서 독립적으로 CLI를 실행합니다. 백엔드는 Connection 옵션(UriConnection)을 사용하여 TCP를 통해 여기에 연결합니다.

다이어그램: 설명된 프로세스를 보여 주는 순서도입니다.

주요 특징:

  • CLI는 영구 서버 프로세스로 실행됩니다(요청당 생성되지 않음)
  • TCP를 통해 SDK 연결 - CLI 및 앱은 다른 컨테이너에서 실행할 수 있습니다.
  • 여러 SDK 클라이언트가 하나의 CLI 서버를 공유할 수 있습니다.
  • 모든 인증 메서드(GitHub 토큰, env vars, BYOK)에서 작동합니다.

아키텍처: 자동 관리 및 외부 CLI

다이어그램: 설명된 프로세스를 보여 주는 순서도입니다.

1단계: 헤드리스 모드에서 CLI를 시작합니다

CLI를 백그라운드 서버로 실행합니다.

# Start with a specific port
copilot --headless --port 4321

# Or let it pick a random port (prints the URL)
copilot --headless
# Output: Listening on http://localhost:52431

기본적으로 헤드리스 서버는 루프백(127.0.0.1)의 연결만 허용합니다. 네트워크의 다른 컴퓨터와 같은 다른 호스트의 연결을 허용하려면 다음을 사용하여 루프백이 아닌 주소 --host에 바인딩합니다.

copilot --headless --host 0.0.0.0 --port 4321

프로덕션의 경우 시스템 서비스 또는 컨테이너에서 실행합니다.

참고

Copilot CLI에 대한 공식 미리 빌드된 Docker 이미지는 없습니다. GitHub 릴리스에서 직접 빌드할 수 있습니다.

FROM debian:bookworm-slim
ARG COPILOT_VERSION=1.0.7
RUN apt-get update \
    && apt-get install -y --no-install-recommends ca-certificates wget \
    && ARCH=$(dpkg --print-architecture) \
    && case "${ARCH}" in amd64) COPILOT_ARCH="x64" ;; arm64) COPILOT_ARCH="arm64" ;; *) echo "Unsupported: ${ARCH}" && exit 1 ;; esac \
    && wget -q "https://github.com/github/copilot-cli/releases/download/v${COPILOT_VERSION}/copilot-linux-${COPILOT_ARCH}.tar.gz" \
    && tar -xzf "copilot-linux-${COPILOT_ARCH}.tar.gz" \
    && mv copilot /usr/local/bin/ \
    && rm "copilot-linux-${COPILOT_ARCH}.tar.gz" \
    && apt-get purge -y wget && apt-get autoremove -y && rm -rf /var/lib/apt/lists/*
ENTRYPOINT ["copilot"]
# Build the image
docker build --build-arg COPILOT_VERSION=1.0.7 -t copilot-cli:latest .

# For remote deployments (Kubernetes, ACI, etc.), push to your registry
docker tag copilot-cli:latest your-registry/copilot-cli:latest
docker push your-registry/copilot-cli:latest
# Docker — must bind to 0.0.0.0 so the container's published port is reachable
docker run -d --name copilot-cli \
    -p 4321:4321 \
    -e COPILOT_GITHUB_TOKEN="$TOKEN" \
    copilot-cli:latest \
    --headless --host 0.0.0.0 --port 4321

# systemd
[Service]
ExecStart=/usr/local/bin/copilot --headless --port 4321
Environment=COPILOT_GITHUB_TOKEN=your-token
Restart=always

2단계: SDK 연결

TypeScript
import { CopilotClient } from "@github/copilot-sdk";

const client = new CopilotClient({
    cliUrl: "localhost:4321",
});

const session = await client.createSession({
    sessionId: `user-${userId}-${Date.now()}`,
    model: "gpt-4.1",
});

const response = await session.sendAndWait({ prompt: req.body.message });
res.json({ content: response?.data.content });
Python
from copilot import CopilotClient, RuntimeConnection
from copilot.session import PermissionHandler

client = CopilotClient(
    connection=RuntimeConnection.for_uri("localhost:4321"),
)
await client.start()

session = await client.create_session(on_permission_request=PermissionHandler.approve_all, model="gpt-4.1", session_id=f"user-{user_id}-{int(time.time())}")

response = await session.send_and_wait(message)
Go
package main

import (
    "context"
    "fmt"
    "time"
    copilot "github.com/github/copilot-sdk/go"
)

func main() {
    ctx := context.Background()
    userID := "user1"
    message := "Hello"

    client := copilot.NewClient(&copilot.ClientOptions{
        Connection: copilot.UriConnection{URL: "localhost:4321"},
    })
    client.Start(ctx)
    defer client.Stop()

    session, _ := client.CreateSession(ctx, &copilot.SessionConfig{
        SessionID: fmt.Sprintf("user-%s-%d", userID, time.Now().Unix()),
        Model:     "gpt-4.1",
    })

    response, _ := session.SendAndWait(ctx, copilot.MessageOptions{Prompt: message})
    _ = response
}
client := copilot.NewClient(&copilot.ClientOptions{
    Connection: copilot.UriConnection{URL: "localhost:4321"},
})
client.Start(ctx)
defer client.Stop()

session, _ := client.CreateSession(ctx, &copilot.SessionConfig{
    SessionID: fmt.Sprintf("user-%s-%d", userID, time.Now().Unix()),
    Model:     "gpt-4.1",
})

response, _ := session.SendAndWait(ctx, copilot.MessageOptions{Prompt: message})
.NET
using GitHub.Copilot;

var userId = "user1";
var message = "Hello";

var client = new CopilotClient(new CopilotClientOptions
{
    Connection = RuntimeConnection.ForUri("localhost:4321"),
});

await using var session = await client.CreateSessionAsync(new SessionConfig
{
    SessionId = $"user-{userId}-{DateTimeOffset.UtcNow.ToUnixTimeSeconds()}",
    Model = "gpt-4.1",
});

var response = await session.SendAndWaitAsync(
    new MessageOptions { Prompt = message });
var client = new CopilotClient(new CopilotClientOptions
{
    Connection = RuntimeConnection.ForUri("localhost:4321"),
});

await using var session = await client.CreateSessionAsync(new SessionConfig
{
    SessionId = $"user-{userId}-{DateTimeOffset.UtcNow.ToUnixTimeSeconds()}",
    Model = "gpt-4.1",
});

var response = await session.SendAndWaitAsync(
    new MessageOptions { Prompt = message });
Java
import com.github.copilot.sdk.CopilotClient;
import com.github.copilot.sdk.events.*;
import com.github.copilot.sdk.json.*;

var userId = "user1";
var message = "Hello!";

var client = new CopilotClient(new CopilotClientOptions()
    .setCliUrl("localhost:4321")
);

try {
    client.start().get();

    var session = client.createSession(new SessionConfig()
        .setSessionId(String.format("user-%s-%d", userId, System.currentTimeMillis() / 1000))
        .setModel("gpt-4.1")
        .setOnPermissionRequest(PermissionHandler.APPROVE_ALL)
    ).get();

    var response = session.sendAndWait(new MessageOptions()
        .setPrompt(message)).get();
} finally {
    client.stop().get();
}

백 엔드 서비스에 대한 인증

환경 변수 토큰

가장 간단한 방법은 CLI 서버에서 토큰을 설정하는 것입니다.

다이어그램: 설명된 프로세스를 보여 주는 순서도입니다.

# All requests use this token
export COPILOT_GITHUB_TOKEN="gho_service_account_token"
copilot --headless --port 4321

사용자별 토큰(OAuth)

세션을 만들 때 개별 사용자 토큰을 전달합니다. 전체 흐름은 GitHub OAuth 설정을 참조하세요.

// Your API receives user tokens from your auth layer
app.post("/chat", authMiddleware, async (req, res) => {
    const client = new CopilotClient({
        cliUrl: "localhost:4321",
        gitHubToken: req.user.githubToken,
        useLoggedInUser: false,
    });

    const session = await client.createSession({
        sessionId: `user-${req.user.id}-chat`,
        model: "gpt-4.1",
    });

    const response = await session.sendAndWait({
        prompt: req.body.message,
    });

    res.json({ content: response?.data.content });
});

BYOK(GitHub 인증 없음)

모델 공급자에 대해 사용자 고유의 API 키를 사용합니다. 자세한 내용을 보려면 BYOK (bring your own key)(을)를 참조하세요.

const client = new CopilotClient({
    cliUrl: "localhost:4321",
});

const session = await client.createSession({
    model: "gpt-4.1",
    provider: {
        type: "openai",
        baseUrl: "https://api.openai.com/v1",
        apiKey: process.env.OPENAI_API_KEY,
    },
});

일반적인 백 엔드 패턴

Express를 사용하는 Web API

다이어그램: 설명된 프로세스를 보여 주는 순서도입니다.

import express from "express";
import { CopilotClient } from "@github/copilot-sdk";

const app = express();
app.use(express.json());

// Single shared CLI connection
const client = new CopilotClient({
    cliUrl: process.env.CLI_URL || "localhost:4321",
});

app.post("/api/chat", async (req, res) => {
    const { sessionId, message } = req.body;

    // Create or resume session
    let session;
    try {
        session = await client.resumeSession(sessionId);
    } catch {
        session = await client.createSession({
            sessionId,
            model: "gpt-4.1",
        });
    }

    const response = await session.sendAndWait({ prompt: message });
    res.json({
        sessionId,
        content: response?.data.content,
    });
});

app.listen(3000);

백그라운드 작업자

import { CopilotClient } from "@github/copilot-sdk";

const client = new CopilotClient({
    cliUrl: process.env.CLI_URL || "localhost:4321",
});

// Process jobs from a queue
async function processJob(job: Job) {
    const session = await client.createSession({
        sessionId: `job-${job.id}`,
        model: "gpt-4.1",
    });

    const response = await session.sendAndWait({
        prompt: job.prompt,
    });

    await saveResult(job.id, response?.data.content);
    await session.disconnect();  // Clean up after job completes
}

Docker Compose 배포

version: "3.8"

services:
  copilot-cli:
    image: copilot-cli:latest  # See "Step 1" above for how to build this image
    command: ["--headless", "--host", "0.0.0.0", "--port", "4321"]
    environment:
      - COPILOT_GITHUB_TOKEN=${COPILOT_GITHUB_TOKEN}
    ports:
      - "4321:4321"
    restart: always
    volumes:
      - session-data:/root/.copilot/session-state

  api:
    build: .
    environment:
      - CLI_URL=copilot-cli:4321
    depends_on:
      - copilot-cli
    ports:
      - "3000:3000"

volumes:
  session-data:

다이어그램: 설명된 프로세스를 보여 주는 순서도입니다.

건강 상태 검사

CLI 서버의 상태를 모니터링합니다.

// Periodic health check
async function checkCLIHealth(): Promise<boolean> {
    try {
        const status = await client.getStatus();
        return status !== undefined;
    } catch {
        return false;
    }
}

세션 정리

백 엔드 서비스는 리소스 누출을 방지하기 위해 세션을 적극적으로 정리해야 합니다.

// Clean up expired sessions periodically
async function cleanupSessions(maxAgeMs: number) {
    const sessions = await client.listSessions();
    const now = Date.now();

    for (const session of sessions) {
        const age = now - new Date(session.createdAt).getTime();
        if (age > maxAgeMs) {
            await client.deleteSession(session.sessionId);
        }
    }
}

// Run every hour
setInterval(() => cleanupSessions(24 * 60 * 60 * 1000), 60 * 60 * 1000);

Limitations

LimitationDetails
단일 CLI 서버 = 단일 실패 지점HA 패턴은 확장성 및 멀티 테넌시을 참조하십시오.
SDK와 CLI 간에 기본 제공 인증 없음네트워크 경로 보호(동일한 호스트, VPC 등)
로컬 디스크의 세션 상태컨테이너 다시 시작을 위한 영구 스토리지 탑재
30분 유휴 시간 제한활동이 없는 세션은 자동으로 정리됩니다.

이동 시기

필요다음 가이드
여러 CLI 서버/고가용성
확장성 및 멀티 테넌시
사용자용 GitHub 계정 인증
GitHub OAuth 설정
사용자 고유의 모델 키
BYOK (bring your own key)

다음 단계