# 엔지니어링 컨텍스트를 GitHub에 남기기: AI 코딩 도구 간 인계와 다중 브랜치 협업

> Canonical: https://vxi.me/ko/posts/github-first-ai-coding-context-handoff-workflow/
> Locale: ko-kr
> Published: 2026-10-21
> Updated: 2026-10-21
> Markdown: https://vxi.me/ko/posts/github-first-ai-coding-context-handoff-workflow.md

<figure class="github-first-hero not-prose"><picture><source media="(prefers-reduced-motion: reduce) and (max-width: 640px)" srcset="/images/posts/github-first-ai-coding-context-handoff-workflow/github-first-context-handoff.mobile.still.ko-kr.svg" type="image/svg+xml"><source media="(prefers-reduced-motion: reduce)" srcset="/images/posts/github-first-ai-coding-context-handoff-workflow/github-first-context-handoff.still.ko-kr.svg" type="image/svg+xml"><source media="(max-width: 640px)" srcset="/images/posts/github-first-ai-coding-context-handoff-workflow/github-first-context-handoff.mobile.ko-kr.svg" type="image/svg+xml"><img src="/images/posts/github-first-ai-coding-context-handoff-workflow/github-first-context-handoff.ko-kr.svg" alt="여러 AI 코딩 도구가 GitHub 작업 상태를 읽고 각 브랜치에서 개발한 뒤 PR 리뷰와 사람의 승인을 거쳐 합치는 GitHub-first 다이어그램." width="1120" height="860" loading="eager" fetchpriority="high" decoding="async" style="display:block;width:100%;height:auto"></picture><figcaption>도구 간 상태 복구, 브랜치 분리, 독립 리뷰와 오래된 지시 차단을 설명하는 예시 그림입니다.</figcaption></figure>

AI 코딩 도구를 바꿀 때 가장 힘든 것은 새 도구가 코드를 못 짜서가 아니라, **프로젝트 상황을 처음부터 다시 설명해야 한다는 점**입니다. 왜 지난 세션에서 이 설계를 골랐는지, 어느 브랜치에서 작업하는지, 어떤 테스트가 통과했는지, 아직 리뷰받지 않은 PR이 무엇인지, 이전 Agent의 권한은 어디까지였는지 다시 알려줘야 합니다.

저는 이런 진행 상태를 채팅창에만 두지 않고 GitHub에 남기기 시작했습니다. Codex든 Claude Code든 Cursor든 브라우저의 ChatGPT든, 새 도구는 먼저 저장소의 Issue·브랜치·PR을 읽습니다. 쓰기 권한이 있으면 독립된 브랜치에 커밋하고, 읽기만 가능하면 리뷰 의견을 남깁니다.

이 방식이 제가 말하는 GitHub-first입니다. **AI 도구는 바뀌어도 작업 상태가 대화와 함께 사라져서는 안 됩니다.** 기억을 위해 별도의 상주 Bot을 운영할 필요가 없고, 휴대폰만 가지고 있을 때도 다음 작업을 넘길 수 있습니다.

## 대화 기억과 엔지니어링 컨텍스트는 다르다

며칠씩 이어지는 개발에서는 Agent A가 설계를 바꾼 이유를 B가 모를 수 있습니다. 새 세션은 예전 커밋의 초록색 CI를 보고 현재 HEAD도 통과했다고 착각할 수 있습니다. 두 개발자가 같은 파일을 수정하면서 모두 자신이 담당자라고 믿는 경우도 있습니다. 과거 채팅을 열 페이지씩 복사하면 잠깐 나아지지만 특정 서비스의 대화 기록에 더 의존하게 됩니다.

GitHub가 보관할 수 있는 것은 모델 내부의 기억이 아니라, **다음 도구가 읽고 검증할 수 있는 작업 사실**입니다. 저는 이를 네 층으로 나눕니다.

- **프로젝트 규칙:** `AGENTS.md`, README, 아키텍처 문서. 모든 클라이언트가 `AGENTS.md`를 자동으로 읽는 것은 아닙니다.
- **작업 식별:** Issue, task ID, 계획, 담당자, checkpoint, 완료한 일과 아직 검증하지 않은 일.
- **코드 버전:** `main`, feature branch, commit 및 Git Blob SHA. 실제 작업 중인 브랜치를 알아야 합니다.
- **리뷰와 승인:** PR diff, 리뷰 댓글, ACK, **해당 HEAD에 대한** CI run, 병합 및 배포 기록.

