giip
SES Proposal
16 min read

์Šค์ผ€์ค„๋Ÿฌ ์—์ด์ „ํŠธ ๊ด€๋ฆฌ ๊ฐ€์ด๋“œ

ํ”„๋กœ์ ํŠธ(CSN)๋ณ„๋กœ ๋“ฑ๋ก๋œ ์ž๋™ํ™” ์‹คํ–‰๊ธฐ(gissue ์Šค์ผ€์ค„๋Ÿฌ ๋“ฑ ๋ฐฑ๊ทธ๋ผ์šด๋“œ ์—์ด์ „ํŠธ)์˜ ์˜จ๋ผ์ธ/์˜คํ”„๋ผ์ธ ์ƒํƒœ, ์‹คํ–‰ ์ƒํƒœยท์ด๋ ฅ, ์‹ค์‹œ๊ฐ„ ๋กœ๊ทธ๋ฅผ ํ•œ ํ™”๋ฉด์—์„œ ๊ด€๋ฆฌํ•ฉ๋‹ˆ๋‹ค.

๐Ÿ• ์Šค์ผ€์ค„๋Ÿฌ ์—์ด์ „ํŠธ ๊ด€๋ฆฌ ํŽ˜์ด์ง€๋กœ ์ด๋™ โ†’

๐Ÿค– AI ์—๊ฒŒ ๋งก๊ฒจ gissue ์Šค์ผ€์ค„๋Ÿฌ ๋งŒ๋“ค๊ธฐ

