GSD 포크를 시도하며 깨달은 점: 이는 진짜 개발자가 아닌 '바이브 코더(vibe coders)'를 위한 것이다
요약
시니어 엔지니어의 관점에서 AI 코딩 에이전트 프레임워크인 GSD를 분석하고, 자율적 오케스트레이터와 인간 참여형 어시스턴트 간의 차이를 다룹니다. GSD의 뛰어난 설계에도 불구하고 실제 개발 워크플로우와의 부적합성을 설명하며, 포크 대신 GitHub Spec Kit으로 전환하는 과정을 공유합니다.
핵심 포인트
- GSD는 자율적 오케스트레이터로서 설계되어 시니어 엔지니어의 제어권을 제한함
- AI 에이전트 프레임워크의 단계별(계획-실행-검증) 루프 모델은 매우 탁월함
- 유지보수 수학 관점에서 오픈소스 프로젝트의 포크는 관리 비용이 매우 높음
- 전문가에게는 자율형 에이전트보다 인간 참여형(Human-in-the-loop) 도구가 적합함
시니어 엔지니어로서 저는 명세 기반(spec-driven) AI 개발을 심도 있게 탐구합니다: 아키텍처, 유지보수 수학(maintenance math), 250개의 포크가 방치된 공동묘지, 거절된 GitHub issue, 그리고 제가 GSD, GitHub Spec Kit, OpenSpec 사이에서 고민한 과정에 대하여.
요약 (TL;DR)
- 저는 진심으로 GSD를 좋아합니다. GSD의 연구, 계획, 그리고 로드맵/단계(phase) 모델은 제가 사용해 본 것 중 최고 수준입니다. 하지만 여전히 제 작업 방식과는 맞지 않습니다.
- 제 문제는 설정이 부족해서가 아니었습니다. 문제는 도구의 **카테고리(category)**였습니다. GSD는 _자율적 오케스트레이터(autonomous orchestrator)_입니다. 저는 _인간 참여형 어시스턴트(human-in-the-loop assistant)_를 원하는 시니어 엔지니어입니다.
- 저는 이를 "라이트(lite)" 버전으로 포크(fork)하는 것을 고려했습니다. 유지보수 수학(maintenance math)에 따르면, 갈라져 나간 포크는 최악의 선택지이며, 250개의 포크를 살펴본 결과 이를 확인했습니다. 저에게 성공적인 시작점이 될 만한 포크는 단 하나도 없었습니다.
- 저는 GitHub Spec Kit으로 전환할 예정이며, OpenSpec이 근소한 차이로 뒤를 잇습니다. 다음은 저의 결정에 반대하는 논거를 포함한 전체적인 이유입니다.
나에게 맞지 않는 도구를 좋아한다는 것
사람들이 잘 글을 쓰지 않는 특정한 종류의 좌절감이 있습니다. 도구가 훌륭하고, 그 안에 담긴 기술력을 알아볼 수 있음에도 불구하고, 모든 프로젝트에서 도구가 당신과 계속 싸우는 경우입니다.
저에게는 GSD가 그렇습니다. GSD("Git. Ship. Done.")는 AI 코딩 에이전트를 위한 명세 기반(spec-driven), 컨텍스트 엔지니어링(context-engineering) 프레임워크입니다. 이 프레임워크는 에이전트를 규율 있는 루프(논의(discuss) → 계획(plan) → 실행(execute) → 검증(verify) → 배포(ship))를 통해 구동하며, 메인 세션이 오염되지 않도록 새로운 컨텍스트를 가진 서브 에이전트(subagents)에서 고도의 연구 및 계획 작업을 수행합니다. 단계/로드맵(phase/roadmap) 모델은 탁월합니다. 연구(research) 단계도 훌륭합니다. 저는 이 절차(ceremony)를 좋아합니다. 저에게 이 절차는 이해의 관문(comprehension gate)이며, 코드를 건드리기 전에 에이전트(그리고 저 자신)가 실제로 작업을 이해하도록 강제하는 장치입니다.
그럼에도 불구하고, 실제 프로젝트에서 실행할 때마다 GSD는 제 작업 방식과 반대로 작동했습니다. 저는 시니어 엔지니어입니다. 제 역할은 대체되는 것이 아니라 도움을 받는 것입니다. GSD는 운전대를 직접 잡도록 설계되었습니다.
저는 엔지니어로서 당연히 할 법한 행동을 할 뻔했습니다. 바로 포크(fork)를 하고, 마음에 들지 않는 부분들을 깎아낸 뒤, 저만의 "GSD lite"를 출시하는 것이었습니다. 이 글은 제가 실제로 먼저 숙제를 수행하며 발견한 내용과, 왜 제가 완전히 다른 길을 가려 하는지에 대한 기록입니다.
GSD의 실제 내부 구조 (under the hood)
도구를 포크하거나 교체하는 것에 대해 논하기 전에, 먼저 그것이 어떻게 연결되어 있는지 알아야 합니다. 그래서 저는 리포지토리(repo)를 읽었습니다.
GSD는 세 개의 레이어가 서로 쌓여 있는 구조입니다:
| 레이어 | 내용 | 내가 신경 써야 하는가? | 포크 시 유지 관리 비용 |
|---|---|---|---|
| Markdown "brain" (두뇌) | commands/ → workflows/ → agents/ → references/ → templates/: 전체 루프를 구동하는 프롬프트 (prompts) | 예, 이것이 제가 좋아하는 부분입니다 | 높음, 업스트림(upstream)에서 가장 변경이 잦은 파일들입니다 |
| ... |
이 분석을 통해 어떤 커스텀(customization) 결정에서도 중요한 두 가지 사실이 도출됩니다:
워크플로(workflows)는 독립적인 프롬프트가 아닙니다. 워크플로는 컨텍스트(context)를 로드하고, 상태(state)를 업데이트하며, 커밋(commit)하기 위해 gsd-tools를 끊임없이 호출합니다. 따라서 "좋은 프롬프트만 내 도구로 가져오면 되겠지"라는 생각은 단순한 복사-붙여넣기로 해결되지 않습니다. 프롬프트들은 바로 옆에 104개의 모듈로 구성된 CLI가 있다고 가정합니다. 두뇌를 가져온다는 것은 신경계 전체를 가져오는 것을 의미합니다.
GSD 복잡성의 대부분은 제가 절대 건드리지 않을 인프라(infrastructure)입니다. 설치 프로그램 하나만 해도 16개 이상의 런타임(runtimes)을 지원합니다 (Claude Code, Codex, Gemini CLI, Cursor, Windsurf, Copilot 등). 33개의 에이전트(agents), 약 67개의 스킬(skills), 11개의 훅(hooks), 기능 레지스트리(capability registry), 그리고 환각(hallucination)된 패키지를 방지하기 위한 공급망 게이트(supply-chain gate)가 존재합니다. 이는 인상적인 엔지니어링입니다. 하지만 동시에 제가 포크하는 순간 상속받게 될, 저에게는 필요 없는 90%의 표면적(surface area)이기도 합니다.
GSD가 무엇인지 정의하는 이름이 있으며, 이것이 이 글 전체의 핵심입니다: GSD는 자율 오케스트레이터(autonomous orchestrator)입니다. GSD는 하위 에이전트(subagents)를 생성하고, 작업별로 커밋하며, 스스로 진행합니다. 인간은 체크포인트(checkpoints)에서 승인할 뿐입니다. 이것은 설계 의도이며, 저와는 다른 운영자를 위해 만들어진 것입니다.
단 하나의 확고한 "거절": 작업별 원자적 커밋 (atomic per-task commits)
제 불만을 가장 핵심적인 부분만 남기고 깎아낸다면 바로 이것입니다: GSD는 실행되는 동안 작업당 하나의 커밋을 자동으로 수행합니다. git-integration.md에 명시된 실제 가이드는 다음과 같습니다:
| Task completed | YES | Atomic unit of work (1 commit per task) |
# How GSD stages and commits during execution
git add src/api/auth.ts src/types/user.ts
git commit -m "feat(08-02): create user registration endpoint"
제가 실제로 원하는 워크플로우는 인간이 개입하는 (human-in-the-loop) 방식입니다:
- 에이전트가 작업을 수행하되, 로컬에서 커밋하지 않은 상태로 진행합니다.
- 에이전트가 멈춥니다. 저는 제 머신에서 검증합니다.
- 제가 명령을 내립니다: 이제 테스트하고, 체크를 실행하고, 코드 리뷰를 하고, PR (Pull Request)을 생성하라고 말이죠.
- 커밋은 작업당 또는 자동으로 이루어지는 것이 아니라, 제 명령에 따라 나중에 이루어집니다.
이것은 소수의 취향 문제가 아닙니다. 에이전트 워크플로우 (agentic workflows)에 대한 2026년의 합의는 이를 아주 명확하게 설명하고 있습니다: "코드 리뷰는 대부분의 에이전트 워크플로우가 조용히 생략해 버리는 단계이며,", 건강한 패턴은 _"실행이 시작된 후가 아니라, 실행 전 단계에서 인간이 계획을 검토하는 것"_입니다. GSD의 자동 커밋은 시니어 엔지니어에게 꼭 필요한 제어 지점들을 정확히 제거해 버립니다.
게다가, 저는 코드를 건드릴 수가 없습니다. 만약 제가 한 줄이라도 수정하거나 무엇이라도 하면, 전체 커밋 히스토리가 엉망이 될 것이고, 시스템은 이를 이해하기 위해 몇 분(그리고 엄청난 양의 토큰)을 허비할 것입니다: "그래, 내 코드 한 줄 정도는 내가 직접 할 수 있으니 고맙지만 사양할게"라고 말이죠.
그래서 이슈를 제기했습니다...
저는 이슈 #745를 등록했습니다: 실행 중 모든 커밋을 연기하고, 워킹 트리 (working tree)를 더티 (dirty) 상태로 남겨두어, 어떤 것이 반영되기 전에 제가 전체 단계를 하나의 디프 (diff)로 검토할 수 있도록 설정 옵션을 추가해 달라는 내용이었습니다.
메인테이너의 답변은 빠르고 명확했습니다:
"이것은 설계된 방식이며, 현재로서는 설계를 변경할 의사가 없습니다. 커밋은 컨텍스트 손실 등을 방지하기 위해 존재하는 것입니다. 이것은 기능 개선이 아니라 작동 방식 자체를 재설계하는 일입니다."
공정하게 말하자면, 이 부분이 실제로 모든 것을 명확하게 해주었습니다. GSD의 설계 관점에서 보면 메인테이너(maintainer)가 옳습니다. 만약 당신의 도구가 실행 도중 컨텍스트 윈도우 (context window)를 잃을 수 있는 자율 에이전트 (autonomous agent)라면, 모든 작업을 커밋 (commit)하는 것은 하나의 기능, 즉 충돌 복구 (crash-recovery) 및 컨텍스트 복구 (context-recovery) 메커니즘입니다. 저의 요청은 그 설계에 대한 미세한 조정이 아니었습니다. 그것은 다른 철학에 대한 요청이었습니다. 우리는 품질에 대해 이견이 있는 것이 아닙니다. 누가 운전대를 잡느냐에 대해 이견이 있는 것입니다.
하지만 실질적인 결과는 명확합니다. 저는 업스트림 (upstream)을 통해 이 문제를 해결할 수 없습니다. 제가 가장 바꾸고 싶은 것이 바로 메인테이너가 설계의 핵심이라고 방어하는 부분이며, 메인테이너는 정당하게도 매 릴리스 (release)마다 이를 계속해서 정교화해 나갈 것입니다. 제가 유지하는 어떤 커스텀 (customization)이라도 활발하게 유지 관리되는 반대 의견과 싸우는 일이 될 것입니다.
더 미묘한 비용: 협업처럼 보이지만, 결국은 그렇지 않은 순간
자동 커밋 (auto-commit)은 제가 지적할 수 있는 불만 사항입니다. 하지만 실제로 저에게 비용을 치르게 한 것은 이름을 붙이기가 더 어렵습니다. 왜냐하면 그것이 훌륭한 작업이라는 가면을 쓰고 있기 때문입니다.
그 양상은 다음과 같습니다. 저는 작은 개인 리포지토리 (repo)에서 흩어져 있는 몇 개의 노트를 하나의 파일로 합치는 아주 작고 일회적인 작업을 수행하려 했습니다. 수작업으로는 20분이면 끝날 일이었습니다. 그럼에도 불구하고 저는 적절한 루프 (loop)인 '논의 → 계획 → 실행' 과정을 거쳤습니다. 대략 2시간 후, 그것은 세련되었지만 완전히 잘못된 결과물을 저에게 건네주었습니다. 일회성 편집을 위해 재사용 가능하고 *단위 테스트 (unit-tested)*까지 완료된 도구를 만들어 놓은 것입니다. 제가 요청하지도 않았고, 원하지도 않았으며, 이제는 다시 되돌려야만 하는 무언가 말입니다.
정말 미치겠는 부분은 그것이 어디서 잘못되었는가 하는 점입니다. 'discuss(논의)' 단계는 제가 가장 좋아하는 부분입니다. 이해의 관문(comprehension gate)이자, 바로 이런 상황을 잡아내야만 하는 장치이기 때문입니다. 그런데 그러지 못했습니다. 논의 과정이 나빠서가 아니라, 그 과정에 특유의 성질이 있기 때문입니다. 즉, 사용자가 말한 내용에 대한 단 하나의 해석에 매몰되어, 그것이 여전히 말이 되는 지점을 지나칠 때까지 확신을 가지고 그 방향으로 강하게 밀어붙입니다. (마치 엄격함을 갖춘 것처럼) 날카로운 질문들을 계속 던지면서도, 실제로는 사용자가 부여한 범위를 조용히 벗어나 버립니다. 그 편차가 눈에 보일 때쯤이면 이미 계획(plan) 단계로, 그다음엔 코드(code) 단계로 흘러가 버린 상태이며, 그것을 다시 되돌리기 위해 비용을 지불하는 것은 결국 사용자입니다.
그리고 그 과정 내내 그것은 생산적인 것처럼 보입니다. 토론을 하고, 계획을 세우고, 조사를 시작합니다. 모든 신호가 "잘 진행되고 있다"라고 말하기 때문에 당신은 그것을 신뢰하게 되고, 청구서는 마지막에야 도착합니다. 당신이 결코 유지하도록 만들 수 없었던 미묘한 차이(nuance)를 놓친 무언가를 생성하는 데 소비된 시간으로서 말입니다. 이것이 매우 강한 주관을 가진 오케스트레이터(orchestrator)의 진짜 실패 모드입니다. 그 주관들이 하중을 지탱하는 구조(load-bearing)이기 때문에, 당신의 의도가 그것과 일치하지 않으면 도구는 유연하게 대처할 수 없습니다. 그저 유창하게 경로를 이탈할 뿐입니다.
그리고 이것은 운이 없었던 한 번의 실행이 아닙니다. 최근 진행한 70단계(70-phase) 프로젝트에서 저는 최소 50단계 이상을 다시 하거나 구조를 재조정해야 했습니다. 살아남은 단계들은 제가 코드를 정리하는 데 많은 시간을 미리 투입했고, 각 단계를 작고 엄격한 범위(tightly scoped)로 유지했기 때문에 가능했습니다. 그럼에도 불구하고, 약 5단계마다 저는 멈춰서 코드를 수동으로 수정해야 했습니다. 그래야 다음 5단계가 길을 잃지 않을 것이기 때문입니다. 검토 및 재프롬프트(review-and-re-prompt) 루프는 예외적인 상황이 아닙니다. 그것이 상시 상태(steady state)입니다. 이러한 프로젝트에서 제 시간의 상당 부분은 도구가 잘못된 아이디어에 전념하기 전에 이를 붙잡는 데 사용됩니다.
다음에 제가 수행한 유지보수 계산법
상류(upstream)로 문제를 넘길 수 없다면, 선택지는 포크(fork), 패치(patch), 설정(config), 또는 처음부터 빌드(build from scratch)하는 것입니다. 저는 이 네 가지를 모두 시도해 보았습니다.
설정(Config)은 기능을 끌 수는 있지만, 흐름을 재구성할 수는 없습니다. GSD의 config.json은 진정으로 심도 있게 설계되어 있습니다. 이를 통해 상당 부분 가볍게 만들 수 있습니다:
하지만 어떤 키도 그 '흐름(flow)'을 재구성할 수는 없습니다. 설정 파일에 '토론 내용을 계획에 병합', '토론 방식 변경', 또는 '내 방식으로 커밋하기'와 같은 명령을 내릴 수 없다는 뜻입니다. 동작 방식을 재구성하려면 리포지토리에서 가장 중요한 파일인 워크플로우 Markdown 파일을 직접 수정해야 합니다. 이는 곧 유지보수 함정(maintenance trap)에 빠지는 것을 의미합니다.
포크 vs 패치 비교는 사람들이 생각하는 것보다 패치 방식에게 덜 유리합니다:
| 포크 (업스트림 추적) | 패치 리포지토리 | |
|---|---|---|
| 충돌 빈도 | 동일함, 업스트림이 당신의 라인을 수정하면 깨짐 | 동일함 |
| ... |
업스트림 변경(upstream churn)에도 불구하고 깔끔하게 살아남을 수 있는 유일한 오버레이 패턴은 merge=ours로 표시된 **추가 파일(additive files)**입니다. 당신은 기존 파일을 수정하는 것이 아니라 항상 새로운 파일을 추가하기만 하므로, 주기적인 동기화에서 충돌이 발생하지 않습니다. 이는 강력하지만, 명확한 한계가 있습니다. 즉, 추가할 수 있는 것(당신의 설정 파일, 런처, 당신의 기술, 호스트 측 래퍼)에 대해서는 작동하지만, _동작 방식 수정(behavior edits)_에는 절대 작동하지 않는다는 것입니다. 제 변경 사항은 동작 방식 수정입니다. 따라서 어떤 경우에도 비싼 길에 갇히게 됩니다.
이것이 제가 전체 결정을 재정립하게 만든 결론입니다: 흐름을 재의미화하는 공개 도구에게 포크는 최악의 영역(worst quadrant)입니다. 이는 당신이 원하지 않는 인프라의 90%를 유지보수해야 할 뿐만 아니라, 자신이 커스터마이즈한 바로 그 파일들에서 병합 충돌과 싸워야 한다는 것을 의미합니다.
포크 무덤 (The fork graveyard)
저는 이론적으로 이 주장을 하고 싶지 않았기에, 증거를 찾아보았습니다. 즉, 리포지토리의 모든 포크들을 살펴보았습니다.
250개의 포크. 그중 성공적인 분기된 '경량화(lite)' 버전은 단 하나도 없습니다. 분석 결과는 다음과 같습니다:
- 대부분의 포크는 업스트림 자체가 사용했던 오래된 이름을 가진, 손대지 않은 개인 복사본일 뿐이며 프로젝트가 아닙니다.
- 몇 개는 README를 재브랜딩하거나 번역한 것으로, 실제 작업 커밋은 하나에 불과합니다.
- 하나의 포크는 야심찬 설명에도 불구하고 메인 브랜치에 커밋이 전혀 없는 런타임 어댑터입니다.
- 유일하게 진지한 것은 **통합 래퍼(integration wrapper)**인데, 이것이 전체 연구에서 가장 교훈적인 대상입니다.
그 진지한 포크(fork)는 GSD를 제품에 내장하고 있는 한 기업의 것입니다. 업스트림(upstream)에 대한 그들의 전체 디프(diff)는 다음과 같습니다:
added .gitattributes (merge=ours rules)
added scripts/sync-upstream.sh
added NOTICE / CONTRIBUTING-UPSTREAM.md
...
그들의 README에는 전략이 명시되어 있습니다: "GSD 자체는 수정 없이 실행됩니다." 그들은 Claude Agent SDK를 통해 호스트 측(host-side)에서 이를 래핑(wrap)하고, 자신들의 오케스트레이터(orchestrator)에서 승인 체크포인트(approval checkpoints)를 가로챕니다. 그리고 그들의 .gitattributes는 실전에서 사용되는 merge=ours 트릭을 보여줍니다:
# 업스트림과 병합할 때 "ours"를 유지하여
# 주기적인 sync-upstream.sh 실행 시 우리가 관리하는
# 파일에서 충돌이 발생하지 않도록 합니다.
NOTICE merge=ours
...
모든 것을 바꾼 재정의 (The reframe)
제가 첫날부터 이해했더라면 좋았을 점이 여기 있습니다. GSD를 나머지 분야와 비교해 보면, 기능과는 전혀 상관없는 분기점이 나타납니다:
- 자율 오케스트레이터 (Autonomous orchestrators) (GSD, BMAD): 이들은 운전대를 잡습니다. 서브 에이전트(subagents)를 생성하고, 스스로 커밋하며, 스스로 진행합니다. 인간은 가끔 승인만 합니다.
- 스펙/계획 레이어 (Spec/planning layers) (GitHub Spec Kit, OpenSpec, Agent OS, Taskmaster): 이들은 구조를 제공하고 문을 잡아줍니다. 이들은 스펙/계획/태스크(spec/plan/tasks)를 생성하며, 실행은 여러분의 일반적인 에이전트를 통해 이루어집니다. 이 과정에서 여러분은 이미 루프(loop) 안에 있으며, 커밋은 기본적으로 여러분의 소유가 됩니다.
지형 (The landscape)
스펙 기반 개발(Spec-driven development)은 2026년에 폭발적으로 성장했습니다. 커뮤니티 맵은 30개 이상의 프레임워크를 추적하고 있습니다. 시니어 엔지니어로서 제가 실제로 관심을 두는 부분과 대조해 보면 다음과 같습니다:
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기