이를 하나의 거대한 JSON에 넣을 필요는 없습니다. Git은 코드 버전을, Issue/PR은 토론을 담당하고 필요할 때 checkpoint로 다음 단계를 정리합니다. 비밀키, 일시적인 모델 캐시, 자주 바뀌는 분산 락은 저장소에 넣지 않습니다.

새 세션에는 긴 대화 대신 짧은 상태 복구 프롬프트를 전달합니다. 다른 코딩 도구에도 그대로 붙여 넣기 좋도록 기술 예시는 영어로 남겨 둡니다.

~~~text
You are the developer for this task. Recover project state read-only first.
Repository: OWNER/REPO
Task: Issue #N, linked PR #M, task ID TASK_ID

Read repository rules, the plan, checkpoint, current feature-branch HEAD,
PR diff, the latest applicable review comments, and checks for that HEAD.
Explain the authorized actions, verified work, and remaining gates.
Stop and report if the branch moved, permissions differ, or orders conflict.
Do not merge, deploy, or change production settings without separate approval.
~~~

**개인 개발자라면 가벼운 방식부터 시작해도 충분합니다.** README나 `AGENTS.md`, 하나의 Issue 또는 PR, 최근 커밋 몇 개만으로도 도구 교체를 연습할 수 있습니다. 여러 세션이나 여러 작성자가 동시에 작업하거나 독립 검증이 필요해졌을 때 checkpoint와 Order/ACK를 추가하면 됩니다.

## 하나의 GitHub 상태 계층으로 여러 AI와 브랜치를 연결하기

전체 관계는 다음처럼 간단히 나타낼 수 있습니다. 글 맨 위의 애니메이션 SVG도 같은 구조를 보여 줍니다.

~~~text
Phone / browser / local IDE / cloud coding agent
                       |
             Read GitHub task facts
                       |
       AGENTS.md · Issue · plan · checkpoint
                  branch · PR
                       |
              Check permission scope
                       |
         Feature branch A     Fix branch B
                  |                |
                commit           commit
                  |                |
                 PR A             PR B
                     \           /
                   review + CI per HEAD
                           |
                  Human approval to merge
                           |
                          main
~~~

모든 AI 연결이 같은 GitHub 권한을 갖는 것은 아닙니다. 검색과 읽기만 되는 연결도 있고, 자체 실행 환경에서 파일을 수정하고 브랜치와 PR을 만드는 코딩 Agent도 있습니다. **이 설명은 2026년 10월을 기준으로 한 권한 모델의 차이이며, 위에서 언급한 모든 제품의 현재 기능을 개별적으로 실측했다는 뜻은 아닙니다.** 실제 사용 시 계정과 연결 설정에서 `read`, `write`, `comment`, `merge`, `deploy` 권한을 확인해야 합니다.

기능 A는 클라우드 Agent, 문서 수정은 브라우저 세션, 인터페이스 변경은 로컬 Codex에 맡길 수 있습니다. 모두 같은 규칙을 읽되 각각 `feature/A`, `docs/B`, `fix/C`처럼 별도 브랜치에 쓰고, 변경 사항은 PR에서 합칩니다.