์ด ๋ฌธ์„œ๋ฅผ AI ์—๊ฒŒ ์ฃผ๋ฉด, AI ๊ฐ€ giip-fde-agent ์ €์žฅ์†Œ(https://github.com/LowyShin/giip-fde-agent.git)๋ฅผ cloneํ•˜๊ฑฐ๋‚˜ ์ตœ์‹ ํ™”ํ•œ ๋’ค gissue ์ฒ˜๋ฆฌ์šฉ ์Šค์ผ€์ค„๋Ÿฌ๋ฅผ ์„ค์น˜ยท๋“ฑ๋กยท๊ฒ€์ฆ๊นŒ์ง€ ์ž๋™์œผ๋กœ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค. ์ฒ˜์Œ๋ถ€ํ„ฐ ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์ƒˆ๋กœ ์งœ์ง€ ๋ง๊ณ  ์ด ์ ˆ์ฐจ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

ํ”„๋กฌํ”„ํŠธ(๋ณต์‚ฌํ•ด์„œ ๊ทธ๋Œ€๋กœ ์‚ฌ์šฉ):

์ด ๋ฌธ์„œ(/help/catquest-schedulers.ko.md)๋ฅผ ์ฝ๊ณ , ์•„๋ž˜ '์„ค์น˜ ์ ˆ์ฐจ'๋Œ€๋กœ gissue ์Šค์ผ€์ค„๋Ÿฌ๋ฅผ ์ด PC ์— ์„ค์น˜ํ•ด์ค˜.
giip-fde-agent ๊ฐ€ ์—†์œผ๋ฉด clone, ์žˆ์œผ๋ฉด git pull --ff-only ๋กœ ์ตœ์‹ ํ™”. ๋กœ์ปฌ ๋ณ€๊ฒฝ์ด ์žˆ์œผ๋ฉด ๋ฎ์–ด์“ฐ์ง€ ๋ง๊ณ  ์ค‘๋‹จํ•˜๊ณ  ๋ณด๊ณ ํ•ด.
๋Œ€์ƒ CSN ์€ <CSN>, ์ž‘์—… ํด๋”๋Š” <๊ฒฝ๋กœ> ๋กœ ์ง€์ •ํ•ด.
SK ๋Š” giipAgent.cnf(๋˜๋Š” giipAgent.cfg)์—์„œ sk= ๊ฐ’์„ ์ฝ๊ณ  ๋‚˜์—๊ฒŒ ๋ฌป์ง€ ๋งˆ.
๊ฐ ๋‹จ๊ณ„ ํ™•์ธ ๊ฒฐ๊ณผ๋ฅผ ๋ณด๊ณ ํ•ด.

์„ค์น˜ ์ ˆ์ฐจ

  1. ์‚ฌ์ „์ ๊ฒ€ โ€” ์‹คํ–‰ โ†’ git --version, node --version, claude --version, Windows ๋Š” powershell -Command $PSVersionTable.PSVersion, Linux ๋Š” pwsh --version. ๋ชจ๋‘ PATH ์— ์žˆ์–ด์•ผ ๋‹ค์Œ ๋‹จ๊ณ„๋กœ.
  2. giip-fde-agent ํ™•๋ณด โ€” ์‹คํ–‰ โ†’ ์—†์œผ๋ฉด git clone https://github.com/LowyShin/giip-fde-agent.git, ์žˆ์œผ๋ฉด git pull --ff-only. ๋กœ์ปฌ ๋ณ€๊ฒฝ์ด ์žˆ์œผ๋ฉด ์ค‘๋‹จํ•˜๊ณ  ๋ณด๊ณ .
  3. ์ •๋ณธ ์ŠคํŽ™ ์ฝ๊ธฐ โ€” docs/60-operations/hourly-issue-scheduler.md ยง4~ยง5 ๋ฅผ ์ฝ๊ณ  CSNโ†’workdir ๋งคํ•‘, heartbeat ๋ธ”๋ก, SK ์œ„์น˜๋ฅผ ํ™•์ธ.
  4. csn-projects.json ์ž‘์„ฑ โ€” scripts/gissue/csn-projects.json.example ์„ csn-projects.json ์œผ๋กœ ๋ณต์‚ฌ. ๋Œ€์ƒ CSN ์˜ workdir/enabled: true ์ฑ„์šฐ๊ณ , ์ตœ์ƒ์œ„ heartbeat ๋ธ”๋ก์— lssn(์„œ๋ฒ„๋ฒˆํ˜ธ)/hostname(์ด PC ์‹๋ณ„์ž)/skFile(sk= ํ˜•์‹ ํŒŒ์ผ ๊ฒฝ๋กœ) ํ•„์ˆ˜๋กœ ์ง€์ •. ์—†์œผ๋ฉด ์ด ํ™”๋ฉด์— ํ–‰์ด ๋‚˜ํƒ€๋‚˜์ง€ ์•Š์Œ.
  5. ์‹œํฌ๋ฆฟ ์ค€๋น„ โ€” ์ƒ์œ„ ํด๋” giipAgent.cnf(๋˜๋Š” giipAgent.cfg)์—์„œ sk= ๊ฐ’์„ ์ฝ์Œ. ์‚ฌ์šฉ์ž์—๊ฒŒ ๋˜๋ฌป์ง€ ์•Š๊ณ , ์ถœ๋ ฅ์—๋„ ๊ธฐ๋กํ•˜์ง€ ์•Š์Œ. slack-bot/.secrets/giip-accounts.json(.sample.json ๋ณต์‚ฌ)๋„ ์ค€๋น„.
  6. ๋“œ๋ผ์ด๋Ÿฐ โ€” scripts/gissue/manage-gissue-scheduler.ps1 -Action DryRun -OnlyCsn <CSN> ์‹คํ–‰ โ†’ [PREFLIGHT-FAIL] ๋กœ๊ทธ ์—†์ด ๋๋‚˜๋ฉด ์„ฑ๊ณต.
  7. ๋“ฑ๋ก
    • Windows โ€” powershell -NoProfile -ExecutionPolicy Bypass -File scripts\register-hourly-issue-scheduler.ps1 -Action Register -RepoRoot <giip-fde-agent ๋ฃจํŠธ>
    • Linux โ€” ์ „์šฉ ๋“ฑ๋ก ์Šคํฌ๋ฆฝํŠธ๋Š” ์—†๊ณ , /etc/cron.d/gissue-scheduler ๊ฐ™์€ cron ํ•œ ์ค„๋กœ ๋“ฑ๋กํ•ฉ๋‹ˆ๋‹ค(์‹ค์ œ docker ๋ฐฐํฌ์™€ ๊ฐ™์€ ํ˜•์‹): 7,27,47 * * * * <์ผ๋ฐ˜ ์‚ฌ์šฉ์ž> cd <๋ฃจํŠธ> && pwsh -NoProfile -NonInteractive -File "<๋ฃจํŠธ>/scripts/gissue/run-gissue-claude.ps1" -OnlyCsn <CSN> >> <๋ฃจํŠธ>/scripts/gissue/logs/cron.log 2>&1. ๋ฐ˜๋“œ์‹œ root ๊ฐ€ ์•„๋‹Œ ์ผ๋ฐ˜ ์‚ฌ์šฉ์ž๋กœ ๋“ฑ๋กํ•ฉ๋‹ˆ๋‹ค(claude ๊ฐ€ root ์—์„œ --dangerously-skip-permissions ๋ฅผ ๊ฑฐ๋ถ€ํ•ด ์ด์Šˆ๊ฐ€ ๋ชจ๋‘ ์‹คํŒจํ•จ). ๊ทธ ์‚ฌ์šฉ์ž์˜ claude ๋กœ๊ทธ์ธ ์ •๋ณด๋„ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.
    • Docker ์ธ์Šคํ„ด์Šค โ€” ์ปจํ…Œ์ด๋„ˆ ๊ธฐ๋™ ์‹œ docker/entrypoint.sh ๊ฐ€ ์œ„ cron ์„ ์ž๋™ ๋“ฑ๋กํ•ฉ๋‹ˆ๋‹ค(GIIP_ENABLE_SCHEDULER ๊ธฐ๋ณธ true, -OnlyCsn ์€ csn-projects.json ์—์„œ ํŒŒ์ƒ). ์ด ๊ฒฝ์šฐ 7๋‹จ๊ณ„๋Š” ์ด๋ฏธ ๋๋‚˜ ์žˆ์œผ๋ฏ€๋กœ /etc/cron.d/gissue-scheduler ์กด์žฌ๋งŒ ํ™•์ธํ•˜๊ณ  scripts/bootstrap-instance.sh ๋กœ ํ™˜๊ฒฝ(pwsh ๋งํฌ ๋“ฑ)์„ ์ ๊ฒ€ํ•ฉ๋‹ˆ๋‹ค.
  8. ๊ฒ€์ฆ โ€” manage-gissue-scheduler.ps1 -Action RunOnce -OnlyCsn <CSN> ๋กœ ํ•œ ๋ฒˆ ์‹คํ–‰ํ•˜๊ฑฐ๋‚˜ ๋‹ค์Œ :07 ์„ ๊ธฐ๋‹ค๋ฆฐ ๋’ค ์ด ํ™”๋ฉด์„ ์ƒˆ๋กœ๊ณ ์นจ โ†’ gissue_csn<CSN> ํ–‰์ด online ์ด๊ณ  History ์— ์‹คํ–‰์ด ๋‚จ์•„ ์žˆ์œผ๋ฉด ์„ฑ๊ณต. ์•ˆ ๋ณด์ด๋ฉด scripts/gissue/logs/gissue_csn<CSN>.log ์˜ [WARN][SchedulerState-...] ์ค„์„ ํ™•์ธ.

AI ๊ฐ€ ํ•˜์ง€ ๋ง์•„์•ผ ํ•  ๊ฒƒ

  • giip-fde-agent ์˜ ๋Ÿฌ๋„ˆ(run-gissue-claude.ps1)๋ฅผ ์ƒˆ๋กœ ์ž‘์„ฑํ•˜์ง€ ์•Š๋Š”๋‹ค
  • SP ๋ฅผ ์ง์ ‘ ํ˜ธ์ถœํ•˜๋Š” ์ฝ”๋“œ๋ฅผ ๋”ฐ๋กœ ์งœ์ง€ ์•Š๋Š”๋‹ค(์„ค์น˜๋œ ๋Ÿฌ๋„ˆ๊ฐ€ ์ฒ˜๋ฆฌํ•œ๋‹ค)
  • SK ๊ฐ’์„ ๋ฌธ์„œ๋‚˜ ๋กœ๊ทธ์— ๋‚จ๊ธฐ์ง€ ์•Š๋Š”๋‹ค
  • giip-fde-agent ์ฝ”๋“œ ์ž์ฒด๋ฅผ ์ˆ˜์ •ํ•˜์ง€ ์•Š๋Š”๋‹ค

๐Ÿ“‹ ๊ฐœ์š”

์Šค์ผ€์ค„๋Ÿฌ ์—์ด์ „ํŠธ ๊ด€๋ฆฌ๋Š” ํ˜„์žฌ ์„ ํƒ๋œ ํ”„๋กœ์ ํŠธ(CSN)์— ๋“ฑ๋ก๋œ ๋ชจ๋“  ์ž๋™ํ™” ์—์ด์ „ํŠธ โ€” ์˜ˆ๋ฅผ ๋“ค์–ด gissue์˜ ๋งค์‹œ๊ฐ„ ์Šค์ผ€์ค„๋Ÿฌ, ๋Œ€ํ™”ํ˜• Claude Code ์„ธ์…˜ ๋“ฑ์„ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค. giip ์ด์Šˆ๋ฅผ ๊ณ ์–‘์ด๋กœ ์‹œ๊ฐํ™”ํ•˜๋Š” /admin/catquest์™€ ๋‹ฌ๋ฆฌ, ์ด ํ™”๋ฉด์€ ์ž๋™ํ™” ์ž‘์—…์„ ์‹คํ–‰ํ•˜๋Š” ์—์ด์ „ํŠธ ์ž์ฒด๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ์šด์˜ ๋Œ€์‹œ๋ณด๋“œ์ž…๋‹ˆ๋‹ค: ๊ฐ ์—์ด์ „ํŠธ๊ฐ€ ์‚ด์•„์žˆ๋Š”์ง€, ํ˜„์žฌ ์‹คํ–‰์ด ์ •์ƒ์ธ์ง€, ๋กœ๊ทธ๋Š” ์–ด๋””์„œ ๋ณผ ์ˆ˜ ์žˆ๋Š”์ง€๋ฅผ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.

๐ŸŽจ ์ƒํƒœ ์ƒ‰์ƒ

์—์ด์ „ํŠธ๋งˆ๋‹ค ์„œ๋กœ ๋…๋ฆฝ์ ์ธ ๋‘ ๊ฐ€์ง€ ์ƒํƒœ ์‹ ํ˜ธ๊ฐ€ ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค โ€” ํ˜ผ๋™ํ•˜์ง€ ๋งˆ์„ธ์š”.

Identity ์ƒํƒœ (์—์ด์ „ํŠธ ์ด๋ฆ„ ์˜† ์ž‘์€ ์ )

๊ฐœ๋ณ„ ์‹คํ–‰(run)๊ณผ ๋ฌด๊ด€ํ•˜๊ฒŒ, ์—์ด์ „ํŠธ ํ”„๋กœ์„ธ์Šค ์ž์ฒด์— ์ ‘๊ทผ ๊ฐ€๋Šฅํ•œ์ง€๋ฅผ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค(tSchedulerAgent.status).

์ƒ‰์ƒ์ƒํƒœ์˜๋ฏธ
๐ŸŸข ์ดˆ๋กonline์—์ด์ „ํŠธ์— ์ ‘๊ทผ ๊ฐ€๋Šฅํ•˜๋ฉฐ ์ •์ƒ ๋ณด๊ณ  ์ค‘
๐Ÿ”ด ๋นจ๊ฐ•error์—์ด์ „ํŠธ๊ฐ€ ์˜ค๋ฅ˜ ์ƒํƒœ๋ฅผ ๋ณด๊ณ ํ•จ
โšช ํšŒ์ƒ‰(slate-400)offlineํ˜„์žฌ ์—์ด์ „ํŠธ์— ์ ‘๊ทผํ•  ์ˆ˜ ์—†์Œ
โšช ์—ฐํ•œ ํšŒ์ƒ‰(slate-300)unknown์•„์ง ์ƒํƒœ๊ฐ€ ๋ณด๊ณ ๋˜์ง€ ์•Š์Œ

์‹คํ–‰ ์ƒํƒœ (Status ์ปฌ๋Ÿผ์˜ ๋ฐฐ์ง€)

๊ฐ€์žฅ ์ตœ๊ทผ ์Šค์ผ€์ค„๋Ÿฌ *์‹คํ–‰(run)*์˜ ์ƒํƒœ(currentStatus)์™€ stale(์ •์ฒด) ํƒ์ง€ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ˜์˜ํ•ฉ๋‹ˆ๋‹ค.

์ƒ‰์ƒํ‘œ์‹œ ๋ผ๋ฒจ์กฐ๊ฑด์˜๋ฏธ
๐ŸŸข ์ดˆ๋กRUNNINGcurrentStatus = RUNNING์ด๊ณ  stale ์•„๋‹˜์ •์ƒ์ ์œผ๋กœ ์‹คํ–‰ ์ค‘
๐Ÿ”ด ๋นจ๊ฐ•STALEcurrentStatus = RUNNING ์ด๋ฉด์„œ isStale = true์‹คํ–‰ ์ค‘์œผ๋กœ ํ‘œ์‹œ๋ผ ์žˆ์ง€๋งŒ heartbeat๊ฐ€ ๋„ˆ๋ฌด ์˜ค๋ž˜ ๋Š๊น€ โ€” ๋ฉˆ์ถฐ๋ฒ„๋ฆฐ/์ข€๋น„ ์‹คํ–‰์œผ๋กœ ๋ณด์ž„
๐ŸŸ  ์ฃผํ™ฉSTALEcurrentStatus = STALE(๋ช…์‹œ์  ๊ฐ’)๋ฐฑ์—”๋“œ๊ฐ€ ์‹คํ–‰ ์ž์ฒด๋ฅผ stale๋กœ ํŒ์ •ํ•จ
โšช ํšŒ์ƒ‰ENDEDcurrentStatus = ENDED์ข…๋ฃŒ๋จ(์ •์ƒ ์™„๋ฃŒ ๋˜๋Š” ์ •์ƒ์ ์ธ ์ค‘์ง€)
โšช ํšŒ์ƒ‰(์›๋ณธ ๊ฐ’)๊ทธ ์™ธ / ์‹คํ–‰ ์ด๋ ฅ ์—†์Œ์•Œ ์ˆ˜ ์—†์Œ / ๋ฐ์ดํ„ฐ ์—†์Œ

์•„๋ž˜ ์‹คํ–‰์ด๋ ฅ ๋ชจ๋‹ฌ์—์„œ๋Š” ์™„๋ฃŒ๋œ ์‹คํ–‰์ด ๋นจ๊ฐ„์ƒ‰ FAILED๋กœ๋„ ํ‘œ์‹œ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค โ€” ENDED(์ •์ƒ ์ข…๋ฃŒ)๋‚˜ stale/ํƒ€์ž„์•„์›ƒ๊ณผ๋Š” ๊ตฌ๋ถ„๋˜๋Š”, ์˜ค๋ฅ˜๋กœ ์ข…๋ฃŒ๋œ ์‹คํ–‰์ž…๋‹ˆ๋‹ค.

๐Ÿ” ํ™”๋ฉด ๊ตฌ์„ฑ

1. ์ƒ๋‹จ ํ—ค๋”

  • /admin/catquest๋กœ ๋Œ์•„๊ฐ€๋Š” ๋’ค๋กœ๊ฐ€๊ธฐ ํ™”์‚ดํ‘œ(โ†).
  • Refresh: ํ˜„์žฌ CSN์˜ ์—์ด์ „ํŠธ ๋ชฉ๋ก์„ ๋‹ค์‹œ ๋ถˆ๋Ÿฌ์˜ต๋‹ˆ๋‹ค.

2. Open Interactive Sessions

ํ™œ์„ฑ ์ƒํƒœ์ธ claude_interactive_session ์—์ด์ „ํŠธ โ€” ์ฆ‰ ํ˜„์žฌ ํ˜ธ์ŠคํŠธ์—์„œ ์‹คํ–‰ ์ค‘์œผ๋กœ ๋“ฑ๋ก๋œ ๋Œ€ํ™”ํ˜• Claude Code ์„ธ์…˜ โ€” ์ด ํ•˜๋‚˜ ์ด์ƒ ์žˆ์„ ๋•Œ๋งŒ ๋ณ„๋„ ์นด๋“œ๋กœ ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค. ๊ฐ ํ–‰์€ ์„ธ์…˜ ์ด๋ฆ„, ํ˜ธ์ŠคํŠธ, ๋งˆ์ง€๋ง‰ ํ†ต์‹  ์‹œ๊ฐ, ๊ทธ๋ฆฌ๊ณ  ์—์ด์ „ํŠธ์˜ capabilities์— ์„ธ์…˜ URL์ด ๋“ฑ๋ก๋ผ ์žˆ์„ ๋•Œ ํ‘œ์‹œ๋˜๋Š” "Open session" ๋งํฌ๋ฅผ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค.

3. ์—์ด์ „ํŠธ ๋ชฉ๋ก (ํ‘œ)

์Šค์ผ€์ค„๋Ÿฌ ์—์ด์ „ํŠธ๋‹น ํ•œ ํ–‰์”ฉ ํ‘œ์‹œ๋˜๋ฉฐ, ๋‹ค์Œ ์ •๋ณด๋ฅผ ๋‹ด์Šต๋‹ˆ๋‹ค.

  • Name โ€” identity ์ƒํƒœ ์ , ์—์ด์ „ํŠธ ์ด๋ฆ„, OS/์—์ด์ „ํŠธ ์œ ํ˜•/๋ฒ„์ „ ๋ฐฐ์ง€, lssn(์—ฐ๊ฒฐ๋œ ์„œ๋ฒ„), ์ž˜๋ฆฐ capabilities ์š”์•ฝ, ๋งˆ์ง€๋ง‰ ์˜ค๋ฅ˜(์žˆ๋Š” ๊ฒฝ์šฐ).
  • Host โ€” hostIdentifier.
  • Windows Task โ€” ํ•ด๋‹น๋˜๋Š” ๊ฒฝ์šฐ, ์ด ์—์ด์ „ํŠธ๋ฅผ ์‹คํ–‰ํ•˜๋Š” Windows ์ž‘์—… ์Šค์ผ€์ค„๋Ÿฌ ์ž‘์—… ์ด๋ฆ„.
  • Project โ€” ํ”„๋กœ์ ํŠธ ์ด๋ฆ„.
  • Active โ€” ON/OFF ๋ฐฐ์ง€(isActive).
  • Last Comm โ€” ๋งˆ์ง€๋ง‰ heartbeat/ํ†ต์‹  ์‹œ๊ฐ.
  • Status โ€” ์œ„์—์„œ ์„ค๋ช…ํ•œ ์‹คํ–‰ ์ƒํƒœ ๋ฐฐ์ง€์™€, ๋ณด๊ณ ๋œ ๊ฒฝ์šฐ ํ˜„์žฌ ๋‹จ๊ณ„(phase) ํ…์ŠคํŠธ.

ํ•˜๋‹จ ํ†ต๊ณ„ ํ‘ธํ„ฐ๋Š” ๋ชฉ๋ก์— ํ‘œ์‹œ๋œ ๋ชจ๋“  ์—์ด์ „ํŠธ์˜ ์ฒ˜๋ฆฌ(Processed) / ์Šคํ‚ต(Skipped) / ์‹คํŒจ(Failed) ๊ฑด์ˆ˜ ํ•ฉ๊ณ„๋ฅผ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค.

4. ์‹คํ–‰์ด๋ ฅ (Run History)

ํ‘œ ์•„๋ž˜ "View History" ์นด๋“œ์— ๋ชจ๋“  ์—์ด์ „ํŠธ๊ฐ€ ๋‹ค์‹œ ๋‚˜์—ด๋˜๋ฉฐ, ํ–‰์˜ History ๋ฒ„ํŠผ์„ ํด๋ฆญํ•˜๋ฉด ํ•ด๋‹น ์—์ด์ „ํŠธ์˜ ์ตœ๊ทผ ์‹คํ–‰ ๋ชฉ๋ก์„ ๋ชจ๋‹ฌ๋กœ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค โ€” ์‹คํ–‰ ๋ชจ๋“œ, ์ƒํƒœ(FAILED ํฌํ•จ), ์‹œ์ž‘/์ข…๋ฃŒ ์‹œ๊ฐ, ์†Œ์š” ์‹œ๊ฐ„, ์ฒ˜๋ฆฌ/์Šคํ‚ต/์‹คํŒจ ๊ฑด์ˆ˜, ๋‹จ๊ณ„, ์š”์•ฝ.

5. ์‹ค์‹œ๊ฐ„ ๋กœ๊ทธ ๋ทฐ์–ด (Live Log Viewer)

๋‘ ์˜์—ญ์œผ๋กœ ๊ตฌ์„ฑ๋œ ์‹ค์‹œ๊ฐ„ tailing ํ™”๋ฉด์ž…๋‹ˆ๋‹ค.

  • ์ขŒ์ธก(์—์ด์ „ํŠธ โ†’ ์ŠคํŠธ๋ฆผ ํŠธ๋ฆฌ): ์—์ด์ „ํŠธ๋ณ„๋กœ ๊ทธ๋ฃนํ™”๋˜๋ฉฐ, ๊ฐ ์—์ด์ „ํŠธ๋ฅผ ํŽผ์น˜๋ฉด ์•Œ๋ ค์ง„ ๋กœ๊ทธ ์ŠคํŠธ๋ฆผ ๋ชฉ๋ก์ด ๋‚˜์˜ต๋‹ˆ๋‹ค(์ŠคํŠธ๋ฆผ์€ streamKey๋กœ ์‹๋ณ„๋˜๋ฉฐ streamType๊ณผ ๋กœํ…Œ์ด์…˜ ์„ธ๋Œ€ ๋ฒˆํ˜ธ๋ฅผ ๊ฐ€์ง‘๋‹ˆ๋‹ค). ์—์ด์ „ํŠธ๋Š” ๋งˆ์ง€๋ง‰ ํ†ต์‹  ์‹œ๊ฐ์„ ๊ธฐ์ค€์œผ๋กœ online/offline์ด ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.
  • ์šฐ์ธก(๋กœ๊ทธ ์ŠคํŠธ๋ฆผ ์นด๋“œ): ์ŠคํŠธ๋ฆผ์„ ์„ ํƒํ•˜๋ฉด ์ตœ๊ทผ ๋กœ๊ทธ ๋ผ์ธ์ด ํ‘œ์‹œ๋˜๊ณ , ์‹ค์‹œ๊ฐ„ tailing์„ ์œ„ํ•ด ๊ณ„์† ๊ฐฑ์‹ ๋ฉ๋‹ˆ๋‹ค.

โž• ๋‹ค๋ฅธ ํ˜ธ์ŠคํŠธ ์ถ”๊ฐ€ํ•˜๊ธฐ

์ด ํ™”๋ฉด์—๋Š” ํ˜ธ์ŠคํŠธ๋ฅผ ์ˆ˜๋™์œผ๋กœ "์ถ”๊ฐ€"ํ•˜๋Š” ๋ฒ„ํŠผ์ด๋‚˜ ์ž…๋ ฅ ํผ์ด ์—†์Šต๋‹ˆ๋‹ค โ€” ๋ชฉ๋ก์€ ์ „์ ์œผ๋กœ ์•„๋ž˜ ๋‘ ๊ฐ€์ง€ ์ž๋™ ๋“ฑ๋ก ๊ฒฝ๋กœ์˜ ๊ฒฐ๊ณผ์ž…๋‹ˆ๋‹ค. ๋‘ ๊ฒฝ๋กœ ๋ชจ๋‘ **CSN(ํ”„๋กœ์ ํŠธ)๋ณ„๋กœ ๋ฐœ๊ธ‰๋œ Secret Key(SK)**๋กœ giipApiSk4 ์—”๋“œํฌ์ธํŠธ๋ฅผ ํ˜ธ์ถœํ•ด tSchedulerAgent/tSchedulerAgentRun์— ์ž์‹ ์„ ๋“ฑ๋ก(upsert)ํ•˜๋Š” ๋ฐฉ์‹์ด๋ฉฐ, ์œ ํšจํ•œ SK ์—†์ด๋Š” ํ˜ธ์ถœ ์ž์ฒด๊ฐ€ 401 Unauthorized๋กœ ์‹คํŒจํ•˜๋ฏ€๋กœ ์•„๋ž˜ ์ ˆ์ฐจ๋ฅผ ์•Œ์•„๋„ ์ž„์˜๋กœ ๋‚จ์˜ ํ”„๋กœ์ ํŠธ์— ๊ฐ€์งœ ์—์ด์ „ํŠธ๋ฅผ ๋“ฑ๋กํ•  ์ˆ˜๋Š” ์—†์Šต๋‹ˆ๋‹ค.

โš ๏ธ ์•„๋ž˜ SK/AK ๊ฐ’์€ ํ•ญ์ƒ ์˜ˆ์‹œ ํ”Œ๋ ˆ์ด์Šคํ™€๋”์ž…๋‹ˆ๋‹ค. ์‹ค์ œ ๊ฐ’์€ ์ ˆ๋Œ€ ๋ฌธ์„œยท์ฝ”๋“œ์— ํ•˜๋“œ์ฝ”๋”ฉํ•˜์ง€ ๋ง๊ณ , ๋ฐœ๊ธ‰๋ฐ›์€ ๊ฐ’์€ ๊ฐ์ž ์•ˆ์ „ํ•œ ๋ฐฉ์‹(์‹œํฌ๋ฆฟ ํŒŒ์ผ, ํ™˜๊ฒฝ๋ณ€์ˆ˜, ์‹œํฌ๋ฆฟ ๋งค๋‹ˆ์ € ๋“ฑ)์œผ๋กœ ๋ณด๊ด€ํ•˜์„ธ์š”.

๊ณตํ†ต ์‚ฌ์ „์กฐ๊ฑด

ํ•ญ๋ชฉ์„ค๋ช…
๋Œ€์ƒ CSN์—์ด์ „ํŠธ๋ฅผ ๋“ฑ๋กํ•  ํ”„๋กœ์ ํŠธ ๋ฒˆํ˜ธ. ์ด ํŽ˜์ด์ง€๋Š” ์„ธ์…˜์˜ ํ˜„์žฌ CSN ๊ธฐ์ค€์œผ๋กœ ๋ชฉ๋ก์„ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค.
SK (Secret Key)ํ•ด๋‹น CSN์— ๋Œ€ํ•ด ์“ฐ๊ธฐ(๋“ฑ๋ก) ๊ถŒํ•œ์„ ๊ฐ€์ง„ ๋น„๋ฐ€ํ‚ค. ํ”„๋กœ์ ํŠธ ๊ด€๋ฆฌ์ž์—๊ฒŒ ํ•ด๋‹น CSN์šฉ SK ๋ฐœ๊ธ‰์„ ์š”์ฒญํ•˜์„ธ์š” โ€” ์ด ํ™”๋ฉด์ด๋‚˜ API๋กœ ์Šค์Šค๋กœ ๋ฐœ๊ธ‰๋ฐ›์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.
๋“ฑ๋ก ์—”๋“œํฌ์ธํŠธhttps://giipfaw.azurewebsites.net/api/giipApiSk4 (anonymous ์ธ์ฆ โ€” Function key ๋ถˆํ•„์š”, ์š”์ฒญ ํผ์˜ SK ํ† ํฐ์œผ๋กœ ์ธ์ฆ)

์ฝ˜์†”์„ ์ด ํ™”๋ฉด์— ๋“ฑ๋กํ•˜๊ธฐ โ€” ๊ทธ๋Œ€๋กœ ๋ณต์‚ฌํ•ด์„œ ์ฝ˜์†”์— ๋ถ™์—ฌ๋„ฃ๊ธฐ

์ด ํ™”๋ฉด์˜ "Open Interactive Sessions" ์— ์ง€๊ธˆ ์“ฐ๋Š” Claude Code ์ฝ˜์†”์ด ๋ณด์ด์ง€ ์•Š์œผ๋ฉด, ์•„๋ž˜ ์š”์ฒญ๋ฌธ์„ ์ฝ˜์†”(Claude Code)์— ๊ทธ๋Œ€๋กœ ๋ถ™์—ฌ๋„ฃ์œผ๋ฉด ๋ฉ๋‹ˆ๋‹ค. ์ฝ˜์†”์ด ์•„๋ž˜ "๋ฐฉ๋ฒ• A" ์˜ ๊ทœ๊ฒฉ(agentKey ๊ทœ์น™, SP ํ˜ธ์ถœ)๋งŒ์œผ๋กœ ๋“ฑ๋ก์„ ์ˆ˜ํ–‰ํ•˜๋ฏ€๋กœ ๋ณ„๋„ ์Šคํฌ๋ฆฝํŠธ๋‚˜ ๋‹ค๋ฅธ ์ €์žฅ์†Œ๊ฐ€ ํ•„์š” ์—†์Šต๋‹ˆ๋‹ค. <CSN> ์€ ๋“ฑ๋กํ•  ํ”„๋กœ์ ํŠธ ๋ฒˆํ˜ธ๋กœ ๋ฐ”๊ฟ” ๋„ฃ์œผ์„ธ์š”.

์‚ฌ์ „์กฐ๊ฑด: ๋Œ€์ƒ CSN ์šฉ SK ๊ฐ€ ์ด PC ์˜ ์ƒ์œ„ ํด๋” giipAgent.cnf(๋˜๋Š” giipAgent.cfg)์— sk= ๋กœ ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค(์—†์œผ๋ฉด ํ”„๋กœ์ ํŠธ ๊ด€๋ฆฌ์ž์—๊ฒŒ ํ•ด๋‹น CSN ์šฉ SK ๋ฐœ๊ธ‰์„ ์š”์ฒญ). ์ฝ˜์†”์€ SK ๋ฅผ ์‚ฌ์šฉ์ž์—๊ฒŒ ๋˜๋ฌป์ง€ ์•Š๊ณ  ๊ทธ ํŒŒ์ผ์—์„œ ์ฝ์Šต๋‹ˆ๋‹ค.

์š”์ฒญ๋ฌธ 1 โ€” ์ง€๊ธˆ ์—ด๋ฆฐ ์ด ์ฝ˜์†”์„ ํ•œ ๋ฒˆ ๋“ฑ๋ก

giip ์Šค์ผ€์ค„๋Ÿฌ ์—์ด์ „ํŠธ ํ™”๋ฉด(/ko/admin/catquest/schedulers)์— ์ง€๊ธˆ ์—ด๋ ค ์žˆ๋Š” ์ด ์ฝ˜์†” ์„ธ์…˜์„ CSN <CSN> ์˜ ๋Œ€ํ™”ํ˜• ์„ธ์…˜์œผ๋กœ ํ•œ ๋ฒˆ ๋“ฑ๋กํ•ด์ค˜.
์ด ๋ฌธ์„œ(/help/catquest-schedulers.ko.md)์˜ "๋ฐฉ๋ฒ• A โ€” ๋Œ€ํ™”ํ˜• Claude Code ์„ธ์…˜ ๋“ฑ๋ก"์„ ์ฝ๊ณ  ๊ทธ ๊ทœ๊ฒฉ ๊ทธ๋Œ€๋กœ ๋”ฐ๋ผ. register-interactive-session.ps1 ๊ฐ™์€ ๋ณ„๋„ ์Šคํฌ๋ฆฝํŠธ๋Š” ์—†๋Š” ๊ฒƒ์œผ๋กœ ๋ณด๊ณ , ๋ฌธ์„œ์— ์ ํžŒ giipApiSk4 ํ˜ธ์ถœ(HTTP POST, ํผ ํ•„๋“œ text/token/jsondata)์„ ์ง์ ‘ ์‹คํ–‰ํ•ด.
1. agentKey: ๋ฌธ์„œ์˜ "agentKey ์ƒ์„ฑ ๊ทœ์น™" 5๋‹จ๊ณ„๋Œ€๋กœ ๋งŒ๋“ค์–ด. ์›๋ณธ ID ๋Š” ์ด ์„ธ์…˜์˜ session_id ๋ฅผ ์•Œ๋ฉด ๊ทธ ๊ฐ’, ๋ชจ๋ฅด๋ฉด fallback_<COMPUTERNAME>_<PID>. COMPUTERNAME ํ™˜๊ฒฝ๋ณ€์ˆ˜๊ฐ€ ์—†์œผ๋ฉด hostname ๋ช…๋ น ๊ฒฐ๊ณผ๋ฅผ ์จ.
2. SchedulerAgentUpsert: text ๋Š” "SchedulerAgentUpsert agentKey displayName hostIdentifier windowsTaskName projectName scheduleDesc isActive lssn osType agentType version". jsondata ๋Š” agentKey, displayName="Claude Interactive Session (<ํ˜ธ์ŠคํŠธ๋ช…>)", hostIdentifier=<ํ˜ธ์ŠคํŠธ๋ช…>, windowsTaskName/projectName/scheduleDesc ๋Š” ๋นˆ ๋ฌธ์ž์—ด, isActive="1", lssn="0", osType=Windows ๋˜๋Š” Linux, agentType="claude_interactive_session", version="". ํ™˜๊ฒฝ๋ณ€์ˆ˜ CLAUDE_CODE_BRIDGE_SESSION_ID ๊ฐ€ ์žˆ์œผ๋ฉด text ์™€ jsondata ๋งจ ๋์— capabilities={"sessionUrl":"https://claude.ai/code/<๊ทธ ๊ฐ’>"} ๋ฅผ ์ถ”๊ฐ€ํ•˜๊ณ , ์—†์œผ๋ฉด capabilities ๋ฅผ ํ†ต์งธ๋กœ ๋นผ. ๋‹ค๋ฅธ ๊ฐ’์œผ๋กœ sessionUrl ์„ ๋งŒ๋“ค์–ด๋‚ด์ง€ ๋งˆ.
3. SchedulerAgentRunStart: text ๋Š” "SchedulerAgentRunStart runIdKey agentKey executionMode totalIssueCount". runIdKey=<agentKey>_<ํ˜„์žฌ์‹œ๊ฐ yyyyMMddHHmmss>, executionMode="interactive", totalIssueCount="0".
4. SK ๋Š” ์ƒ์œ„ ํด๋”์˜ giipAgent.cnf(์—†์œผ๋ฉด giipAgent.cfg)์˜ sk= ๊ฐ’์„ ์ฝ์–ด token ์œผ๋กœ ์จ. ๋‚˜์—๊ฒŒ ๋˜๋ฌป์ง€ ๋ง๊ณ , SK ๊ฐ’์€ ํ™”๋ฉดยท๋กœ๊ทธยทํŒŒ์ผ ์–ด๋””์—๋„ ์ถœ๋ ฅํ•˜๊ฑฐ๋‚˜ ๊ธฐ๋กํ•˜์ง€ ๋งˆ.
5. ํ™•์ธ: ๊ฐ™์€ giipApiSk4 ๋กœ text "SchedulerAgentList csn", jsondata {"csn":"<CSN>"} ๋ฅผ ํ˜ธ์ถœํ•ด ๋ฐฉ๊ธˆ ๋งŒ๋“  agentKey ์˜ ํ–‰์ด is_active=true, current_status=RUNNING ์ธ์ง€ ํ™•์ธํ•ด. ๊ฒฐ๊ณผ์™€ ์‚ฌ์šฉํ•œ agentKey/runIdKey ๋ฅผ ์•Œ๋ ค์ค˜(๊ฐ’ ์ค‘ SK ๋Š” ์ œ์™ธ).

์š”์ฒญ๋ฌธ 2 โ€” ์•ž์œผ๋กœ ๋ชจ๋“  ์„ธ์…˜์ด ์ž๋™ ๋“ฑ๋ก๋˜๊ฒŒ ํ›… ์„ค์ •

์ด PC ์—์„œ Claude Code ์„ธ์…˜์ด ์—ด๋ฆฌ๊ณ  ๋‹ซํž ๋•Œ๋งˆ๋‹ค giip ์Šค์ผ€์ค„๋Ÿฌ ์—์ด์ „ํŠธ ํ™”๋ฉด์— ์ž๋™์œผ๋กœ ๋“ฑ๋ก/ํ•ด์ œ๋˜๋„๋ก SessionStart/SessionEnd ํ›…์„ ์„ค์ •ํ•ด์ค˜. ๋Œ€์ƒ CSN ์€ <CSN>.
์ด ๋ฌธ์„œ(/help/catquest-schedulers.ko.md)์˜ "๋ฐฉ๋ฒ• A โ€” ๋Œ€ํ™”ํ˜• Claude Code ์„ธ์…˜ ๋“ฑ๋ก"์„ ์ฝ๊ณ  ๊ทธ ๊ทœ๊ฒฉ๋งŒ์œผ๋กœ ์ง์ ‘ ๊ตฌํ˜„ํ•ด. ๋‹ค๋ฅธ ์ €์žฅ์†Œ์—์„œ ์Šคํฌ๋ฆฝํŠธ๋ฅผ ๊ฐ€์ ธ์˜ค๋ ค ํ•˜์ง€ ๋งˆ.
1. ํ›… ์ฒ˜๋ฆฌ ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์‚ฌ์šฉ์ž ํ™ˆ ์•„๋ž˜ ํ•œ ๊ณณ(์˜ˆ: ~/.claude/giip-console-hook.ps1)์— ๋งŒ๋“ค์–ด. ์ธ์ž๋กœ Start ๋˜๋Š” End ๋ฅผ ๋ฐ›๊ณ , ํ‘œ์ค€์ž…๋ ฅ์œผ๋กœ ํ›… ์ด๋ฒคํŠธ JSON ์„ ์ฝ์–ด. Windows ๊ฐ€ ์•„๋‹ˆ๋ฉด pwsh ๋‚˜ bash ๋กœ ์ž‘์„ฑํ•ด๋„ ๋ผ.
2. ํ›… ๋“ฑ๋ก์€ ๋ฌธ์„œ์˜ JSON ๋Œ€๋กœ ~/.claude/settings.json(์ „์—ญ)์˜ hooks.SessionStart ์™€ hooks.SessionEnd ์— command ํ›…์„ ์ถ”๊ฐ€ํ•ด. matcher ๋Š” ๋„ฃ์ง€ ๋งˆ. ์ด๋ฏธ ์žˆ๋Š” hooks ํ•ญ๋ชฉ์€ ๋ฎ์–ด์“ฐ์ง€ ๋ง๊ณ  ๋ฐฐ์—ด์— ์ถ”๊ฐ€ํ•˜๊ณ , ๋ฌธ์„œ JSON ์˜ timeout ๊ฐ’์„ ๊ทธ๋Œ€๋กœ ์จ.
3. ํ—ค๋“œ๋ฆฌ์Šค ์ œ์™ธ: ์Šคํฌ๋ฆฝํŠธ๋Š” ๋จผ์ € ๋ถ€๋ชจ ํ”„๋กœ์„ธ์Šค๋ฅผ ๊ฑฐ์Šฌ๋Ÿฌ ์˜ฌ๋ผ๊ฐ€ claude ํ”„๋กœ์„ธ์Šค์˜ ์ปค๋งจ๋“œ๋ผ์ธ์— -p ๋˜๋Š” --print ๊ฐ€ ์žˆ์œผ๋ฉด ์•„๋ฌด๊ฒƒ๋„ ํ•˜์ง€ ์•Š๊ณ  ์ข…๋ฃŒํ•ด(๋ฌธ์„œ์˜ ํ—ค๋“œ๋ฆฌ์Šค ํŒ์ •). CLAUDE_CODE_BRIDGE_SESSION_ID ์˜ ์œ ๋ฌด๋กœ ํ—ค๋“œ๋ฆฌ์Šค๋ฅผ ํŒ์ •ํ•˜์ง€ ๋งˆ.
4. Start: agentKey ๋Š” ๋ฌธ์„œ์˜ "agentKey ์ƒ์„ฑ ๊ทœ์น™"๋Œ€๋กœ(์›๋ณธ ID = stdin ์˜ session_id, ์—†์œผ๋ฉด fallback_<COMPUTERNAME>_<PID>) ๋งŒ๋“  ๋’ค, SchedulerAgentUpsert(agentType="claude_interactive_session", isActive="1", ํ•„๋“œ์™€ ์ˆœ์„œ๋Š” ๋ฌธ์„œ์˜ ์˜ˆ์‹œ์™€ ๋™์ผ)์™€ SchedulerAgentRunStart(executionMode="interactive", totalIssueCount="0")๋ฅผ ํ˜ธ์ถœํ•ด. runIdKey=<agentKey>_<ํ˜„์žฌ์‹œ๊ฐ yyyyMMddHHmmss> ์ด๊ณ , End ์—์„œ ์“ฐ๋„๋ก ์ž„์‹œ ํด๋”์˜ ํŒŒ์ผ์— ์ €์žฅํ•ด. CLAUDE_CODE_BRIDGE_SESSION_ID ๊ฐ€ ์žˆ์„ ๋•Œ๋งŒ capabilities.sessionUrl ์„ ๋„ฃ๊ณ , ์—†์œผ๋ฉด capabilities ๋ฅผ ๋บ€ ์ฑ„ ๋“ฑ๋ก์„ ๊ณ„์†ํ•ด.
5. End: ๊ฐ™์€ ๊ทœ์น™์œผ๋กœ agentKey ๋ฅผ ๋‹ค์‹œ ๊ณ„์‚ฐํ•ด SchedulerAgentRunEnd(status="ENDED", processedCount/skippedCount/failedCount="0")๋ฅผ ํ˜ธ์ถœํ•˜๊ณ , ์ด์–ด์„œ SchedulerAgentUpsert ๋ฅผ isActive="0" ์œผ๋กœ ํ˜ธ์ถœํ•ด ์˜คํ”„๋ผ์ธ์œผ๋กœ ์ „ํ™˜ํ•ด.
6. ํ˜ธ์ถœ์€ ๋ชจ๋‘ giipApiSk4(text/token/jsondata)๋กœ ํ•˜๊ณ , ํ›…์ด ์‹คํŒจํ•ด๋„ ์„ธ์…˜์ด ๋ง‰ํžˆ์ง€ ์•Š๊ฒŒ ํ•ญ์ƒ ์ข…๋ฃŒ์ฝ”๋“œ 0 ์œผ๋กœ ๋๋‚ด.
7. SK ๊ฐ’์€ ์Šคํฌ๋ฆฝํŠธ์— ๋„ฃ์ง€ ๋ง๊ณ , ์‹คํ–‰ํ•  ๋•Œ๋งˆ๋‹ค giipAgent.cnf(์—†์œผ๋ฉด giipAgent.cfg)์˜ sk= ์—์„œ ์ฝ๋„๋ก ๊ทธ ํŒŒ์ผ์˜ ์ ˆ๋Œ€๊ฒฝ๋กœ๋งŒ ์ ์–ด. ๋‚˜์—๊ฒŒ ๋˜๋ฌป์ง€ ๋ง๊ณ , SK ๊ฐ’์€ ์ถœ๋ ฅยท๋กœ๊ทธยทํŒŒ์ผ์— ๋‚จ๊ธฐ์ง€ ๋งˆ.
8. ๋๋‚˜๋ฉด ๋งŒ๋“ค๊ฑฐ๋‚˜ ๋ฐ”๊พผ ํŒŒ์ผ์˜ ๊ฒฝ๋กœ ๋ชฉ๋ก๊ณผ, ์ƒˆ ์„ธ์…˜์—์„œ ๋“ฑ๋ก๋๋Š”์ง€ ํ™•์ธํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์•Œ๋ ค์ค˜.
  • ์š”์ฒญ๋ฌธ 1 ๋กœ ๋“ฑ๋กํ•œ ์„ธ์…˜์€ ์ข…๋ฃŒ ํ›…์ด ์—†์œผ๋ฏ€๋กœ, ๋‹ซ์„ ๋•Œ ํ•ด์ œํ•˜๋ ค๋ฉด ์ฝ˜์†”์—๊ฒŒ "์•Œ๋ ค์ค€ agentKey/runIdKey ๋กœ SchedulerAgentRunEnd ๋ฅผ ํ˜ธ์ถœํ•˜๊ณ  SchedulerAgentUpsert ๋ฅผ isActive=0 ์œผ๋กœ ํ˜ธ์ถœํ•ด์ค˜" ๋ผ๊ณ  ์š”์ฒญํ•˜์„ธ์š”. ํ›…(์š”์ฒญ๋ฌธ 2)์„ ์“ฐ๋ฉด ์ข…๋ฃŒ ์‹œ ์ž๋™์œผ๋กœ ํ•ด์ œ๋ฉ๋‹ˆ๋‹ค.
  • ์„ฑ๊ณต ํ™•์ธ: ํ™”๋ฉด ์ƒˆ๋กœ๊ณ ์นจ ์‹œ "Open Interactive Sessions" ์นด๋“œ์™€ ์—์ด์ „ํŠธ ๋ชฉ๋ก์— ์„ธ์…˜์ด ๋‚˜ํƒ€๋‚ฉ๋‹ˆ๋‹ค. ์ƒ์„ธ ๊ทœ๊ฒฉ์€ ์•„๋ž˜ "๋ฐฉ๋ฒ• A" ๋ฅผ ์ฐธ๊ณ ํ•˜์„ธ์š”.

๋ฐฉ๋ฒ• A โ€” ๋Œ€ํ™”ํ˜• Claude Code ์„ธ์…˜ ๋“ฑ๋ก

Claude Code ๊ฐ™์€ ๋Œ€ํ™”ํ˜• AI ์ฝ”๋”ฉ ์„ธ์…˜์„ "Open Interactive Sessions" ์นด๋“œ์— ๋‚˜ํƒ€๋‚˜๊ฒŒ ํ•˜๋ ค๋ฉด, ์„ธ์…˜์˜ SessionStart/SessionEnd ํ›…์—์„œ ์•„๋ž˜ ์ ˆ์ฐจ๋ฅผ ์‹คํ–‰ํ•˜๋„๋ก ๊ตฌ์„ฑํ•ฉ๋‹ˆ๋‹ค.

  1. ์‚ฌ์ „์กฐ๊ฑด: ์œ„ ๊ณตํ†ต ์‚ฌ์ „์กฐ๊ฑด(๋Œ€์ƒ CSN์šฉ SK) + ์„ธ์…˜์„ ์‹คํ–‰ํ•˜๋Š” ๋„๊ตฌ(Claude Code ๋“ฑ)์— SessionStart/SessionEnd ํ›…์„ ๋“ฑ๋กํ•  ์ˆ˜ ์žˆ๋Š” ์„ค์ • ๊ถŒํ•œ.
  2. ์„ธ์…˜ ์‹œ์ž‘(SessionStart) ์‹œ โ€” SchedulerAgentUpsert ํ˜ธ์ถœ๋กœ identity ๋“ฑ๋ก/๊ฐฑ์‹  ํ›„ SchedulerAgentRunStart ํ˜ธ์ถœ๋กœ ์‹คํ–‰ ์‹œ์ž‘์„ ๊ธฐ๋กํ•ฉ๋‹ˆ๋‹ค.
  3. ์„ธ์…˜ ์ข…๋ฃŒ(SessionEnd) ์‹œ โ€” SchedulerAgentRunEnd ํ˜ธ์ถœ๋กœ ์‹คํ–‰ ์ข…๋ฃŒ๋ฅผ ๊ธฐ๋กํ•˜๊ณ , SchedulerAgentUpsert๋ฅผ isActive=0์œผ๋กœ ๋‹ค์‹œ ํ˜ธ์ถœํ•ด ์˜คํ”„๋ผ์ธ์œผ๋กœ ์ „ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

agentKey ์ƒ์„ฑ ๊ทœ์น™(๊ทธ๋Œ€๋กœ ์ ์šฉ, ํŒ๋‹จ ๋ถˆํ•„์š”): csn + agentKey ์กฐํ•ฉ์ด DB์—์„œ UNIQUE ์ œ์•ฝ์ด๋ฏ€๋กœ, ๊ฐ™์€ ์„ธ์…˜์„ ์žฌ์‹œ์ž‘ํ•ด๋„ ํ•ญ์ƒ ๊ฐ™์€ ๊ฐ’์ด ๋‚˜์™€์•ผ ํ•ฉ๋‹ˆ๋‹ค(๊ทธ๋ž˜์•ผ ์žฌ์‹œ์ž‘ ์‹œ ์ƒˆ ํ–‰์ด ์•„๋‹ˆ๋ผ ๊ธฐ์กด ํ–‰์ด ๊ฐฑ์‹ ๋ฉ๋‹ˆ๋‹ค). ์•„๋ž˜ ์ˆœ์„œ๋ฅผ ๊ทธ๋Œ€๋กœ ์ ์šฉํ•ด ๊ณ„์‚ฐํ•˜์‹ญ์‹œ์˜ค.

  1. ์›๋ณธ ID: ํ›… stdin JSON์˜ session_id ํ•„๋“œ ๊ฐ’์ด ์žˆ์œผ๋ฉด ๊ทธ ๊ฐ’์„ ์“ด๋‹ค. ์—†์œผ๋ฉด fallback_<COMPUTERNAME ํ™˜๊ฒฝ๋ณ€์ˆ˜ ๊ฐ’>_<ํ˜„์žฌ ํ”„๋กœ์„ธ์Šค PID> ๋ฅผ ์›๋ณธ ID๋กœ ์“ด๋‹ค.
  2. ์ •๊ทœํ™”: ์›๋ณธ ID์—์„œ ์˜์ˆซ์ž(a-z, A-Z, 0-9)๊ฐ€ ์•„๋‹Œ ๋ฌธ์ž๋ฅผ ๋ชจ๋‘ ์ œ๊ฑฐํ•œ๋‹ค(์ •๊ทœ์‹ ์น˜ํ™˜: [^a-zA-Z0-9] โ†’ '').
  3. ์ž๋ฅด๊ธฐ(1์ฐจ): ์ •๊ทœํ™”๋œ ๊ฐ’์ด 24์ž๋ฅผ ๋„˜์œผ๋ฉด ์•ž 24์ž๋งŒ ๋‚จ๊ธด๋‹ค.
  4. ์กฐํ•ฉ: agentKey = "claude_interactive_" + <COMPUTERNAME ํ™˜๊ฒฝ๋ณ€์ˆ˜ ๊ฐ’> + "_" + <3๋‹จ๊ณ„ ๊ฒฐ๊ณผ๊ฐ’>
  5. ์ž๋ฅด๊ธฐ(2์ฐจ): 4๋‹จ๊ณ„ ๊ฒฐ๊ณผ๊ฐ€ 100์ž๋ฅผ ๋„˜์œผ๋ฉด ์•ž 100์ž๋งŒ ๋‚จ๊ธด๋‹ค. ์ด ์ตœ์ข… ๊ฐ’์„ agentKey๋กœ ์“ด๋‹ค.

SessionStart/SessionEnd ํ›… ๋“ฑ๋ก ์œ„์น˜(๊ทธ๋Œ€๋กœ ๋ถ™์—ฌ๋„ฃ์„ JSON): Claude Code์—์„œ๋Š” ํ”„๋กœ์ ํŠธ ๋ฃจํŠธ์˜ .claude/settings.json(ํ•ด๋‹น ํ”„๋กœ์ ํŠธ์—๋งŒ ์ ์šฉ) ๋˜๋Š” ์‚ฌ์šฉ์ž ํ™ˆ์˜ ~/.claude/settings.json(๋ชจ๋“  ํ”„๋กœ์ ํŠธ์— ์ „์—ญ ์ ์šฉ) ์ค‘ ํ•˜๋‚˜๋ฅผ ๊ณ ๋ฅธ ๋’ค, ๊ทธ ํŒŒ์ผ์˜ ์ตœ์ƒ์œ„์— ์•„๋ž˜ hooks ํ‚ค๋ฅผ ๋ณ‘ํ•ฉํ•˜์‹ญ์‹œ์˜ค. ํŒŒ์ผ์— ์ด๋ฏธ hooks ํ‚ค๊ฐ€ ์žˆ๋‹ค๋ฉด SessionStart/SessionEnd ๋ฐฐ์—ด ์•ˆ์— ์•„๋ž˜ ๊ฐ์ฒด๋ฅผ ์ถ”๊ฐ€ํ•˜์‹ญ์‹œ์˜ค(๊ธฐ์กด ํ•ญ๋ชฉ์„ ๋ฎ์–ด์“ฐ์ง€ ๋งˆ์‹ญ์‹œ์˜ค). matcher ํ•„๋“œ๋Š” ๋„ฃ์ง€ ์•Š์Šต๋‹ˆ๋‹ค โ€” ์ด ํ›…์€ ๋ชจ๋“  ์„ธ์…˜์— ์ „์—ญ ์ ์šฉ๋ฉ๋‹ˆ๋‹ค.

{
  "hooks": {
    "SessionStart": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "<์„ธ์…˜ ์‹œ์ž‘ ์‹œ ์‹คํ–‰ํ•  command. ์˜ˆ: powershell -NoProfile -ExecutionPolicy Bypass -File \"<๋“ฑ๋ก ์Šคํฌ๋ฆฝํŠธ์˜ ์ ˆ๋Œ€๊ฒฝ๋กœ>\" -Action Start>",
            "timeout": 15000
          }
        ]
      }
    ],
    "SessionEnd": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "<์„ธ์…˜ ์ข…๋ฃŒ ์‹œ ์‹คํ–‰ํ•  command. ์˜ˆ: powershell -NoProfile -ExecutionPolicy Bypass -File \"<๋“ฑ๋ก ์Šคํฌ๋ฆฝํŠธ์˜ ์ ˆ๋Œ€๊ฒฝ๋กœ>\" -Action End>",
            "timeout": 15000
          }
        ]
      }
    ]
  }
}

