{"meta":{"title":"클라우드 세션","intro":"클라우드 세션은 Mission Control을 통해 GitHub에서 호스팅되는 컴퓨팅 리소스에서 Copilot 작업을 실행합니다. 앱이 사용자의 컴퓨터 또는 서버에서 로컬 Copilot CLI 세션을 시작하는 대신 원격으로 실행되는 세션을 만들어야 할 때 사용합니다.","product":"GitHub Copilot","breadcrumbs":[{"href":"/ko/copilot","title":"GitHub Copilot"},{"href":"/ko/copilot/how-tos","title":"방법"},{"href":"/ko/copilot/how-tos/copilot-sdk","title":"코필로트 SDK"},{"href":"/ko/copilot/how-tos/copilot-sdk/features","title":"기능"},{"href":"/ko/copilot/how-tos/copilot-sdk/features/cloud-sessions","title":"클라우드 세션"}],"documentType":"article"},"body":"# 클라우드 세션\n\n클라우드 세션은 Mission Control을 통해 GitHub에서 호스팅되는 컴퓨팅 리소스에서 Copilot 작업을 실행합니다. 앱이 사용자의 컴퓨터 또는 서버에서 로컬 Copilot CLI 세션을 시작하는 대신 원격으로 실행되는 세션을 만들어야 할 때 사용합니다.\n\n<!-- markdownlint-disable GHD046 GHD005 -->\n\n<!-- Suppressed: GHD046 (outdated release terminology), GHD005 (hardcoded data variable) -->\n\n## 사전 요구 사항\n\n클라우드 세션을 만들기 전에 다음을 확인합니다.\n\n* 사용자에게 클라우드 에이전트 자격으로 Copilot 액세스 권한이 있습니다.\n* 세션은 사용자 토큰 또는 로그인한 Copilot CLI ID를 사용하여 GitHub 인증할 수 있습니다.\n* 세션을 GitHub 리포지토리와 연결할 수 있습니다. SDK 유형에서는 선택 사항이지만 Mission Control 및 클라우드 에이전트에 리포지토리 컨텍스트가 있도록 권장됩니다.\n* 조직 정책을 사용하면 클라우드 화면에서 원격 제어 및 세션을 볼 수 있습니다.\n\n## 클라우드 세션 만들기\n\n클라우드 세션을 만들려면 세션 `cloud` 만들기 옵션을 설정합니다. 리포지토리 메타데이터를 포함하여 클라우드 세션을 GitHub 리포지토리와 연결할 수 있습니다.\n\n<!-- tabs:start -->\n\n### TypeScript\n\n```typescript\nimport { CopilotClient } from \"@github/copilot-sdk\";\n\nconst client = new CopilotClient();\nawait client.start();\n\nconst session = await client.createSession({\n  onPermissionRequest: async () => ({ kind: \"approve-once\" }),\n  cloud: {\n    repository: {\n      owner: \"github\",\n      name: \"copilot-sdk\",\n      branch: \"main\",\n    },\n  },\n});\n```\n\n### Python\n\n```python\nfrom copilot import (\n    CloudSessionOptions,\n    CloudSessionRepository,\n    CopilotClient,\n    PermissionHandler,\n)\n\nclient = CopilotClient()\nawait client.start()\n\nsession = await client.create_session(\n    on_permission_request=PermissionHandler.approve_all,\n    cloud=CloudSessionOptions(\n        repository=CloudSessionRepository(\n            owner=\"github\",\n            name=\"copilot-sdk\",\n            branch=\"main\",\n        )\n    ),\n)\n```\n\n### 이동\n\n```golang\nclient := copilot.NewClient(nil)\nif err := client.Start(ctx); err != nil {\n    return err\n}\n\nsession, err := client.CreateSession(ctx, &copilot.SessionConfig{\n    Cloud: &copilot.CloudSessionOptions{\n        Repository: &copilot.CloudSessionRepository{\n            Owner:  \"github\",\n            Name:   \"copilot-sdk\",\n            Branch: \"main\",\n        },\n    },\n    OnPermissionRequest: func(req copilot.PermissionRequest, inv copilot.PermissionInvocation) (rpc.PermissionDecision, error) {\n        return &rpc.PermissionDecisionApproveOnce{}, nil\n    },\n})\n_ = session\n```\n\n### .NET\n\n```csharp\nawait using var client = new CopilotClient();\n\nvar session = await client.CreateSessionAsync(new SessionConfig\n{\n    Cloud = new CloudSessionOptions\n    {\n        Repository = new CloudSessionRepository\n        {\n            Owner = \"github\",\n            Name = \"copilot-sdk\",\n            Branch = \"main\",\n        },\n    },\n    OnPermissionRequest = (req, inv) =>\n        Task.FromResult(PermissionDecision.ApproveOnce()),\n});\n```\n\n### Java\n\n```java\nimport com.github.copilot.CopilotClient;\nimport com.github.copilot.rpc.*;\n\ntry (var client = new CopilotClient()) {\n    client.start().get();\n\n    var session = client.createSession(\n        new SessionConfig()\n            .setCloud(new CloudSessionOptions()\n                .setRepository(new CloudSessionRepository()\n                    .setOwner(\"github\")\n                    .setName(\"copilot-sdk\")\n                    .setBranch(\"main\")))\n            .setOnPermissionRequest(PermissionHandler.APPROVE_ALL)\n    ).get();\n}\n```\n\n### 러스트\n\n```rust\nuse std::sync::Arc;\nuse github_copilot_sdk::{CloudSessionOptions, CloudSessionRepository, SessionConfig};\nuse github_copilot_sdk::handler::ApproveAllHandler;\n\nlet session = client.create_session(\n    SessionConfig::default()\n        .with_cloud(CloudSessionOptions::with_repository(\n            CloudSessionRepository::new(\"github\", \"copilot-sdk\").with_branch(\"main\"),\n        ))\n        .with_permission_handler(Arc::new(ApproveAllHandler)),\n).await?;\n```\n\n<!-- tabs:end -->\n\n## 첫 번째 프롬프트 보내기\n\n클라우드 세션은 두 단계로 초기화됩니다: `createSession`는 Mission Control이 작업을 예약하는 즉시 처리되지만, 원격 `copilot-agent` 워커가 연결되어 `session.start`를 내보내기까지는 1\\~2초가 더 걸립니다. 그 전에 `session.send`을(를) 호출하면 런타임의 `RemoteSession.send`이(가) `\"Remote session is still starting\"`을(를) 발생시키지만, 스키마 래퍼는 fire-and-forget 방식이라 **오류를 조용히 처리하면서도** 여전히 코드에 새 `messageId`을(를) 반환합니다. 프롬프트가 서버에서 삭제되고 작업자에게 도달하지 않습니다.\n\n안정적으로 보내려면 보내기 **전에** 이벤트를 구독하고 다음과 같은 `session.start``producer`첫 번째 `\"copilot-agent\"` 이벤트를 기다립니다.\n\n<!-- docs-validate: skip -->\n\n```typescript\nimport { CopilotClient, type CopilotSession } from \"@github/copilot-sdk\";\n\nconst client = new CopilotClient();\nawait client.start();\n\nconst session: CopilotSession = await client.createSession({\n  streaming: true, // required for assistant.message_delta to fire\n  cloud: { repository: { owner: \"github\", name: \"copilot-sdk\" } },\n  onPermissionRequest: async () => ({ kind: \"approve-once\" }),\n});\n\n// Subscribe BEFORE sending so you don't miss the start event.\nconst ready = new Promise<void>((resolve) => {\n  const off = session.on(\"session.start\", (event) => {\n    if (event.data?.producer === \"copilot-agent\") {\n      off();\n      resolve();\n    }\n  });\n});\n\nawait ready;\nawait session.send({ prompt: \"Summarize the README\" });\n```\n\n몇 가지 참고 사항:\n\n* 런타임이 `streaming: true` 이벤트를 내보내도록 `createSession`에서 `assistant.message_delta`을 설정합니다. 이 신호가 없으면 받을 수 있는 어시스턴트 신호는 마지막 `assistant.message`뿐입니다. 배치 처리에는 괜찮지만, 실시간 UI를 렌더링하고 있다면 채팅이 멈춘 것처럼 보일 것입니다.\n  [스트리밍 세션 이벤트](/ko/copilot/how-tos/copilot-sdk/features/streaming-events)을(를) 참조하세요.\n* 오직 **첫 번째**`session.send`만 이 경쟁 상태의 영향을 받습니다. 런타임이 세션 수명 동안 설정된 상태이므로 `hasSessionStarted` 동일한 세션에 대한 후속 전송은 정상적으로 작동합니다.\n* 중단된 Mission Control 프로비저닝이 앱을 영원히 중단하지 않도록 `ready` 프라미스 주위에 시간 제한(예: 60s)을 적용합니다.\n* 동일한 패턴은 모든 SDK 언어에 동일하게 적용됩니다. `session.start`을 구독하고, `producer === \"copilot-agent\"`을 확인한 다음, `send`를 호출합니다.\n\n## Mission Control URL에 접속하기\n\n클라우드 세션은 기본적으로 원격입니다. 작업자가 연결되면 Mission Control에서 `https://github.com/copilot/tasks/{sessionId}` 세션을 게시하고 런타임에서 URL을 사용하여 `session.info` 이벤트를 내보냅니다. 호출할 \\*\\*\\*\\* 필요가 `remote.enable()`. API는 로컬 세션을 Mission Control으로 승격하기 위한 것입니다.\n\nURL을 캡처하려면 `session.info`을(를) 구독하고 `infoType: \"remote\"`으로 필터링하세요:\n\n<!-- docs-validate: skip -->\n\n```typescript\nsession.on(\"session.info\", (event) => {\n  if (event.data?.infoType === \"remote\" && event.data.url) {\n    console.log(\"Open from web or mobile:\", event.data.url);\n    // For example, surface in your UI as a shareable link or QR code.\n  }\n});\n```\n\n이 이벤트는 `session.start` 직후에 실행됩니다. 렌더러가 이벤트가 이미 발생한 뒤에 마운트되는 경우, 앱 상태에 세션 레코드와 함께 URL을 저장하고 다시 마운트될 때 리하이드레이션하세요. 런타임은 자체적으로 `session.info`를 다시 내보내지 않습니다.\n\n`remote: true`를 통해 승격된 로컬 세션의 동일한 배선에 대해서는 [원격 세션](/ko/copilot/how-tos/copilot-sdk/features/remote-sessions)을 참조하세요.\n\n## 리포지토리 연결\n\n`cloud.repository` 개체는 클라우드 세션을 GitHub 리포지토리와 연결합니다.\n\n| Field    | 필수  | Description                                                           |\n| -------- | --- | --------------------------------------------------------------------- |\n| `owner`  | Yes | 리포지토리 소유자 또는 조직.                                                      |\n| `name`   | Yes | 리포지토리 이름입니다.                                                          |\n| `branch` | No  | 리포지토리 컨텍스트에 사용할 분기입니다. 런타임에서 기본 분기 또는 현재 리포지토리 컨텍스트를 선택할 수 있도록 생략합니다. |\n\n리포지토리 연결은 SDK 형식에서 선택 사항이지만 앱이 대상 리포지토리를 알 때마다 포함합니다. 이를 통해 Mission Control은 올바른 컨텍스트에서 세션을 표시하고 클라우드 에이전트에 보다 명확한 시작점을 제공합니다.\n\n특정 분기에서 작업을 시작해야 하는 경우에 사용합니다 `branch` . 앱이 풀 리퀘스트, 이슈 분류 흐름 또는 배포 워크플로에서 세션을 생성하는 경우, 사용자에게 표시되는 작업에 해당하는 브랜치를 전달하세요.\n\n## 클라우드 세션 다시 열기\n\n이 옵션은 `cloud` 새 세션을 만들 때만 적용됩니다. 기존 클라우드 세션을 다시 시작하려면 SDK 언어에 대한 표준 다시 시작 API를 사용합니다.\n\n```typescript\nconst session = await client.resumeSession(\"session-id\", {\n  onPermissionRequest: async () => ({ kind: \"approve-once\" }),\n});\n```\n\n다시 시작할 때는 `cloud`를 다시 전달하지 마세요. 저장된 세션 메타데이터는 세션이 클라우드 지원임을 확인하고 다시 시작은 일반 세션 다시 시작 경로를 따릅니다.\n\n## 조직 정책 및 자격\n\n사용자 또는 조직이 클라우드 에이전트 실행을 받을 자격이 없거나 조직 수준 정책이 흐름을 차단하는 경우 클라우드 세션 생성이 실패할 수 있습니다. 특히 클라우드 샌드박스에 대한 정책은 클라이언트가 클라우드 작업을 만들지 못하게 할 수 있습니다.\n\n이 경우 런타임은 클라우드 작업 생성에 대해 `\"policy_blocked\"` 실패 사유를 보고합니다. 일시적인 인프라 오류가 아닌 권한 부여 또는 정책 결과로 처리합니다.\n\nTypeScript에서 다시 시도하기 전에 이유를 확인합니다.\n\n```typescript\ntry {\n  await client.createSession({ cloud: { repository } });\n} catch (error) {\n  if ((error as { reason?: string }).reason === \"policy_blocked\") {\n    // Show an admin-facing message or link to org policy settings.\n  }\n  throw error;\n}\n```\n\nSDK 오류가 다르게 표시되는 언어에서는 표시된 오류 원인이나 코드를 검사하고 `\"policy_blocked\"`를 명시적으로 처리합니다. 정책 변경 없이 재시도는 성공하지 못할 것으로 예상됩니다.\n\n## 통합 ID 및 라우팅\n\n클라우드 세션은 `Copilot-Integration-Id` 환경 변수에서 파생된 `GITHUB_COPILOT_INTEGRATION_ID` 헤더로 스탬프됩니다. 이 통합 ID는 Mission Control에서 라우팅, 어트리뷰션 및 통합별 동작을 위해 사용됩니다.\n\n다중 사용자 서버 지침 및 전체 통합 ID 세부 정보는 [다중 테넌트 및 서버 배포](/ko/copilot/how-tos/copilot-sdk/setup/multi-tenancy)을 참조하세요.\n\nMission Control은 SDK로 생성된 클라우드 세션을 `copilot-developer-sandbox` 에이전트 슬러그로 라우팅합니다. 이름은 클라우드 에이전트에 대한 내부 라우팅 슬러그이며 세션이 로컬 Windows 샌드박스를 사용하는 것을 의미하지는 않습니다.\n\n## 고급: `COPILOT_MC_BASE_URL`\n\n기본적으로 런타임은 구성된 Copilot API URL에서 Mission Control 기본 URL을 파생합니다. 해당 Mission Control 엔드포인트를 재정의해야 하는 경우에만 설정합니다 `COPILOT_MC_BASE_URL` .\n\n이 작업은 GitHub Enterprise Server 배포에 필요할 수 있습니다. 프로덕션 환경에서 신뢰하기 전에 GitHub 담당자에게 올바른 값 및 지원 상태를 확인합니다.\n\n```shell\nCOPILOT_MC_BASE_URL=\"https://example.com/agents\"\n```\n\n## 클라우드 세션 및 원격 세션\n\n| Capability                   | 원격 세션                  | 클라우드 세션              |\n| ---------------------------- | ---------------------- | -------------------- |\n| 실행 위치                        | 로컬 컴퓨터 또는 서버           | GitHub 호스팅 컴퓨팅       |\n| 미션 컨트롤 역할                    | GitHub 웹/모바일에 로컬 세션 공유 | 호스트된 세션을 만들고 라우팅합니다. |\n| SDK 옵션                       |                        |                      |\n| `remote: true` 클라이언트 또는 세션에서 |                        |                      |\n| `cloud: { ... }` 세션 생성 시     |                        |                      |\n| 경로 다시 시작                     | 표준 이력서                 | 표준 이력서               |\n| Windows 샌드박스 관련              | 관련이 없는                 | 관련이 없는               |\n\nSDK 런타임이 이미 실행 중인 위치에서 세션이 실행되어야 하지만 Mission Control에서도 액세스할 수 있는 경우 원격 세션을 사용합니다. GitHub 호스팅 컴퓨팅에서 세션을 실행해야 하는 경우 클라우드 세션을 사용합니다.\n\n## Troubleshooting\n\n| 증상                                                                                                  | 가능한 원인                                                                  | 확인할 사항                                                                  |\n| --------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------- | ----------------------------------------------------------------------- |\n| 클라우드 세션 생성이 `\"policy_blocked\"` 반환됩니다.                                                               | 조직 정책은 클라우드 흐름에서 원격 제어 또는 보기를 차단합니다.                                    | 조직 Copilot 정책 및 사용자 자격 확인                                               |\n| 리포지토리 컨텍스트 없이 세션 만들기                                                                                |                                                                         |                                                                         |\n| `cloud.repository` 생략되었습니다.                                                                         |                                                                         |                                                                         |\n| `owner`, `name` 및 선택적으로 `branch`를 전달하세요                                                             |                                                                         |                                                                         |\n| 다시 시작은 새 `cloud` 옵션을 무시합니다.                                                                         |                                                                         |                                                                         |\n| `cloud` 새 세션에만 적용됩니다.                                                                               | 기존 세션을 정상적으로 다시 시작합니다.                                                  |                                                                         |\n| 샌드박스 설정과 혼동                                                                                         | Windows 샌드박스 및 클라우드 세션은 별개입니다.                                          | 클라우드 실행에는 `SANDBOX=true`를 사용하지 마세요.                                     |\n| `session.send`가 `messageId`와 함께 해결되지만 `assistant.*` 이벤트는 전혀 발생하지 않고 Mission Control에도 프롬프트가 표시되지 않음 | session.send가 원격 워커에서 온 `session.start`보다 앞서 실행되었고, 런타임이 프롬프트를 먹어버렸습니다. | 보내기 전에 `session.start`로 첫 번째 `producer === \"copilot-agent\"` 이벤트를 대기합니다. |\n| [첫 번째 프롬프트 보내기](#sending-the-first-prompt) 참조                                                       |                                                                         |                                                                         |\n| 클라우드 작업자가 처리 중이더라도 라이브 UI가 업데이트되지 않습니다.                                                             |                                                                         |                                                                         |\n| `streaming`에 `createSession`이 설정되지 않았으므로 최종 `assistant.message`만 출력됩니다.                             |                                                                         |                                                                         |\n| `streaming: true`에서 `createSession`을(를) 설정하고 다시 시작                                                  |                                                                         |                                                                         |\n| 클라우드 세션이 작동하지만 UI에 공유 가능한 URL이 표시되지 않음                                                              | 앱이 URL에 대해 `session.info`를 구독한 적이 없습니다                                  |                                                                         |\n| `session.info`를 구독하고 `infoType === \"remote\"`를 필터링합니다.                                               |                                                                         |                                                                         |\n| [Mission Control URL에 액세스하기](#accessing-the-mission-control-url)를 참조하세요                             |                                                                         |                                                                         |\n\n## 참고하십시오\n\n* [원격 세션](/ko/copilot/how-tos/copilot-sdk/features/remote-sessions): Mission Control을 통해 로컬로 호스트되는 세션 공유\n* [스트리밍 세션 이벤트](/ko/copilot/how-tos/copilot-sdk/features/streaming-events): 실시간 UI 렌더링용 `assistant.*` 델타 구독\n* [다중 테넌트 및 서버 배포](/ko/copilot/how-tos/copilot-sdk/setup/multi-tenancy): 통합 ID 및 서버 배포 패턴\n* [인증](/ko/copilot/how-tos/copilot-sdk/auth): SDK 세션에 대한 GitHub 인증 구성"}