**브랜치를 나눴다고 논리적 충돌까지 사라지는 것은 아닙니다.** 두 브랜치가 같은 API나 의존성을 바꿀 수 있기 때문입니다. 한 작업 브랜치에는 실제 작성자를 한 명만 두고, 병합 전에 공통 기준점, 변경 파일, 최신 CI 및 통합 테스트를 다시 살펴봅니다. GitHub의 [Pull Request 안내](https://docs.github.com/en/pull-requests/get-started/about-pull-requests)와 [보호된 브랜치](https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/managing-protected-branches/about-protected-branches) 기능도 이런 절차를 뒷받침합니다.

여러 로컬 작업 디렉터리를 분리하려면 Git Worktree를 쓸 수 있습니다. 그 문제는 [Git Worktree 실전 글](/posts/git-worktree-parallel-development/)에서 따로 다뤘습니다. 여기서는 **서로 다른 AI 도구가 같은 GitHub 작업을 어떻게 인계받고 PR로 모으는지**에 집중합니다.

## 도구 간 인계: Issue, 브랜치, PR부터 확인하기

프롬프트는 시작 위치일 뿐입니다. 새 도구가 실제로 **어느 HEAD에 있는지, 직전 담당자가 무엇을 전달했는지, 누가 쓸 수 있는지** 설명할 수 있어야 합니다.

가벼운 프로젝트라면 루트의 짧은 `AGENTS.md`부터 시작하세요. 기존 아키텍처 문서와 테스트 명령으로 안내하는 역할이면 충분합니다.

~~~markdown
# AGENTS.md

- Stack and architecture: see README.md and docs/architecture.md
- Install and test: follow the current commands in README.md
- Task entry points: GitHub Issue and linked PR
- Optional state: tasks/<TASK_ID>/checkpoint.json
- Before editing: verify task ID, branch, and live HEAD
- Prefer one writer for each feature branch
- Merges and deployments need separate approval
~~~

장기 작업에서는 `checkpoint.json`도 선택적으로 남깁니다. 아래 필드 이름은 실제로 사용한 checkpoint에서 가져왔지만, 프로젝트 ID와 SHA는 모두 공개용 플레이스홀더입니다.

~~~json
{
  "task_id": "TASK_ID",
  "phase": "P2",
  "status": "IN_PROGRESS",
  "branch": "feat/TASK_ID",
  "commit_sha": "REPLACE_WITH_LAST_VERIFIED_40_HEX_SHA",
  "pr": "https://github.com/OWNER/REPO/pull/N",
  "verification": { "merge": { "status": "NOT_AUTHORIZED" } },
  "next_action": "Read current HEAD and review comments before resuming"
}
~~~

이것은 개인 저장소 파일의 복사본도, 모든 프로젝트에서 그대로 검증되는 완전한 스키마도 아닙니다. **매 커밋마다 checkpoint를 수정할 필요도 없습니다.** 저는 단계 인계, 검증 완료, 작업 중단 같은 의미 있는 시점에만 갱신합니다. 작은 일은 Issue/PR 댓글로 충분합니다.

특히 `commit_sha`에는 자기 참조 문제가 있습니다. **`checkpoint.commit_sha`는 마지막으로 검증한 코드의 커밋이지, checkpoint 파일을 포함한 커밋이나 실시간 HEAD일 필요가 없습니다.** 코드 커밋 A를 검증한 뒤 커밋 B에서 checkpoint를 저장했다면 파일은 A를 가리킬 수 있습니다. 그러나 B를 생성하기 전에 B 자신의 해시를 파일에 적을 수는 없습니다. 두 SHA가 항상 한 커밋만큼 차이 나는 것도 아닙니다.

따라서 새 세션은 GitHub에서 현재 브랜치 HEAD를 새로 읽고, checkpoint에 기록된 기준점 이후의 변경을 확인해야 합니다. 두 SHA가 다르다고 무조건 실패인 것은 아닙니다. ACK의 `observed_head_sha`와 `new_head_sha`는 각각 리뷰 대상의 이전 버전과 수정 후 버전입니다. 오래된 Order를 거부하는 것은 별도의 버전 검사입니다.

`AGENTS.md`는 규칙, Issue/PR은 토론과 리뷰, checkpoint는 선택적 진행 상태를 담당합니다. 자동 읽기를 지원하지 않는 도구에는 `AGENTS.md`를 명시적으로 읽으라고 지시합니다.

제가 사용하는 **엄격한 인계 프로토콜의 핵심**도 오픈소스로 공개했습니다. 가벼운 방식에는 필요하지 않지만, Order/ACK가 HEAD에 어떻게 묶이는지, 오래된 명령을 어떻게 거부하는지, 오프라인 검증이 어떻게 작동하는지 코드를 직접 볼 수 있습니다.

<a class="gh-repo-pill" href="https://github.com/vxime/conversation-memory-hub" target="_blank" rel="noopener"><svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg><span>vxime/conversation-memory-hub</span></a>

이 공개 저장소는 프로토콜, 검증기, 예제를 제공합니다. 다른 AI 대화를 자동으로 깨우는 호스팅 서비스도 아니고, 업무 저장소의 상태를 복제하는 Bot도 아닙니다. 실제 Issue·브랜치·PR은 각자의 GitHub에 남습니다.

## 실제 PR 복기: FIX_REQUIRED → ACK → 독립 재검토

아키텍처 그림을 그리면 두 AI가 모두 “알겠습니다”라고 답하는 것만으로 인계가 성공한 것처럼 느끼기 쉽습니다. 저는 실제 문서 수정 PR을 다시 읽었습니다. 리뷰어 B는 두 가지 문제를 지적했고, 개발자 A는 수정 후 새 HEAD를 댓글로 남겼습니다. B가 그 새 버전을 확인했고, 실제 병합 결정은 별도로 사람이 내렸습니다.

먼저 `FIX_REQUIRED`, `ACK`, `ADVANCE`는 **프로젝트 자체에서 정의한 댓글 규약이지 GitHub 기본 PR 상태가 아닙니다.** 각각 수정 요청, 개발자의 수락 및 새 버전 기록, 새 HEAD를 검토한 후 진행 허용을 뜻합니다. `STALE_ORDER`는 이전 버전에 묶인 명령이 만료됐음을 알립니다.

해당 PR은 Runner의 읽기 전용 감사 계획 문서만 수정했으며 실제 Runner를 설치하지 않았습니다. F-001에서 발견된 문제는 GitHub Actions의 `issue_comment` 같은 이벤트를 확인하려는 감사 계획이 workflow의 **파일 이름만** 나열하고 있었다는 점입니다.

~~~sh
# Original plan: names only; the YAML triggers remain invisible.
gh api "repos/OWNER/REPO/contents/.github/workflows" --jq '.[].name'
~~~

파일 이름만으로는 YAML의 최상위 `on:`에 `issue_comment`가 있는지 알 수 없습니다. F-002는 감사 문서의 잘못된 장 참조였습니다. 수정된 문서는 감사 대상 SHA를 고정하고 실제 YAML 트리거를 읽으며, 마지막에 HEAD가 이동했는지도 확인하도록 바뀌었습니다. 저는 수정 전후 문서를 비교했습니다. 이벤트 종류는 [GitHub Actions 공식 문서](https://docs.github.com/en/actions/reference/workflows-and-actions/events-that-trigger-workflows)에서 확인할 수 있습니다.

A는 원래 PR에 ACK와 새 HEAD를 기록했습니다. B는 두 수정 사항을 해당 HEAD에서 다시 확인한 뒤 `ADVANCE`를 남겼습니다. **사람이 두 AI 세션을 직접 이어 준 과정**이며, 다른 채팅을 자동으로 깨우거나 `decideResume()`를 GitHub Actions 게이트 또는 로컬 Git hook에 설치한 것이 아닙니다. 간단한 인계라면 정확한 HEAD를 적은 평범한 PR 댓글로도 충분합니다.

실제 ACK 댓글의 중요 필드만 남기고 비공개 ID와 SHA를 플레이스홀더로 바꾸면 다음과 같습니다.

~~~json
{
  "protocol": "ai-supervisor/ack/v1",
  "task_id": "TASK_ID",
  "order_id": "REPLACE_WITH_ORDER_ID",
  "decision_received": "FIX_REQUIRED",
  "observed_head_sha": "REPLACE_WITH_OLD_HEAD",
  "new_head_sha": "REPLACE_WITH_NEW_HEAD",
  "executed": [
    "F-001: Inspect workflow triggers at a pinned SHA",
    "F-002: Correct the audit plan's section reference"
  ]
}
~~~

원래 규약에는 무결성 검증을 위한 필드가 더 있습니다. 핵심은 A가 어떤 이전 HEAD에 대한 지적을 고쳤는지, 어느 새 HEAD를 B에게 전달했는지 명확히 남기는 것입니다. B는 “고쳤다”라는 말이 아닌 실제 변경 버전을 다시 검토할 수 있습니다.

이 PR은 감사 계획 문서만 수정했습니다. 해당 HEAD의 성공한 CI 결과나 운영 VPS 감사 실행 기록은 없었습니다. 확인할 수 있는 것은 **GitHub에 남은 재검토와 인계 기록**이지 완전한 자율 운영이 아닙니다.

## STALE_ORDER: 예전 HEAD에 묶인 지시는 멈춰야 한다

**Order**는 B가 Issue/PR 댓글에 남기는 구조화된 지시입니다. 작업 ID, 대상 브랜치, 당시의 `observed_head_sha`, 발견된 문제와 허용·금지 작업을 함께 기록합니다. ACK의 `order_id`는 해당 지시를 가리킵니다.

별도의 부정 테스트에서는 Order가 이전 `main` HEAD에 묶여 있었고, 이후 저장소가 갱신됐습니다. 새 세션이 옛 Order를 읽으면 그대로 파일을 쓰지 않고 `STALE_ORDER`를 반환해 멈춰야 합니다.

저는 저장된 옛 Order, 나중의 HEAD, `decideResume()`의 버전 만료 검사 소스를 확인했습니다. 당시 A가 멈췄다고 보고했지만, **그 보고는 사람이 옮겨 기록한 것이지 A가 GitHub에 독립적인 ACK를 남긴 것은 아닙니다.** 의미 있는 부정 실험이지만 모든 AI 클라이언트에서 종단 간 자동 검증을 완료했다는 뜻은 아닙니다.

실용적인 규칙은 단순합니다. B가 작업·브랜치·HEAD·권한을 Order에 묶고, A는 작업 전에 최신 HEAD를 다시 읽습니다. 달라졌다면 멈춰서 B에게 새 버전에 대한 리뷰를 요청합니다. 과거에 맞았던 지시라도 현재 코드에는 맞지 않을 수 있습니다.

그래서 저는 독립 리뷰를 유지합니다. Agent가 그럴듯한 diff를 만들었다는 사실과 다른 세션이 **실제 새 HEAD에 대해 수정 여부를 검증했다는 사실**은 다릅니다. 더 넓은 owner·상태 인계 이야기는 [AI Agent Orchestration 글](/posts/ai-agent-orchestration-after-assistants/)을 참고하세요.

## 휴대폰으로 협업할 수 있어도 GitHub가 무료 컴퓨터는 아니다

이 구조 덕분에 진행 상황을 기억하려고 한 대의 Mac을 항상 켜 두거나 상주 조정 Bot을 따로 운영할 필요가 없어졌습니다. 권한이 있는 클라이언트라면 휴대폰에서도 PR과 댓글을 읽고 다음 작업을 전달할 수 있습니다. 실제 코드 변경, 빌드, 테스트는 실행 환경과 권한이 있는 클라우드 Agent, Runner, 로컬 도구가 담당합니다.

비용도 두 가지로 나눠 봐야 합니다. 맥락을 반복해서 설명하거나 전용 서비스를 운영하는 시간과 부담은 줄 수 있지만 모델 추론, Chat/Codex/API 할당량, CI에는 각각 비용이 있습니다. **같은 작업을 비교한 Token 비용 실험은 하지 않았으므로** 절감률을 만들어서 주장하지 않습니다.

제 블로그에는 GitHub Actions → Self-hosted Runner 배포 경로도 있습니다. [기기 간 개발과 통합 배포 글](/posts/chatgpt-web-github-self-hosted-runner/)은 코드가 올라가는 마지막 단계에 관한 이야기입니다. 이 글이 해결하려는 것은 그보다 앞선 문제, 즉 **도구나 사람이 바뀌어도 같은 작업을 제대로 이어받고 있음을 어떻게 확인하는가**입니다.

위험이 작은 단일 파일 수정이라면 AI 한 개와 브랜치 하나면 충분할 수 있습니다. 작업이 며칠에 걸치고 여러 도구와 사람이 이어받게 될수록 checkpoint, 브랜치 소유권, 독립 리뷰, 권한 경계가 중요해집니다. GitHub-first의 매력은 AI가 마법처럼 기억을 공유한다는 데 있지 않습니다. **확인 가능한 엔지니어링 사실이 같은 장소에 남아 다음 담당자가 작업을 다시 시작할 수 있다는 점**입니다.