โš ๏ธ ์ „์—ญ(matcher ์—†๋Š”) ํ›…์œผ๋กœ ๋“ฑ๋กํ•œ ๊ฒฝ์šฐ ํ—ค๋“œ๋ฆฌ์Šค ์˜คํŒ์ • ์ฃผ์˜(giip #1837): ์œ„ ํ›…์€ matcher๊ฐ€ ์—†์–ด ์ด ํ˜ธ์ŠคํŠธ์—์„œ ์‹คํ–‰๋˜๋Š” ๋ชจ๋“  claude ํ”„๋กœ์„ธ์Šค(๋Œ€ํ™”ํ˜• ์„ธ์…˜๋ฟ ์•„๋‹ˆ๋ผ, ๋ฌด์ธ ์Šค์ผ€์ค„๋Ÿฌ๊ฐ€ claude -p๋กœ ์—ฌ๋Š” ํ—ค๋“œ๋ฆฌ์Šค ์‹คํ–‰๊นŒ์ง€ ์ „๋ถ€)์—์„œ ๋ฐœํ™”ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ๋“ฑ๋ก ์Šคํฌ๋ฆฝํŠธ ์•ˆ์— "์ง€๊ธˆ ์ด ์‹คํ–‰์ด ๋Œ€ํ™”ํ˜•์ธ์ง€ ํ—ค๋“œ๋ฆฌ์Šค์ธ์ง€" ํŒ์ • ๋กœ์ง์ด ์‚ฌ์‹ค์ƒ ํ•„์ˆ˜์ž…๋‹ˆ๋‹ค. ์ด๋•Œ $env:CLAUDE_CODE_BRIDGE_SESSION_ID(Remote Control ๋ธŒ๋ฆฟ์ง€ ์—ฐ๊ฒฐ ์—ฌ๋ถ€)๋ฅผ ํŒ์ • ๊ธฐ์ค€์œผ๋กœ ์“ฐ์ง€ ๋งˆ์‹ญ์‹œ์˜ค โ€” ์ด ๊ฐ’์€ ๋ธŒ๋ฆฟ์ง€ ์—ฐ๊ฒฐ ์—ฌ๋ถ€๋งŒ ๋‚˜ํƒ€๋‚ผ ๋ฟ ํ—ค๋“œ๋ฆฌ์Šค ์—ฌ๋ถ€์™€ ๋ฌด๊ด€ํ•˜๋ฉฐ, ์ง„์งœ ๋Œ€ํ™”ํ˜• ์„ธ์…˜๋„ ์•„์ง /remote-control์„ ์‹คํ–‰/์—ฐ๊ฒฐํ•˜์ง€ ์•Š์•˜๋‹ค๋ฉด ์ด ๊ฐ’์ด ์—†์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค(๊ทธ๋Ÿฐ ์„ธ์…˜๊นŒ์ง€ ํ—ค๋“œ๋ฆฌ์Šค๋กœ ์˜คํŒํ•ด ๋“ฑ๋ก ์ž์ฒด๊ฐ€ ์Šคํ‚ต๋˜๋Š” ์‚ฌ๊ณ ๊ฐ€ ์‹ค์ œ๋กœ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค โ€” giip #1837). ์˜ฌ๋ฐ”๋ฅธ ํŒ์ • ๋ฐฉ๋ฒ•: ์ด ํ›…์„ ์‹คํ–‰ํ•˜๋Š” ํ”„๋กœ์„ธ์Šค ์ž์‹ ์˜ ๋ถ€๋ชจ๋ฅผ ๊ฑฐ์Šฌ๋Ÿฌ ์˜ฌ๋ผ๊ฐ€ ์‹ค์ œ claude/claude.exe ํ”„๋กœ์„ธ์Šค๋ฅผ ์ฐพ๊ณ , ๊ทธ ํ”„๋กœ์„ธ์Šค์˜ ์ปค๋งจ๋“œ๋ผ์ธ์— -p/--print ํ”Œ๋ž˜๊ทธ๊ฐ€ ์žˆ๋Š”์ง€๋กœ ํŒ์ •ํ•˜์‹ญ์‹œ์˜ค. Windows PowerShell ์˜ˆ์‹œ(๊ทธ๋Œ€๋กœ ์ ์šฉ):

function Test-IsHeadlessClaudeInvocation {
    try {
        $checkPid = $PID
        for ($i = 0; $i -lt 6; $i++) {
            $proc = Get-CimInstance Win32_Process -Filter "ProcessId=$checkPid" -ErrorAction Stop
            if (-not $proc) { return $false }
            if ($proc.Name -eq 'claude.exe') {
                $cmd = $proc.CommandLine
                if ($cmd -and ($cmd -match '(^|\s)(-p|--print)(\s|$)')) { return $true }
                return $false
            }
            $checkPid = $proc.ParentProcessId
            if (-not $checkPid -or $checkPid -eq 0) { return $false }
        }
        return $false
    } catch {
        return $false
    }
}

Windows๊ฐ€ ์•„๋‹Œ ํ™˜๊ฒฝ์—์„œ๋Š” ๋™์ผํ•œ ์›๋ฆฌ(๋ถ€๋ชจ ํ”„๋กœ์„ธ์Šค์˜ ์ปค๋งจ๋“œ๋ผ์ธ์—์„œ -p/--print ํ™•์ธ)๋ฅผ ํ•ด๋‹น OS์˜ ํ”„๋กœ์„ธ์Šค ์กฐํšŒ ๋ฐฉ๋ฒ•์œผ๋กœ ๊ตฌํ˜„ํ•˜์‹ญ์‹œ์˜ค. ์ด ํŒ์ •์€ "๋“ฑ๋ก ์ž์ฒด๋ฅผ ํ• ์ง€ ๋ง์ง€"(Start/End ์Šคํ‚ต ์—ฌ๋ถ€)์—๋งŒ ์“ฐ๊ณ , ์•„๋ž˜ sessionUrl ๊ด€๋ จ ํŒ์ •๊ณผ๋Š” ์™„์ „ํžˆ ๋ณ„๊ฐœ์ž…๋‹ˆ๋‹ค โ€” ํ˜ผ๋™ํ•˜์ง€ ๋งˆ์‹ญ์‹œ์˜ค.

์ด command๋Š” ํ‘œ์ค€์ž…๋ ฅ(stdin)์œผ๋กœ ํ›… ์ด๋ฒคํŠธ JSON(session_id ๋“ฑ ํฌํ•จ)์„ ๋ฐ›์Šต๋‹ˆ๋‹ค. ์•„๋ž˜ ์ด ๋ฌธ์„œ์— ์ ํžŒ SP ํ˜ธ์ถœ ์ŠคํŽ™(ํ˜ธ์ถœ ๊ทœ์•ฝ, ํ•„๋“œ ๋ชฉ๋ก, agentKey ์ƒ์„ฑ ๊ทœ์น™)๋งŒ์œผ๋กœ ์ž๊ธฐ ์™„๊ฒฐ์ ์œผ๋กœ ๊ตฌํ˜„ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค โ€” ์ด ๋ฌธ์„œ๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ์šด์˜์ž๊ฐ€ ๊ฐœ์ธ์ ์œผ๋กœ ์ฐธ๊ณ ํ•˜๋Š” ๊ตฌํ˜„์ฒด๊ฐ€ ์žˆ๋”๋ผ๋„ ๊ทธ ์ €์žฅ์†Œ๋Š” ๋น„๊ณต๊ฐœ๋ผ ๋‹ค๋ฅธ ์„ธ์…˜์ด ์ ‘๊ทผํ•  ์ˆ˜ ์—†์œผ๋‹ˆ, ์ฝ”๋“œ๋ฅผ ์–ด๋”˜๊ฐ€์—์„œ ๊ฐ€์ ธ์˜ค๋ ค ํ•˜์ง€ ๋ง๊ณ  ์ด ๋ฌธ์„œ์˜ ์ŠคํŽ™๋งŒ์œผ๋กœ ์ง์ ‘ ์ž‘์„ฑํ•˜์‹ญ์‹œ์˜ค.

์ด๋•Œ agentKey์™€ capabilities.sessionUrl์€ ์„œ๋กœ ๋‹ค๋ฅธ ๊ฐ’์—์„œ ๋‚˜์˜ค๋Š” ๋ณ„๊ฐœ์˜ ID๋ผ๋Š” ์ ์— ์ฃผ์˜ํ•˜์„ธ์š” โ€” ์ด ๋‘˜์„ ํ˜ผ๋™ํ•˜๋ฉด "์„ธ์…˜ ID๊ฐ€ ์—†์–ด์„œ URL์„ ๋ชป ๋งŒ๋“ ๋‹ค"๋Š” ์ฐฉ๊ฐ์— ๋น ์ ธ ๋“ฑ๋ก ์ž์ฒด๋ฅผ ํฌ๊ธฐํ•˜๊ฒŒ ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:

  • agentKey โ€” ํ›… stdin์˜ session_id(ํ•˜๋‹ˆ์Šค ๋‚ด๋ถ€ UUID, ์˜ˆ: ~/.claude/projects/*/<uuid>.jsonl ํŒŒ์ผ๋ช…์— ์“ฐ์ด๋Š” ๊ฐ’) ๊ธฐ๋ฐ˜์œผ๋กœ ๊ตฌ์„ฑํ•ฉ๋‹ˆ๋‹ค. "์žฌ์‹œ์ž‘ํ•ด๋„ ๊ฐ™์€ ์„ธ์…˜์ด๋ฉด ๊ฐ™์€ ํ‚ค๊ฐ€ ๋‚˜์˜ค๊ฒŒ" ํ•˜๊ธฐ ์œ„ํ•œ ์šฉ๋„์ผ ๋ฟ, URL์ด ์•„๋‹™๋‹ˆ๋‹ค.
  • capabilities.sessionUrl โ€” ์žˆ๋‹ค๋ฉด $env:CLAUDE_CODE_BRIDGE_SESSION_ID(์˜ˆ: session_01JGmSiTajXu9iZmjVZC27Nt ๊ฐ™์€ ULID ์Šคํƒ€์ผ ๊ฐ’ โ€” ํ›… stdin์˜ session_id์™€๋Š” ๊ฐ’์ด ๋‹ค๋ฅธ ๋ณ„๊ฐœ์˜ ID)๋ฅผ ์ด์šฉํ•ด https://claude.ai/code/<์ด ๊ฐ’> ํ˜•ํƒœ๋กœ ๊ตฌ์„ฑํ•ฉ๋‹ˆ๋‹ค.

์ด ํ™˜๊ฒฝ๋ณ€์ˆ˜๋Š” ๋ชจ๋“  ์„ธ์…˜์— ์žˆ๋Š” ๊ฒŒ ์•„๋‹™๋‹ˆ๋‹ค โ€” ์˜ˆ๋ฅผ ๋“ค์–ด claude.ai/code ๋ธŒ๋ฆฟ์ง€๋ฅผ ๊ฑฐ์น˜์ง€ ์•Š์€ ๋กœ์ปฌ CLI ์„ธ์…˜์—๋Š” ์—†์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. $env:CLAUDE_CODE_BRIDGE_SESSION_ID๊ฐ€ ์—†๋‹ค๋ฉด sessionUrl์„ ๋งŒ๋“ค ์ˆ˜ ์—†๋‹ค๋Š” ๋œป์ด์ง€, ๋“ฑ๋ก์ด ๋ง‰ํžŒ๋‹ค๋Š” ๋œป์ด ์•„๋‹™๋‹ˆ๋‹ค โ€” ๊ทธ๋Ÿด ๋•Œ๋Š” capabilities ํ•„๋“œ ์ž์ฒด๋ฅผ ํ˜ธ์ถœ์—์„œ ํ†ต์งธ๋กœ ๋นผ๊ณ  ๋‚˜๋จธ์ง€ ํ•„๋“œ๋งŒ์œผ๋กœ ๋“ฑ๋ก์„ ๊ณ„์† ์ง„ํ–‰ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค(์•„๋ž˜ "sessionUrl์„ ๋งŒ๋“ค ์ˆ˜ ์—†์„ ๋•Œ" ์ฐธ๊ณ ).

CLAUDE_CODE_BRIDGE_SESSION_ID๊ฐ€ ์–ธ์ œ ์ƒ๊ธฐ๋Š”์ง€, ์—†์„ ๋•Œ ์‚ฌํ›„์— ์–ป์„ ์ˆ˜ ์žˆ๋Š”์ง€(๊ณต์‹ ๋ฌธ์„œ https://code.claude.com/docs/en/remote-control ๊ธฐ์ค€, ๊ทธ๋Œ€๋กœ ์‹คํ–‰ ๊ฐ€๋Šฅํ•œ ์ ˆ์ฐจ):

์ด ํ™˜๊ฒฝ๋ณ€์ˆ˜๋Š” ์„ธ์…˜์ด Anthropic์˜ "Remote Control" ๊ธฐ๋Šฅ์— ์—ฐ๊ฒฐ๋ผ ์žˆ์„ ๋•Œ๋งŒ ์กด์žฌํ•ฉ๋‹ˆ๋‹ค. ์•„๋ž˜ ์กฐ๊ฑด์„ ํ•˜๋‚˜๋ผ๋„ ๋งŒ์กฑํ•˜์ง€ ๋ชปํ•˜๋ฉด ์›์ฒœ์ ์œผ๋กœ ์–ป์„ ์ˆ˜ ์—†์œผ๋ฉฐ, ์ด๋Š” ๊ฒฐํ•จ์ด ์•„๋‹ˆ๋ผ ์ •์ƒ ์ƒํƒœ์ž…๋‹ˆ๋‹ค โ€” ์ด ๊ฒฝ์šฐ ๋‹ค๋ฅธ ์‹œ๋„๋ฅผ ํ•˜์ง€ ๋ง๊ณ  ๊ณง๋ฐ”๋กœ capabilities๋ฅผ ์ƒ๋žตํ•˜๊ณ  ๋“ฑ๋ก์„ ๊ณ„์†ํ•˜์‹ญ์‹œ์˜ค.

  • ํ—ค๋“œ๋ฆฌ์Šค(claude -p) ์„ธ์…˜์—๋Š” ์ด ๊ธฐ๋Šฅ ์ž์ฒด๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. Remote Control์€ ๋Œ€ํ™”ํ˜• ์„ธ์…˜ ์ „์šฉ์ด๋ฏ€๋กœ, gissue ์Šค์ผ€์ค„๋Ÿฌ์ฒ˜๋Ÿผ claude -p๋กœ ๋„๋Š” ๋ฌด์ธ ํ”„๋กœ์„ธ์Šค๋Š” ์ด ๊ฐ’์„ ์ ˆ๋Œ€ ๊ฐ€์งˆ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.
  • API ํ‚ค(ANTHROPIC_API_KEY) ์ธ์ฆ ์„ธ์…˜์€ Remote Control์„ ์ง€์›ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. claude.ai ๊ณ„์ • ๋กœ๊ทธ์ธ(claude ์‹คํ–‰ ํ›„ /login)์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.
  • Amazon Bedrock / Google Vertex / Microsoft Foundry ๊ฒฝ์œ ์ด๊ฑฐ๋‚˜, ANTHROPIC_BASE_URL์ด api.anthropic.com ์™ธ์˜ ๊ฐ’(LLM ๊ฒŒ์ดํŠธ์›จ์ดยทํ”„๋ก์‹œ ๋“ฑ)์œผ๋กœ ์„ค์ •๋ผ ์žˆ์œผ๋ฉด ์ง€์›๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
  • DISABLE_TELEMETRY, DO_NOT_TRACK, CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC, DISABLE_GROWTHBOOK ์ค‘ ํ•˜๋‚˜๋ผ๋„ ์„ค์ •๋ผ ์žˆ์œผ๋ฉด ์ง€์›๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค(์„ค์ •๋ผ ์žˆ๋‹ค๋ฉด ๊ทธ ๋ณ€์ˆ˜๋ฅผ ํ•ด์ œํ•ด์•ผ ํ•จ).

์œ„ ์กฐ๊ฑด์„ ์ „๋ถ€ ๋งŒ์กฑํ•˜๋Š” ์ผ๋ฐ˜ ๋Œ€ํ™”ํ˜• ์„ธ์…˜์ธ๋ฐ๋„ ์ด ๋ณ€์ˆ˜๊ฐ€ ์—†๋‹ค๋ฉด, ์•„์ง Remote Control์ด ์—ฐ๊ฒฐ๋งŒ ์•ˆ ๋œ ๊ฒƒ๋ฟ์ž…๋‹ˆ๋‹ค. ์„ธ์…˜์„ ์žฌ์‹œ์ž‘ํ•  ํ•„์š” ์—†์ด, ๊ทธ ์„ธ์…˜ ์•ˆ์—์„œ ๋‹ค์Œ ๋ช…๋ น์„ ์‹คํ–‰ํ•˜๋ฉด ์ฆ‰์‹œ ์—ฐ๊ฒฐ๋˜๊ณ  ๊ทธ ์ˆœ๊ฐ„๋ถ€ํ„ฐ $env:CLAUDE_CODE_BRIDGE_SESSION_ID๊ฐ€ ์„ค์ •๋ฉ๋‹ˆ๋‹ค:

/remote-control

(/rc๋„ ๋™์ผ) ๋‹ค์Œ ์„ธ์…˜๋ถ€ํ„ฐ ๋งค๋ฒˆ ์ž๋™์œผ๋กœ ์—ฐ๊ฒฐ๋˜๊ฒŒ ํ•˜๋ ค๋ฉด ์„ธ์…˜ ์•ˆ์—์„œ /config๋ฅผ ์‹คํ–‰ํ•ด "Enable Remote Control for all sessions"๋ฅผ ์ผœ๊ฑฐ๋‚˜, ์‚ฌ์šฉ์ž ํ™ˆ์˜ ~/.claude/settings.json์— ๋‹ค์Œ์„ ์ถ”๊ฐ€ํ•˜์‹ญ์‹œ์˜ค:

{
  "remoteControlAtStartup": true
}

์—ฌ๊ธฐ์„œ๋„ ์ ˆ๋Œ€ ๊ธˆ์ง€ (guide 147ํ–‰ ์›์น™๊ณผ ๋™์ผ): ์œ„ ์กฐ๊ฑด์„ ๋งŒ์กฑํ•˜์ง€ ๋ชปํ•ด(ํ—ค๋“œ๋ฆฌ์Šค ์‹คํ–‰, API ํ‚ค ์ธ์ฆ ๋“ฑ) CLAUDE_CODE_BRIDGE_SESSION_ID๋ฅผ ์–ป์„ ์ˆ˜ ์—†๋Š” ๊ฒฝ์šฐ, ํ›… stdin์˜ session_id๋‚˜ $env:CLAUDE_CODE_SESSION_ID ๊ฐ™์€ ๋‹ค๋ฅธ ๊ฐ’์œผ๋กœ ๋Œ€์ฒดํ•ด sessionUrl์„ "๋งŒ๋“ค์–ด๋‚ด๋ ค" ํ•˜์ง€ ๋งˆ์‹ญ์‹œ์˜ค โ€” ์ด ๊ฐ’๋“ค์€ claude.ai/code์˜ ์‹ค์ œ ์„ธ์…˜๊ณผ ๋ฌด๊ด€ํ•ด ์—ด๋ฆฌ์ง€ ์•Š๋Š”(404) ๋งํฌ๊ฐ€ ๋ฉ๋‹ˆ๋‹ค. ์ด ๊ฒฝ์šฐ ์œ ์ผํ•œ ์ •๋‹ต์€ capabilities๋ฅผ ์ƒ๋žตํ•˜๊ณ  ๋“ฑ๋ก์„ ๊ณ„์† ์ง„ํ–‰ํ•˜๋Š” ๊ฒƒ์ด๋ฉฐ, ๋ณ„๋„ ์กฐ์น˜๋ฅผ ์‹œ๋„ํ•  ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.

์ด ํŒ๋‹จ์€ ์ˆœ์ „ํžˆ ๊ธฐ๊ณ„์ ์ž…๋‹ˆ๋‹ค โ€” ์‚ฌ๋žŒ์—๊ฒŒ ๋ฌป์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ž์‹ ์˜ ํ”„๋กœ์„ธ์Šค์—์„œ $env:CLAUDE_CODE_BRIDGE_SESSION_ID ์กด์žฌ ์—ฌ๋ถ€๋งŒ ํ™•์ธํ•ด ๋ถ„๊ธฐํ•˜๋ฉฐ, ์–ด๋–ค ๊ฐ’์„ ์“ธ์ง€ ์‚ฌ์šฉ์ž์—๊ฒŒ ์„ ํƒ์ง€๋กœ ์ œ์‹œํ•˜๊ฑฐ๋‚˜ ์งˆ๋ฌธํ•˜๋Š” ๊ฒƒ์€ ์ ˆ๋Œ€ ๊ธˆ์ง€์ž…๋‹ˆ๋‹ค. ํ›… stdin์˜ session_id(agentKey์˜ ์ถœ์ฒ˜)๋ฅผ sessionUrl๋กœ ์žฌ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ๋„ ์ ˆ๋Œ€ ๊ธˆ์ง€์ž…๋‹ˆ๋‹ค โ€” ์„œ๋กœ ๋‹ค๋ฅธ ID์ด๋ฉฐ ๊นจ์ง„/404 ๋งํฌ๊ฐ€ ๋ฉ๋‹ˆ๋‹ค. ๋‚ด๋ถ€ ๋„๊ตฌ ๋งํฌ, ์ž„์˜ URL ๋“ฑ ๋‹ค๋ฅธ ๊ฐ’์œผ๋กœ sessionUrl์„ ๋Œ€์‹  ์ฑ„์šฐ๋Š” ๊ฒƒ๋„ ๊ธˆ์ง€์ž…๋‹ˆ๋‹ค โ€” sessionUrl์€ ์˜ค์ง claude.ai/code ๋ธŒ๋ฆฟ์ง€ ๋งํฌ์ด๊ฑฐ๋‚˜, ์•„์˜ˆ ์—†๋Š”(์ƒ๋žต๋œ) ๊ฐ’์ด์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

sessionUrl์„ ๋ฐ˜๋“œ์‹œ ์ฑ„์šฐ๊ณ  ์‹ถ๋‹ค๋ฉด: ์ด ๋“ฑ๋ก์„ ์ˆ˜ํ–‰ํ•˜๋Š” ์„ธ์…˜ "์ž๊ธฐ ์ž์‹ "์ด Remote Control ๋ธŒ๋ฆฟ์ง€์— ์—ฐ๊ฒฐ๋ผ ์žˆ์–ด์•ผ $env:CLAUDE_CODE_BRIDGE_SESSION_ID๊ฐ€ ์ฑ„์›Œ์ง‘๋‹ˆ๋‹ค. ์ด๋Š” ๊ฐ ์„ธ์…˜์ด ์Šค์Šค๋กœ ๊ฐ–์ถ”๋Š” ์ƒํƒœ์ด์ง€, ๋‹ค๋ฅธ ์šด์˜์ž์˜ PC ์„ค์ •(์˜ˆ: ์„ธ์…˜ ์‹œ์ž‘ ์‹œ ์ž๋™์œผ๋กœ ๋ธŒ๋ฆฟ์ง€์— ์—ฐ๊ฒฐํ•˜๋Š” ์„ค์ •)์— ์˜์กดํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค โ€” ๋‹ค๋ฅธ ์‚ฌ๋žŒ์˜ PC ์„ค์ •์€ ์ด ์„ธ์…˜์— ์•„๋ฌด ์˜ํ–ฅ๋„ ์ฃผ์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์•„์ง ์—ฐ๊ฒฐ ์ „์ด๋ผ๋ฉด /remote-control ๋ช…๋ น์„ ์‹คํ–‰ํ•˜๊ฑฐ๋‚˜(๋Œ€ํ™”ํ˜• ์„ธ์…˜ ๋‚ด์—์„œ) claude --remote-control/--rc ํ”Œ๋ž˜๊ทธ๋กœ ๋‹ค์‹œ ์‹œ์ž‘ํ•ด ์Šค์Šค๋กœ ์—ฐ๊ฒฐํ•˜์‹ญ์‹œ์˜ค. ์—ฐ๊ฒฐ์„ ๊ธฐ๋‹ค๋ฆฌ๋Š” ๋™์•ˆ์—๋„ ๋“ฑ๋ก ์ž์ฒด(Upsert/RunStart)๋Š” ๊ณ„์† ์ง„ํ–‰ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค โ€” ์•„๋ž˜ "sessionUrl์„ ๋งŒ๋“ค ์ˆ˜ ์—†์„ ๋•Œ(capabilities ์ƒ๋žต)" ์ ˆ์˜ ๋ฐฉ์‹๋Œ€๋กœ ํ•˜๊ณ , ๋“ฑ๋ก์„ ํ†ต์งธ๋กœ ๋ฏธ๋ฃจ์ง€ ๋งˆ์‹ญ์‹œ์˜ค.

ํ˜ธ์ถœ ๊ทœ์•ฝ(giipApiSk4 ๊ณตํ†ต): HTTP POST, application/x-www-form-urlencoded ํผ ํ•„๋“œ 3๊ฐœ.

โš ๏ธ ์œ„์น˜ ๊ธฐ๋ฐ˜ ํŒŒ๋ผ๋ฏธํ„ฐ: ์ด SP๋“ค(pApiSchedulerAgentUpsertBySK ๋“ฑ)์€ jsondata์˜ ํ•„๋“œ๋ฅผ SP์˜ ๊ฐœ๋ณ„ ์œ„์น˜ ํŒŒ๋ผ๋ฏธํ„ฐ(@p0, @p1, ...)์— ์ˆœ์„œ๋Œ€๋กœ ๋ฐ”์ธ๋”ฉํ•ฉ๋‹ˆ๋‹ค โ€” ์ค‘๊ฐ„ ํ•„๋“œ๋ฅผ ๊ฑด๋„ˆ๋›ธ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ๋’ค์ชฝ ํ•„๋“œ(์˜ˆ: capabilities)๊นŒ์ง€ ๊ฐ’์„ ์ฑ„์šฐ๋ ค๋ฉด ๊ทธ ์•ž์˜ ๋ชจ๋“  ํ•„๋“œ๋ฅผ ํ•จ๊ป˜ ๋ณด๋‚ด์•ผ ํ•˜๋ฉฐ, ์‹ค์ œ๋กœ ์•ˆ ์“ฐ๋Š” ํ•„๋“œ๋Š” ์•ˆ์ „ํ•œ ์ž๋ฆฌ๊ฐ’(์˜ˆ: windowsTaskName='', projectName='', scheduleDesc='', lssn='0', version='')์œผ๋กœ ์ฑ„์›๋‹ˆ๋‹ค. ์ •์ˆ˜ํ˜• ํŒŒ๋ผ๋ฏธํ„ฐ(lssn ๋“ฑ)์— ๋นˆ ๋ฌธ์ž์—ด์„ ๋ณด๋‚ด๋ฉด ๋ณ€ํ™˜ ์˜ค๋ฅ˜๊ฐ€ ๋‚˜๋ฏ€๋กœ ๋ฐ˜๋“œ์‹œ ์ˆซ์ž ๋ฌธ์ž์—ด์„ ์จ์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋‹ค๋งŒ capabilities๋Š” ์ด ํ•„๋“œ ๋ชฉ๋ก์˜ ๋งจ ๋์— ์žˆ์œผ๋ฏ€๋กœ, ๊ฐ’์ด ์—†์œผ๋ฉด(์œ„์—์„œ ์„ค๋ช…ํ•œ $env:CLAUDE_CODE_BRIDGE_SESSION_ID ๋ถ€์žฌ ์ƒํ™ฉ) ํ•„๋“œ ์ž์ฒด๋ฅผ ํ†ต์งธ๋กœ ์ƒ๋žตํ•ด๋„ ์•ˆ์ „ํ•ฉ๋‹ˆ๋‹ค โ€” ๋’ค์— ์ด์–ด์ง€๋Š” ๋‹ค๋ฅธ ํ•„๋“œ๊ฐ€ ์—†์–ด ์œ„์น˜๊ฐ€ ๋ฐ€๋ฆฌ์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ์œ„์น˜ ๊ธฐ๋ฐ˜ ์ œ์•ฝ์€ ์–ด๋””๊นŒ์ง€๋‚˜ ์ค‘๊ฐ„ ํ•„๋“œ๋ฅผ ๊ฑด๋„ˆ๋›ธ ์ˆ˜ ์—†๋‹ค๋Š” ๋œป์ด๋ฉฐ, ๋ ํ•„๋“œ๊นŒ์ง€ ๋ฌด์กฐ๊ฑด ์ฑ„์›Œ์•ผ ํ•œ๋‹ค๋Š” ๋œป์€ ์•„๋‹™๋‹ˆ๋‹ค.

ํผ ํ•„๋“œ๊ฐ’
text"<SP์ด๋ฆ„> <ํ•„๋“œ1> <ํ•„๋“œ2> ..." (SP ์ด๋ฆ„์€ BySK ์ ‘๋ฏธ์‚ฌ๋ฅผ ๋บ€ ์ด๋ฆ„, ๋’ค์— ์ด ํ˜ธ์ถœ์—์„œ ์ฑ„์šธ ํ•„๋“œ๋ช…์„ ๊ณต๋ฐฑ์œผ๋กœ ๋‚˜์—ด)
token<YOUR_SECRET_KEY> (๋Œ€์ƒ CSN์˜ SK)
jsondataํ•„๋“œ๋ช…โ†’๊ฐ’ ๋งคํ•‘ JSON ๋ฌธ์ž์—ด, ์˜ˆ: {"agentKey":"...","displayName":"..."}

๊ฐ ๋‹จ๊ณ„์—์„œ ์‹ค์ œ๋กœ ์ฑ„์šฐ๋Š” ํ•„๋“œ:

๋‹จ๊ณ„SP ์ด๋ฆ„(text์˜ ์ฒซ ํ† ํฐ)์ฃผ์š” ํ•„๋“œ
์‹œ์ž‘ โ€” identity ๋“ฑ๋ก/๊ฐฑ์‹ SchedulerAgentUpsertagentKey(ํ˜ธ์ŠคํŠธ+์„ธ์…˜๋ณ„ ๊ณ ์œ  ์‹๋ณ„์ž), displayName, hostIdentifier(ํ˜ธ์ŠคํŠธ๋ช…), windowsTaskName, projectName, scheduleDesc, isActive=1, lssn, osType, agentType(์˜ˆ: claude_interactive_session), version, capabilities(JSON ๋ฌธ์ž์—ด, ์˜ˆ: {"sessionUrl":"<์„ธ์…˜์„ ์—ด ์ˆ˜ ์žˆ๋Š” URL>"})
์‹œ์ž‘ โ€” ์‹คํ–‰(run) ์‹œ์ž‘SchedulerAgentRunStartrunIdKey(์ด ์‹คํ–‰์˜ ๊ณ ์œ  ํ‚ค), agentKey, executionMode=interactive, totalIssueCount
์ข…๋ฃŒ โ€” ์‹คํ–‰(run) ์ข…๋ฃŒSchedulerAgentRunEndrunIdKey, agentKey, status=ENDED, processedCount, skippedCount, failedCount
์ข…๋ฃŒ โ€” identity ์˜คํ”„๋ผ์ธ ์ „ํ™˜SchedulerAgentUpsertagentKey, displayName, hostIdentifier, windowsTaskName, projectName, scheduleDesc, isActive=0

์˜ˆ์‹œ(PowerShell, ๊ฐ’์€ ๋ชจ๋‘ ํ”Œ๋ ˆ์ด์Šคํ™€๋”):

$body = @{
  text     = 'SchedulerAgentUpsert agentKey displayName hostIdentifier windowsTaskName projectName scheduleDesc isActive lssn osType agentType version capabilities'
  token    = '<YOUR_SECRET_KEY>'
  jsondata = (@{
    agentKey        = 'claude_interactive_<YOUR_HOST>_<UNIQUE_ID>'
    displayName     = 'Claude Interactive Session (<YOUR_HOST>)'
    hostIdentifier  = '<YOUR_HOST>'
    windowsTaskName = ''
    projectName     = ''
    scheduleDesc    = ''
    isActive        = '1'
    lssn            = '0'
    osType          = 'Windows'
    agentType       = 'claude_interactive_session'
    version         = ''
    capabilities    = (@{ sessionUrl = '<์„ธ์…˜ URL, ์„ ํƒ์‚ฌํ•ญ>' } | ConvertTo-Json -Compress)
  } | ConvertTo-Json -Compress)
}
Invoke-WebRequest -Uri 'https://giipfaw.azurewebsites.net/api/giipApiSk4' -Method Post -Body $body

sessionUrl์„ ๋งŒ๋“ค ์ˆ˜ ์—†์„ ๋•Œ(capabilities ์ƒ๋žต): $env:CLAUDE_CODE_BRIDGE_SESSION_ID๊ฐ€ ์—†์–ด capabilities๋ฅผ ๊ตฌ์„ฑํ•  ์ˆ˜ ์—†๋Š” ๊ฒฝ์šฐ, ์œ„ ์˜ˆ์‹œ์—์„œ text์˜ capabilities ํ† ํฐ๊ณผ jsondata์˜ capabilities ํ•„๋“œ๋งŒ ๋นผ๊ณ  ๋‚˜๋จธ์ง€ 11๊ฐœ ํ•„๋“œ๋Š” ๊ทธ๋Œ€๋กœ ์‚ฌ์šฉํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค. sessionUrl ์—†์ด๋„ ๋“ฑ๋ก ์ž์ฒด๋Š” ์™„์ „ํžˆ ์ •์ƒ์ ์œผ๋กœ ์„ฑ๊ณตํ•ฉ๋‹ˆ๋‹ค โ€” ๋‹ค๋งŒ "Open Interactive Sessions" ์นด๋“œ์— "Open session" ๋งํฌ๋งŒ ๋‚˜ํƒ€๋‚˜์ง€ ์•Š์„ ๋ฟ์ž…๋‹ˆ๋‹ค(์•„๋ž˜ "๋ฌธ์ œ ํ•ด๊ฒฐ" ์ ˆ ์ฐธ๊ณ ).

$body = @{
  text     = 'SchedulerAgentUpsert agentKey displayName hostIdentifier windowsTaskName projectName scheduleDesc isActive lssn osType agentType version'
  token    = '<YOUR_SECRET_KEY>'
  jsondata = (@{
    agentKey        = 'claude_interactive_<YOUR_HOST>_<UNIQUE_ID>'
    displayName     = 'Claude Interactive Session (<YOUR_HOST>)'
    hostIdentifier  = '<YOUR_HOST>'
    windowsTaskName = ''
    projectName     = ''
    scheduleDesc    = ''
    isActive        = '1'
    lssn            = '0'
    osType          = 'Windows'
    agentType       = 'claude_interactive_session'
    version         = ''
  } | ConvertTo-Json -Compress)
}
Invoke-WebRequest -Uri 'https://giipfaw.azurewebsites.net/api/giipApiSk4' -Method Post -Body $body

๋‹ค๋ฅธ ํ˜ธ์ŠคํŠธ์—์„œ ์ด ๋ฉ”์ปค๋‹ˆ์ฆ˜์„ ์žฌํ˜„ํ•˜๋ ค๋ฉด ๋‹ค์Œ ๋‘ ๊ฐ€์ง€๊ฐ€ ๊ทธ๋Œ€๋กœ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค(๋‘˜ ๋‹ค ๊ณ ์ • ์š”๊ตฌ์‚ฌํ•ญ์ด๋ฉฐ ์žฌ๋Ÿ‰์˜ ์—ฌ์ง€๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค): (a) ํ•ด๋‹น ํ˜ธ์ŠคํŠธ์˜ ์„ธ์…˜ ์‹คํ–‰ ๋„๊ตฌ์—๋„ ์œ„์™€ ๋™์ผํ•œ hooks.SessionStart/hooks.SessionEnd ๊ตฌ์„ฑ, (b) ๋“ฑ๋กํ•˜๋ ค๋Š” CSN์— ๋Œ€ํ•ด ์œ ํšจํ•œ SK.

SK๋ฅผ ์–ด๋””์— ๋ณด๊ด€ํ• ์ง€๋Š”(์ด ์ ˆ์ฐจ์™€ ๋ฌด๊ด€ํ•œ) ์ˆœ์ˆ˜ ๋ณด์•ˆ ์žฌ๋Ÿ‰ ์‚ฌํ•ญ์ž…๋‹ˆ๋‹ค โ€” ์ฐธ๊ณ ๋กœ ์ด ์šด์˜์ž์˜ ๊ฐœ์ธ ํ™˜๊ฒฝ(lowyworkenv ์ €์žฅ์†Œ)์—์„œ๋Š” ์ด SK๋ฅผ slack-bot/.secrets/giip-accounts.json์ด๋ผ๋Š” JSON ํŒŒ์ผ(Slack ์ฑ„๋„ID โ†’ {login_id, sk, csn} ๋งคํ•‘ ๊ตฌ์กฐ)๋กœ ๋ณด๊ด€ํ•˜์ง€๋งŒ, ์ด๋Š” ์ฐธ๊ณ ์šฉ ์˜ˆ์‹œ ๊ตฌ์กฐ์ผ ๋ฟ์ž…๋‹ˆ๋‹ค โ€” ์ด ํŠน์ • ํŒŒ์ผ ๊ฒฝ๋กœ๋ฅผ ๊ทธ๋Œ€๋กœ ๋”ฐ๋ผ ํ•˜๋ผ๋Š” ๋œป์ด ์•„๋‹ˆ๋ฉฐ, ๋‹ค๋ฅธ ํ˜ธ์ŠคํŠธ/์šด์˜์ž๋Š” ๊ฐ์ž ์•ˆ์ „ํ•œ ๋ฐฉ์‹(OS ์ž๊ฒฉ ์ฆ๋ช… ์ €์žฅ์†Œ, ์‹œํฌ๋ฆฟ ๋งค๋‹ˆ์ €, ํ™˜๊ฒฝ๋ณ€์ˆ˜ ๋“ฑ)์œผ๋กœ SK๋ฅผ ๋ณด๊ด€ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.

์„ฑ๊ณต ํ™•์ธ: ํ™”๋ฉด ์ƒˆ๋กœ๊ณ ์นจ ์‹œ "Open Interactive Sessions" ์นด๋“œ์— ์„ธ์…˜์ด ๋‚˜ํƒ€๋‚ฉ๋‹ˆ๋‹ค.

๋ฐฉ๋ฒ• B โ€” ์Šค์ผ€์ค„๋Ÿฌ ์—์ด์ „ํŠธ(์ž๋™ํ™” ์‹คํ–‰๊ธฐ) ๋“ฑ๋ก

gissue ์Šค์ผ€์ค„๋Ÿฌ ๊ฐ™์€ ๋ฐฑ๊ทธ๋ผ์šด๋“œ ์ž๋™ํ™” ์‹คํ–‰๊ธฐ๋ฅผ ๋“ฑ๋กํ•˜๋Š” ์ ˆ์ฐจ๋Š” ๋ฐฉ๋ฒ• A์™€ ๊ฐ™์€ SP ๊ณ„์—ด์„ ์“ฐ๋˜, 1ํšŒ์„ฑ์ด ์•„๋‹ˆ๋ผ ์ฃผ๊ธฐ์ ์œผ๋กœ(heartbeat) ์ž์‹ ์˜ identity์™€ ์‹คํ–‰ ์ƒํƒœ๋ฅผ ๊ฐฑ์‹ ํ•ฉ๋‹ˆ๋‹ค.

ํ‘œ์ค€ ๊ตฌํ˜„์€ giip-fde-agent ์ž…๋‹ˆ๋‹ค. ์ฒ˜์Œ๋ถ€ํ„ฐ ์งœ์ง€ ๋ง๊ณ  ์œ„ 'AI ์—๊ฒŒ ๋งก๊ฒจ gissue ์Šค์ผ€์ค„๋Ÿฌ ๋งŒ๋“ค๊ธฐ' ์ ˆ์ฐจ๋ฅผ ๋”ฐ๋ฅด์‹ญ์‹œ์˜ค. ์•„๋ž˜ SP ๊ทœ๊ฒฉ์€ ๋Ÿฌ๋„ˆ๊ฐ€ ๋‚ด๋ถ€์ ์œผ๋กœ ์“ฐ๋Š” ํ˜ธ์ถœ์ด๋ฉฐ, ์ง์ ‘ ๊ตฌํ˜„ํ•ด์•ผ ํ•  ๋•Œ๋งŒ ์ฐธ๊ณ ํ•˜์‹ญ์‹œ์˜ค.

  1. ์‚ฌ์ „์กฐ๊ฑด: ์œ„ ๊ณตํ†ต ์‚ฌ์ „์กฐ๊ฑด(๋Œ€์ƒ CSN์šฉ SK).
  2. ์ตœ์ดˆ ๋“ฑ๋ก/์ฃผ๊ธฐ์  identity ๊ฐฑ์‹ : SchedulerAgentUpsert(๋ฐฉ๋ฒ• A์™€ ๋™์ผ ํ•„๋“œ โ€” agentKey/displayName/hostIdentifier/osType/agentType/version/capabilities ๋“ฑ)๋ฅผ ํ”„๋กœ์„ธ์Šค ์‹œ์ž‘ ์‹œ 1ํšŒ ํ˜ธ์ถœํ•˜๊ณ , ๊ทธ ๋’ค๋กœ๋Š” ์ตœ๋Œ€ 5๋ถ„ ๊ฐ„๊ฒฉ(๊ถŒ์žฅ: 2๋ถ„ ๊ฐ„๊ฒฉ)์œผ๋กœ ๋ฐ˜๋ณต ํ˜ธ์ถœํ•ฉ๋‹ˆ๋‹ค.
  3. ์‹คํ–‰(run) ์‹œ์ž‘: SchedulerAgentRunStart(runIdKey, agentKey, executionMode=scheduled, totalIssueCount).
  4. ์‹คํ–‰ ๋„์ค‘ ์ง„ํ–‰ ์ƒํ™ฉ ๊ฐฑ์‹ (heartbeat): SchedulerAgentHeartbeatPut โ€” runIdKey, agentKey, processedCount, skippedCount, failedCount, currentPhase, currentIssueNum, totalIssueCount. ์ฒ˜๋ฆฌ ๋‹จ์œ„(์˜ˆ: ์ด์Šˆ 1๊ฑด ์ฒ˜๋ฆฌ ์™„๋ฃŒ)๋งˆ๋‹ค ํ˜ธ์ถœํ•˜๊ณ , ์ฒ˜๋ฆฌํ•  ํ•ญ๋ชฉ์ด ์—†์–ด ์œ ํœด ์ƒํƒœ์ด๋”๋ผ๋„ ์ตœ๋Œ€ 2๋ถ„ ๊ฐ„๊ฒฉ์œผ๋กœ ํ˜ธ์ถœํ•˜์‹ญ์‹œ์˜ค โ€” 5๋ถ„ ์ด์ƒ heartbeat๊ฐ€ ๋Š๊ธฐ๋ฉด ํ™”๋ฉด์— STALE๋กœ ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.
  5. ์‹คํ–‰ ์ข…๋ฃŒ: SchedulerAgentRunEnd(runIdKey, agentKey, status, processedCount, skippedCount, failedCount, exitCode, summary). status ๊ฐ’์€ SUCCEEDED / TIMED_OUT / FAILED, exitCode๋Š” ์ˆซ์ž ๋ฌธ์ž์—ด('0' ๋˜๋Š” '1').
SP ์ด๋ฆ„์ธ์ฆ์šฉ๋„
SchedulerAgentUpsertSKidentity ๋“ฑ๋ก/๊ฐฑ์‹ 
SchedulerAgentRunStartSK์‹คํ–‰ ์‹œ์ž‘ ๊ธฐ๋ก
SchedulerAgentHeartbeatPutSK์‹คํ–‰ ์ค‘ ์ง„ํ–‰๋ฅ /heartbeat ๊ฐฑ์‹ 
SchedulerAgentRunEndSK์‹คํ–‰ ์ข…๋ฃŒ ๊ธฐ๋ก
SchedulerAgentListAK(๋กœ๊ทธ์ธ ์„ธ์…˜)์ด ํ™”๋ฉด์ด ๋ชฉ๋ก์„ ์กฐํšŒํ•  ๋•Œ ์‚ฌ์šฉ โ€” ๋“ฑ๋ก์—๋Š” ํ•„์š” ์—†์Œ

์œ„์น˜ ์ธ์ž ์ˆœ์„œ(๋ฐฉ์‹ 1 ๊ธฐ์ค€):

  • Upsert ์ธ์ž ์ˆœ์„œ: agentKey, displayName, hostIdentifier, windowsTaskName, projectName, scheduleDesc, isActive
  • RunStart ์ธ์ž ์ˆœ์„œ: runIdKey, agentKey, executionMode, totalIssueCount
  • HeartbeatPut ์ธ์ž ์ˆœ์„œ: runIdKey, agentKey, processedCount, skippedCount, failedCount, currentPhase, currentIssueNum

ํ˜ธ์ถœ ๊ทœ์•ฝ์€ ๋‘ ๊ฐ€์ง€ ๋ฐฉ์‹์ด ๋ชจ๋‘ ์œ ํšจํ•ฉ๋‹ˆ๋‹ค. ๋ฐฉ์‹ 1(๋Ÿฌ๋„ˆ ๋‚ด๋ถ€): giipApiSk2์— token=SK, text="SP์ด๋ฆ„ '๊ฐ’1' '๊ฐ’2' ..."(SP ํŒŒ๋ผ๋ฏธํ„ฐ ์„ ์–ธ ์ˆœ์„œ์˜ ์œ„์น˜ ์ธ์ž, ๊ฐ’์€ ์ž‘์€๋”ฐ์˜ดํ‘œ ๋ฆฌํ„ฐ๋Ÿด), jsondata๋Š” ๋นˆ ๊ฐ’. ๋ฐฉ์‹ 2(์ง์ ‘ ๊ตฌํ˜„ ์‹œ, ๋ฐฉ๋ฒ• A ์™€ ๊ฐ™์€ ํ˜•์‹): giipApiSk4์— token=SK, text์— ํ•„๋“œ๋ช…์„ ๊ณต๋ฐฑ ๋‚˜์—ด, jsondata์— {"ํ•„๋“œ๋ช…":"๊ฐ’",...} JSON.

์ฐธ๊ณ : ์ด ์ €์žฅ์†Œ๊ฐ€ ๊ด€๋ฆฌํ•˜๋Š” giipAgentWin/giipAgentLinux(์„œ๋ฒ„ ์ธํ”„๋ผ ์—์ด์ „ํŠธ)๋Š” ์ด tSchedulerAgent ์ฒด๊ณ„์™€๋Š” ๋ณ„๊ฐœ์˜ ๋“ฑ๋ก ๋ฉ”์ปค๋‹ˆ์ฆ˜(x-api-key ๊ธฐ๋ฐ˜ agent-register/agent-heartbeat API)์„ ์‚ฌ์šฉํ•˜๋ฉฐ, ์ด ํ™”๋ฉด๊ณผ๋Š” ๋ฌด๊ด€ํ•ฉ๋‹ˆ๋‹ค. ์ด ํ™”๋ฉด(admin/catquest/schedulers)์— ๋“ฑ๋กํ•˜๋ ค๋ฉด ์œ„ SP ๊ณ„์—ด์„ ํ˜ธ์ถœํ•˜๋Š” ๊ตฌํ˜„์ด ํ•„์š”ํ•˜๋ฉฐ, gissue ๋งค์‹œ๊ฐ„ ์Šค์ผ€์ค„๋Ÿฌ์˜ ํ‘œ์ค€ ๊ตฌํ˜„์€ giip-fde-agent ์˜ run-gissue-claude.ps1 ์ž…๋‹ˆ๋‹ค.

์„ฑ๊ณต ํ™•์ธ: ๋‹ค์Œ heartbeat/์ƒˆ๋กœ๊ณ ์นจ ํ›„ ์—์ด์ „ํŠธ ๋ชฉ๋ก ํ‘œ์— ๋‚˜ํƒ€๋‚ฉ๋‹ˆ๋‹ค.

๐Ÿ’ก ์œ ์˜ ์‚ฌํ•ญ

  • ์ด ํ™”๋ฉด์€ ๊ด€๋ฆฌ์ž ์ „์šฉ์ž…๋‹ˆ๋‹ค. AdminGuard(uLevel โ‰ฅ 70) ์ ‘๊ทผ ๊ถŒํ•œ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.
  • ์—์ด์ „ํŠธ ๋ชฉ๋ก, ์‹คํ–‰์ด๋ ฅ, ๋กœ๊ทธ ์นดํƒˆ๋กœ๊ทธ๋Š” ๋ชจ๋‘ ์„ธ์…˜์˜ ํ˜„์žฌ CSN์„ ๊ธฐ์ค€์œผ๋กœ ์กฐํšŒ๋ฉ๋‹ˆ๋‹ค โ€” ๋‹ค๋ฅธ ํ”„๋กœ์ ํŠธ์˜ ์—์ด์ „ํŠธ๋ฅผ ํ™•์ธํ•˜๋ ค๋ฉด ์ƒ๋‹จ ๋‚ด๋น„๊ฒŒ์ด์…˜์—์„œ ํ”„๋กœ์ ํŠธ๋ฅผ ์ „ํ™˜ํ•˜์„ธ์š”.
  • ๋ฐ์ดํ„ฐ ์กฐํšŒ์—๋Š” ์ธ์ฆ๋œ ์„ธ์…˜(AK ํ† ํฐ)์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ์š”์ฒญ์ด ์ธ์ฆ ์˜ค๋ฅ˜๋กœ ์‹คํŒจํ•˜๊ธฐ ์‹œ์ž‘ํ•˜๋ฉด ๋‹ค์‹œ ๋กœ๊ทธ์ธ ํ›„ Refresh๋ฅผ ๋ˆ„๋ฅด์„ธ์š”.
  • ์ด ํŽ˜์ด์ง€๋Š” /admin/catquest์™€๋Š” ๋ณ„๊ฐœ์˜ ๋„๊ตฌ์ž…๋‹ˆ๋‹ค โ€” CatQuest ํ™”๋ฉด์˜ ๋‚ด๋น„๊ฒŒ์ด์…˜์„ ํ†ตํ•ด ์ง„์ž…ํ–ˆ๋‹ค๊ณ  ํ•ด์„œ CatQuest์˜ ๊ณ ์–‘์ด ์‹œ๊ฐํ™” ๋ฐ์ดํ„ฐ๋‚˜ ๋Œ€์ƒ ์‚ฌ์šฉ์ž๋ฅผ ๊ณต์œ ํ•˜๋Š” ๊ฒƒ์€ ์•„๋‹™๋‹ˆ๋‹ค.

๋ฌธ์ œ ํ•ด๊ฒฐ

์ฆ์ƒ์›์ธํ•ด๊ฒฐ
๋Œ€ํ™”ํ˜• ์„ธ์…˜์— ๋“ฑ๋ก์„ ์ง€์‹œํ–ˆ๋Š”๋ฐ "Open Interactive Sessions"์— ์ „ํ˜€ ์•ˆ ๋‚˜ํƒ€๋‚จ์ „์—ญ ํ›…์˜ ํ—ค๋“œ๋ฆฌ์Šค ํŒ์ • ๋กœ์ง์ด $env:CLAUDE_CODE_BRIDGE_SESSION_ID ์œ ๋ฌด๋งŒ์œผ๋กœ ํŒ๋‹จํ•ด, ๋ธŒ๋ฆฟ์ง€ ๋ฏธ์—ฐ๊ฒฐ ๋Œ€ํ™”ํ˜• ์„ธ์…˜๊นŒ์ง€ ํ—ค๋“œ๋ฆฌ์Šค๋กœ ์˜ค์ธํ•ด ๋“ฑ๋ก ์ž์ฒด๋ฅผ ์Šคํ‚ตํ–ˆ์„ ๊ฐ€๋Šฅ์„ฑ์ด ๊ฐ€์žฅ ํผ(giip #1837)์œ„ "์ „์—ญ ํ›…์œผ๋กœ ๋“ฑ๋กํ•œ ๊ฒฝ์šฐ ํ—ค๋“œ๋ฆฌ์Šค ์˜คํŒ์ • ์ฃผ์˜" ๋ฐ•์Šค์˜ ํ”„๋กœ์„ธ์Šค ์ปค๋งจ๋“œ๋ผ์ธ ๊ฒ€์‚ฌ ๋ฐฉ์‹์œผ๋กœ ํŒ์ • ๋กœ์ง์„ ๊ต์ฒดํ•˜์‹ญ์‹œ์˜ค.
"Authentication required" ์˜ค๋ฅ˜AK/์„ธ์…˜ ํ† ํฐ์„ ์ฐพ์„ ์ˆ˜ ์—†์Œ๋‹ค์‹œ ๋กœ๊ทธ์ธํ•œ ๋’ค ํŽ˜์ด์ง€๋ฅผ ์ƒˆ๋กœ๊ณ ์นจํ•˜์„ธ์š”.
์—์ด์ „ํŠธ ๋ชฉ๋ก์ด ๋น„์–ด ์žˆ์Œ์ด CSN์— ๋“ฑ๋ก๋œ ์Šค์ผ€์ค„๋Ÿฌ ์—์ด์ „ํŠธ๊ฐ€ ์—†๊ฑฐ๋‚˜, ํ”„๋กœ์ ํŠธ๊ฐ€ ์ž˜๋ชป ์„ ํƒ๋จ์ƒ๋‹จ ๋‚ด๋น„๊ฒŒ์ด์…˜์—์„œ ์˜ฌ๋ฐ”๋ฅธ ํ”„๋กœ์ ํŠธ(CSN)๊ฐ€ ์„ ํƒ๋ผ ์žˆ๋Š”์ง€ ํ™•์ธํ•˜์„ธ์š”.
์ž‘์—…์ด ์œ ํœด ์ƒํƒœ์ธ ๊ฑธ ์•„๋Š”๋ฐ๋„ ํ–‰์ด ๋นจ๊ฐ„์ƒ‰ STALE๋กœ ํ‘œ์‹œ๋จ์—์ด์ „ํŠธ๊ฐ€ ENDED๋กœ ์ „์ด๋˜์ง€ ์•Š์€ ์ฑ„ ์‹คํ–‰ ๋„์ค‘ heartbeat ์ „์†ก์ด ๋ฉˆ์ถค(isStale = true) โ€” ํ”„๋กœ์„ธ์Šค๊ฐ€ ํฌ๋ž˜์‹œํ–ˆ๊ฑฐ๋‚˜ ๊ฐ•์ œ ์ข…๋ฃŒ๋์„ ๊ฐ€๋Šฅ์„ฑ์—์ด์ „ํŠธ ํ˜ธ์ŠคํŠธ๋ฅผ ์ง์ ‘ ํ™•์ธํ•˜์„ธ์š”. ์žฌ์‹œ์ž‘ ํ›„ ๋‹ค์‹œ ๋ณด๊ณ ๋ฅผ ์‹œ์ž‘ํ•˜๋ฉด ๋ฐฐ์ง€๊ฐ€ ๊ฐฑ์‹ ๋ฉ๋‹ˆ๋‹ค.
Live Log Viewer์— "No streams yet."์ด ํ‘œ์‹œ๋จ์—์ด์ „ํŠธ๊ฐ€ ์•„์ง ๋กœ๊ทธ ์ŠคํŠธ๋ฆผ์„ ๋“ฑ๋กํ•˜์ง€ ์•Š์•˜๊ฑฐ๋‚˜, ์นดํƒˆ๋กœ๊ทธ๊ฐ€ ๋งˆ์ง€๋ง‰์œผ๋กœ ๊ฐฑ์‹ ๋œ ์ดํ›„ ์ถœ๋ ฅ์ด ์—†์Œ์—์ด์ „ํŠธ์˜ ๋‹ค์Œ ์‹คํ–‰์„ ๊ธฐ๋‹ค๋ฆฌ๊ฑฐ๋‚˜, ์—์ด์ „ํŠธ ํ”„๋กœ์„ธ์Šค๊ฐ€ ์‹ค์ œ๋กœ ๋กœ๊ทธ๋ฅผ ์“ฐ๊ณ  ์žˆ๋Š”์ง€ ํ™•์ธํ•˜์„ธ์š”.
Open Interactive Sessions์— "Open session" ๋งํฌ๊ฐ€ ์—†์Œํ•ด๋‹น ์—์ด์ „ํŠธ์˜ ๋“ฑ๋ก๋œ capabilities์— sessionUrl์ด ํฌํ•จ๋ผ ์žˆ์ง€ ์•Š์Œ์—ด ์ˆ˜ ์žˆ๋Š” ํ•ญ๋ชฉ์ด ์—†์Šต๋‹ˆ๋‹ค โ€” ํ•ด๋‹น ๋Œ€ํ™”ํ˜• ์„ธ์…˜์ด ์ ‘๊ทผ ๊ฐ€๋Šฅํ•œ URL์„ ๋“ฑ๋กํ•˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค.

๋ฒ„์ „: 1.1 ์ตœ์ข… ์—…๋ฐ์ดํŠธ: 2026-09-01 ์†Œ์Šค ํŒŒ์ผ: giipv3/public/help/catquest-schedulers.ko.md