{"meta":{"title":"세션 후크","intro":"후크를 사용하면 대화 수명 주기의 주요 지점에서 Copilot 세션의 동작을 가로채고 사용자 지정할 수 있습니다. 후크를 사용하여 다음을 수행합니다.","product":"GitHub Copilot","breadcrumbs":[{"href":"/ko/enterprise-cloud@latest/copilot","title":"GitHub Copilot"},{"href":"/ko/enterprise-cloud@latest/copilot/how-tos","title":"방법"},{"href":"/ko/enterprise-cloud@latest/copilot/how-tos/copilot-sdk","title":"코필로트 SDK"},{"href":"/ko/enterprise-cloud@latest/copilot/how-tos/copilot-sdk/hooks","title":"후크 사용"},{"href":"/ko/enterprise-cloud@latest/copilot/how-tos/copilot-sdk/hooks/hooks-overview","title":"후크 개요"}],"documentType":"article"},"body":"# 세션 후크\n\n후크를 사용하면 대화 수명 주기의 주요 지점에서 Copilot 세션의 동작을 가로채고 사용자 지정할 수 있습니다. 후크를 사용하여 다음을 수행합니다.\n\n<!-- markdownlint-disable GHD046 GHD005 -->\n\n<!-- Suppressed: GHD046 (outdated release terminology), GHD005 (hardcoded data variable) -->\n\n* **제어 도구 실행** - 도구 호출 승인, 거부 또는 수정\n* **결과 변환** - 처리하기 전에 도구 출력 수정\n* **컨텍스트 추가** - 세션 시작 시 추가 정보 삽입\n* **오류 처리** - 사용자 지정 오류 처리 구현\n* **감사 및 로그** - 규정 준수를 위한 모든 상호 작용 추적\n\n## 사용 가능한 후크\n\n| 후크                                                                                                           | Trigger               | 사용 사례                |\n| ------------------------------------------------------------------------------------------------------------ | --------------------- | -------------------- |\n| [사전 도구 사용 후크](/ko/enterprise-cloud@latest/copilot/how-tos/copilot-sdk/hooks/pre-tool-use)                    | 도구를 실행하기 전에           | 권한 제어, 인수 유효성 검사     |\n| [사후 도구 사용 후크](/ko/enterprise-cloud@latest/copilot/how-tos/copilot-sdk/hooks/post-tool-use)                   | 도구가 실행된 후(성공에만 해당)    | 결과 변환, 로깅            |\n| [사후 도구 사용 후크](/ko/enterprise-cloud@latest/copilot/how-tos/copilot-sdk/hooks/post-tool-use#failure-variant)   | 도구 실행 후 결과가 실패했습니다.   | 재시도 지침 삽입, 로그 오류     |\n| [사용자 프롬프트 제출 후크](/ko/enterprise-cloud@latest/copilot/how-tos/copilot-sdk/hooks/user-prompt-submitted)        | 사용자가 메시지를 보내는 경우      | 프롬프트 수정, 필터링         |\n| [변환된 사용자 프롬프트 훅](/ko/enterprise-cloud@latest/copilot/how-tos/copilot-sdk/hooks/user-prompt-transformed)      | 런타임 프롬프트 변환 후         | 모델용 콘텐츠 검사 또는 교체     |\n| [세션 수명 주기 후크](/ko/enterprise-cloud@latest/copilot/how-tos/copilot-sdk/hooks/session-lifecycle#session-start) | 세션 시작                 | 컨텍스트 추가, 세션 구성       |\n| [세션 수명 주기 후크](/ko/enterprise-cloud@latest/copilot/how-tos/copilot-sdk/hooks/session-lifecycle#session-end)   | 세션 종료                 | 정리, 분석               |\n| [오류 처리 후크](/ko/enterprise-cloud@latest/copilot/how-tos/copilot-sdk/hooks/error-handling)                     | 오류가 발생합니다.            | 사용자 지정 오류 처리         |\n| [세션 수명 주기 후크](/ko/enterprise-cloud@latest/copilot/how-tos/copilot-sdk/hooks/session-lifecycle#agent-stop)    | 최상위 에이전트가 자동으로 중지됩니다. | 완료 유효성 검사 또는 다른 턴 요청 |\n\n## 빠른 시작\n\n<div class=\"ghd-codetabs\">\n<div class=\"ghd-codetab\" data-lang=\"typescript\" data-label=\"TypeScript\"><div class=\"ghd-codetab-fallback-label\" role=\"heading\" aria-level=\"3\">TypeScript</div>\n\n```typescript\nimport { CopilotClient } from \"@github/copilot-sdk\";\n\nconst client = new CopilotClient();\n\nconst session = await client.createSession({\n  hooks: {\n    onPreToolUse: async (input) => {\n      console.log(`Tool called: ${input.toolName}`);\n      // Allow all tools\n      return { permissionDecision: \"allow\" };\n    },\n    onPostToolUse: async (input) => {\n      console.log(`Tool result: ${JSON.stringify(input.toolResult)}`);\n      return null; // No modifications\n    },\n    onSessionStart: async (input) => {\n      return { additionalContext: \"User prefers concise answers.\" };\n    },\n  },\n});\n```\n\n</div>\n\n<div class=\"ghd-codetab\" data-lang=\"python\" data-label=\"Python\"><div class=\"ghd-codetab-fallback-label\" role=\"heading\" aria-level=\"3\">Python</div>\n\n```python\nfrom copilot import CopilotClient\nfrom copilot.session import PermissionHandler\n\nasync def main():\n    client = CopilotClient()\n    await client.start()\n\n    async def on_pre_tool_use(input_data, invocation):\n        print(f\"Tool called: {input_data['toolName']}\")\n        return {\"permissionDecision\": \"allow\"}\n\n    async def on_post_tool_use(input_data, invocation):\n        print(f\"Tool result: {input_data['toolResult']}\")\n        return None\n\n    async def on_session_start(input_data, invocation):\n        return {\"additionalContext\": \"User prefers concise answers.\"}\n\n    session = await client.create_session(on_permission_request=PermissionHandler.approve_all, hooks={\n            \"on_pre_tool_use\": on_pre_tool_use,\n            \"on_post_tool_use\": on_post_tool_use,\n            \"on_session_start\": on_session_start,\n        })\n```\n\n</div>\n\n<div class=\"ghd-codetab\" data-lang=\"go\" data-label=\"Go\"><div class=\"ghd-codetab-fallback-label\" role=\"heading\" aria-level=\"3\">Go</div>\n\n```golang\npackage main\n\nimport (\n    \"context\"\n    \"fmt\"\n    copilot \"github.com/github/copilot-sdk/go\"\n)\n\nfunc main() {\n    client := copilot.NewClient(nil)\n\n    session, _ := client.CreateSession(context.Background(), &copilot.SessionConfig{\n        Hooks: &copilot.SessionHooks{\n            OnPreToolUse: func(input copilot.PreToolUseHookInput, inv copilot.HookInvocation) (*copilot.PreToolUseHookOutput, error) {\n                fmt.Printf(\"Tool called: %s\\n\", input.ToolName)\n                return &copilot.PreToolUseHookOutput{\n                    PermissionDecision: \"allow\",\n                }, nil\n            },\n            OnPostToolUse: func(input copilot.PostToolUseHookInput, inv copilot.HookInvocation) (*copilot.PostToolUseHookOutput, error) {\n                fmt.Printf(\"Tool result: %v\\n\", input.ToolResult)\n                return nil, nil\n            },\n            OnSessionStart: func(input copilot.SessionStartHookInput, inv copilot.HookInvocation) (*copilot.SessionStartHookOutput, error) {\n                return &copilot.SessionStartHookOutput{\n                    AdditionalContext: \"User prefers concise answers.\",\n                }, nil\n            },\n        },\n    })\n    _ = session\n}\n```\n\n</div>\n\n<div class=\"ghd-codetab\" data-lang=\"dotnet\" data-label=\".NET\"><div class=\"ghd-codetab-fallback-label\" role=\"heading\" aria-level=\"3\">.NET</div>\n\n```csharp\nusing GitHub.Copilot;\n\nvar client = new CopilotClient();\n\nvar session = await client.CreateSessionAsync(new SessionConfig\n{\n    Hooks = new SessionHooks\n    {\n        OnPreToolUse = (input, invocation) =>\n        {\n            Console.WriteLine($\"Tool called: {input.ToolName}\");\n            return Task.FromResult<PreToolUseHookOutput?>(\n                new PreToolUseHookOutput { PermissionDecision = \"allow\" }\n            );\n        },\n        OnPostToolUse = (input, invocation) =>\n        {\n            Console.WriteLine($\"Tool result: {input.ToolResult}\");\n            return Task.FromResult<PostToolUseHookOutput?>(null);\n        },\n        OnSessionStart = (input, invocation) =>\n        {\n            return Task.FromResult<SessionStartHookOutput?>(\n                new SessionStartHookOutput { AdditionalContext = \"User prefers concise answers.\" }\n            );\n        },\n    },\n});\n```\n\n</div>\n\n<div class=\"ghd-codetab\" data-lang=\"java\" data-label=\"Java\"><div class=\"ghd-codetab-fallback-label\" role=\"heading\" aria-level=\"3\">Java</div>\n\n```java\nimport com.github.copilot.*;\nimport com.github.copilot.rpc.*;\nimport java.util.concurrent.CompletableFuture;\n\ntry (var client = new CopilotClient()) {\n    client.start().get();\n\n    var hooks = new SessionHooks()\n        .setOnPreToolUse((input, invocation) -> {\n            System.out.println(\"Tool called: \" + input.getToolName());\n            return CompletableFuture.completedFuture(PreToolUseHookOutput.allow());\n        })\n        .setOnPostToolUse((input, invocation) -> {\n            System.out.println(\"Tool result: \" + input.getToolResult());\n            return CompletableFuture.completedFuture(null);\n        })\n        .setOnSessionStart((input, invocation) -> {\n            return CompletableFuture.completedFuture(\n                new SessionStartHookOutput(\"User prefers concise answers.\", null)\n            );\n        });\n\n    var session = client.createSession(\n        new SessionConfig()\n            .setHooks(hooks)\n            .setOnPermissionRequest(PermissionHandler.APPROVE_ALL)\n    ).get();\n}\n```\n\n</div>\n\n</div>\n\n## 후크 호출 컨텍스트\n\n모든 후크는 현재 세션에 대한 컨텍스트가 있는 매개 변수를 받 `invocation` 습니다.\n\n| Field       | Type   | 설명        |\n| ----------- | ------ | --------- |\n| `sessionId` | string | 현재 세션의 ID |\n\n이렇게 하면 후크가 상태를 유지 관리하거나 세션별 논리를 수행할 수 있습니다.\n\n## 일반적인 패턴\n\n### 모든 도구 호출 로깅\n\n```typescript\nconst session = await client.createSession({\n  hooks: {\n    onPreToolUse: async (input) => {\n      console.log(`[${new Date().toISOString()}] Tool: ${input.toolName}, Args: ${JSON.stringify(input.toolArgs)}`);\n      return { permissionDecision: \"allow\" };\n    },\n    onPostToolUse: async (input) => {\n      console.log(`[${new Date().toISOString()}] Result: ${JSON.stringify(input.toolResult)}`);\n      return null;\n    },\n  },\n});\n```\n\n### 위험한 도구 차단\n\n```typescript\nconst BLOCKED_TOOLS = [\"shell\", \"bash\", \"exec\"];\n\nconst session = await client.createSession({\n  hooks: {\n    onPreToolUse: async (input) => {\n      if (BLOCKED_TOOLS.includes(input.toolName)) {\n        return {\n          permissionDecision: \"deny\",\n          permissionDecisionReason: \"Shell access is not permitted\",\n        };\n      }\n      return { permissionDecision: \"allow\" };\n    },\n  },\n});\n```\n\n### 사용자 컨텍스트 추가\n\n```typescript\nconst session = await client.createSession({\n  hooks: {\n    onSessionStart: async () => {\n      const userPrefs = await loadUserPreferences();\n      return {\n        additionalContext: `User preferences: ${JSON.stringify(userPrefs)}`,\n      };\n    },\n  },\n});\n```\n\n## 후크 가이드\n\n* **[사전 도구 사용 후크](/ko/enterprise-cloud@latest/copilot/how-tos/copilot-sdk/hooks/pre-tool-use)** - 컨트롤 도구 실행 권한\n* **[사후 도구 사용 후크](/ko/enterprise-cloud@latest/copilot/how-tos/copilot-sdk/hooks/post-tool-use)** - 도구 결과 변환\n* **[사용자 프롬프트 제출 후크](/ko/enterprise-cloud@latest/copilot/how-tos/copilot-sdk/hooks/user-prompt-submitted)** - 사용자 프롬프트 수정\n* **[변환된 사용자 프롬프트 훅](/ko/enterprise-cloud@latest/copilot/how-tos/copilot-sdk/hooks/user-prompt-transformed)** - 모델 연결 프롬프트 바꾸기\n* **[세션 수명 주기 후크](/ko/enterprise-cloud@latest/copilot/how-tos/copilot-sdk/hooks/session-lifecycle)** - 세션 시작 및 종료\n* **[세션 수명 주기 후크](/ko/enterprise-cloud@latest/copilot/how-tos/copilot-sdk/hooks/session-lifecycle#agent-stop)** - 에이전트가 중지되기 전에 완료 유효성 검사\n* **[오류 처리 후크](/ko/enterprise-cloud@latest/copilot/how-tos/copilot-sdk/hooks/error-handling)** - 사용자 지정 오류 처리\n\n## 참고하십시오\n\n* [첫 번째 Copilot 기반 앱 빌드](/ko/enterprise-cloud@latest/copilot/how-tos/copilot-sdk/getting-started)\n* [첫 번째 Copilot 기반 앱 빌드](/ko/enterprise-cloud@latest/copilot/how-tos/copilot-sdk/getting-started#step-4-add-a-custom-tool)\n* [디버깅 가이드](/ko/enterprise-cloud@latest/copilot/how-tos/copilot-sdk/troubleshooting/debugging)"}