기다리지 말고, 포크(Fork)하세요
요약
AI 에이전트 기반 코딩 도구의 등장으로 인해 사용자가 도구를 직접 수정하고 최적화하던 기존의 개발 문화가 변화하고 있습니다. 에이전트가 코딩 노동 비용을 낮춤에 따라, 벤더 중심의 폐쇄적 도구 환경에서 벗어나 개인화된 '포크(Fork)'를 통해 도구를 제어해야 한다는 관점을 제시합니다.
핵심 포인트
- AI 에이전트의 등장으로 코드 수정 및 포크 비용이 급격히 감소함
- Claude Code 등 최신 도구들이 벤더 중심의 폐쇄적 생태계로 변모하는 추세
- 사용자 맞춤형 설정(dotfiles)과 도구 제어권의 중요성 재부각
- 에이전트 시대에도 자신만의 작업 환경을 구축하는 '포크' 정신이 필요함
아무도 당신에게 dotfiles(설정 파일)를 업스트림(upstream)하라고 요구한 적이 없습니다.
지난 30년 동안 우리가 만지는 모든 도구와의 계약은 이랬습니다. 만약 마음에 들지 않는다면, 당신이 직접 수정하고 그 수정 사항은 당신과 함께 남는 것이었습니다. 그러다 도구들이 코드를 작성하기 시작하면서, 그 계약은 조용히 끝이 났습니다.
이 에세이는 왜 그 계약이 다시 논의 테이블 위로 올라왔는지에 관한 것입니다. 왜냐하면 과거에 포크(forking)를 비용이 많이 들게 만들었던 요소인 '노동(labour)'이, 바로 에이전트(agents)에 의해 저렴해졌기 때문입니다.
이 글의 목차
- 작업대 본능 (The Workbench Instinct)
- 그리고 하네스(Harness) 시대가 도래했다
- 포크(Forking)는 언제나 탈출구였다
- 코드가 저렴해졌다
- 내가 내 포크(Fork)에 담은 것
- 기능이 반드시 유용할 필요는 없다
- 당신의 욕망이 한계다
- 포크(Fork)가 목적지다
- 이제 규율의 차례
- 즐거움을 되찾자
작업대 본능 (The Workbench Instinct)
자신의 설정(config)을 한 번도 만져보지 않은 개발자를 보여달라고 한다면, 저는 아직 시작하지 않은 사람을 보여드리겠습니다. Vim 사용자들은 목수들이 20년 동안 사용해 온 대패에 대해 말하듯 자신들의 init.lua를 자랑합니다. Emacs 사용자들은 할 수 있다는 이유만으로 텍스트 에디터 안에 운영체제 전체를 작성하기도 했습니다. VS Code는 확장 API(extension API)를 제공하고 사용자의 방해를 하지 않음으로써 부분적인 승리를 거두었습니다. Dotfiles 저장소는 공개된 결과물로서 별(star)을 받고 포크(fork)되는데, 이는 설정(setup) 자체가 기술(craft)의 일부이기 때문입니다.
이것은 생산성 연극(productivity theatre)이 아닙니다. 어떤 것은 진정한 필요에 의한 것이고, 어떤 것은 오직 당신만이 느끼는 특정한 불편함을 해결하기 위한 것이며, 많은 부분은 그저 재미를 위한 것입니다. 이 세 가지 모두 타당합니다. 작업대는 즐거움이 머무는 곳이며, 명령어를 별칭(alias)으로 지정하기 위해 누구도 허락을 기다리지 않습니다.
그리고 하네스(Harness) 시대가 도래했다
그러다 에이전트 기반 코딩 도구(agentic coding tools)들이 등장했고, 조용히 계약의 형태를 바꾸어 놓았습니다.
최고 수준의 에이전트 하네스(agent harnesses)들은 점점 더 벤더(vendor)에 의해 통제되고 있습니다. Claude Code는 제품이지, 당신이 클론(clone)하여 다시 빌드할 수 있는 저장소(repo)가 아닙니다. Google은 Gemini CLI를 은퇴시키고 폐쇄 소스(closed-source) 후속 제품으로 대체한다고 발표했습니다. 그리고 그 경계선이 어디에 그어져 있는지 주목하십시오. Codex CLI는 Apache-2.0 라이선스이며 GitHub에 그대로 공개되어 있지만, 대부분의 사람들이 실제로 클릭하게 되는 Codex 데스크톱 앱은 그렇지 않습니다. 터미널은 열려 있었지만, 인터페이스는 그렇지 않았습니다.
심지어 오픈 소스(open source)인 도구들조차 너무 빠르게 움직이고 있어서 당신의 패치(patches)를 받아들이지 않고 있습니다. T3 Code의 README에는 다음과 같이 명확하게 적혀 있습니다: 우리는 아직 기여(contributions)를 받지 않습니다.
이제 공정하게 말해보겠습니다. 이 논쟁의 게으른 버전은 댓글에서 비판받기 마련이니까요. 이 도구들은 완전히 닫힌 상자가 아닙니다. Claude Code는 실제 플러그인 생태계(plugin ecosystem) — 스킬(skills), 서브 에이전트(subagents), 훅(hooks), MCP 서버, 마켓플레이스, 수천 개의 커뮤니티 확장 기능 — 를 갖추고 있습니다. 그것은 진정하고 관대한 표면적(surface area)이며, 그렇지 않은 척하는 것은 정직하지 못한 일입니다.
하지만 실제로 중요한 점은 이것입니다:
확장 지점(extension point)은 당신이 부여받는 것이지만, 포크(fork)는 당신이 가져가는 것입니다.
플러그인 API는 벤더가 노출하기로 선택한 이음새(seams)를 정의합니다. 그 이음새 안에서는 엄청난 자유를 누릴 수 있습니다. 하지만 그 이음새 밖에서는 자유가 전혀 없습니다. 잘 설계된 확장 지점의 가장 좋은 예시인 스킬(skills)을 예로 들어보겠습니다. 당신은 원하는 만큼 많은 스킬을 작성할 수 있습니다. 하지만 그것들이 호출되는 방식 — 매칭 로직(matching logic), 모델이 특정 스킬이 관련 있다고 판단하는 시점, 무엇이 어떤 순서로 주입(injected)되는지 — 은 변경할 수 없습니다. UI는 전혀 변경할 수 없습니다. 컴포저(composer)도, 디프(diff)가 렌더링되는 방식도, 토큰 카운터(token counter)의 위치도 마찬가지입니다. 당신은 PostToolUse에 훅(hook)을 등록할 수 있습니다. 하지만 컨텍스트(context)가 압축(compacted)되는 방식은 변경할 수 없습니다. 슬래시 명령어(slash command)를 추가할 수는 있습니다. 하지만 새벽 2시에 당신의 프로덕션 저장소(production repo)에서 모델이 잘못된 형식의 도구 호출(malformed tool call)을 반환했을 때 발생하는 일은 변경할 수 없습니다.
이 중 그 어떤 것도 설계에 대한 불평이 아닙니다. 그것들은 선을 긋기에 합리적인 지점들이며, 누군가는 선을 그어야 합니다. 다만 그 선을 그은 주체가 당신이 아니라 그들이라는 것뿐입니다.
모든 확장 시스템(extension system)은 한쪽만이 계약을 작성하는 협상입니다. 도구가 텍스트 에디터(text editor)였을 때는 그것으로 충분했습니다. 하지만 도구가 당신의 코드 대부분을 작성하는 주체가 되었을 때는 상황이 달라집니다.
포크(Forking)는 언제나 탈출구였습니다
이 중 그 어떤 것도 새로운 것이 아닙니다. "벤더(vendor)가 내가 필요한 것을 출시하지 않는다"라는 문제에 대한 업계의 해답은 항상 동일했습니다. 코드를 가져가서 떠나는 것이었습니다.
- OpenOffice는 LibreOffice가 되었습니다.
- MySQL은 MariaDB가 되었습니다.
- Redis의 라이선스 변경은 우리에게 Valkey를 가져다주었습니다.
- Terraform의 변경은 OpenTofu를 가져다주었습니다.
- LinkedIn은 업스트림(upstream)이 자신들의 규모에 맞춰 움직일 수 없었기 때문에 수년간 자체적인 Kafka 브랜치를 운영했습니다.
- 모든 진지한 저지연(low-latency) 기업들은 자체적인 커널(kernel)을 튜닝합니다. 범용 스케줄러(general-purpose scheduler)는 그들의 꼬리 지연 시간(tail latency)을 위해 만들어진 적이 없기 때문입니다.
하지만 이 모든 것들의 공통점을 보십시오. 그것들은 팀을 필요로 했습니다. 포크는 결정이 아니라, 인원수(headcount)의 문제였습니다. 그것을 유지 관리하고, 리베이스(rebase)하고, CVE(취약점)를 패치하며, 영원히 이끌고 나갈 사람들이 필요했습니다. 그래서 우리 대부분의 솔직한 계산은 다음과 같았습니다. "이 변화를 원하지만, 향후 3년 동안 포크를 책임질 만큼 원하지는 않는다." 그래서 우리는 공허 속으로 기능 요청(feature request)을 던져두고 다음으로 넘어갔습니다.
변한 것은 바로 그 계산법입니다. 라이선스가 아닙니다. 비용입니다.
코드가 저렴해졌습니다
우리 모두가 서서히 내면화하고 있는 사실은, 포크의 비용이 발생하는 부분은 결코 아이디어가 아니었다는 점입니다. 그것은 노동(labour)이었습니다. 메뉴가 채워지는 단 한 곳을 찾기 위해 익숙하지 않은 4만 줄의 TypeScript 코드를 읽는 것. 빌드(build) 과정을 이해하는 것. 테스트를 작성하는 것. 6주 후에 리베이스를 수행하는 것.
그것이 바로 에이전트(agents)가 이제 잘하는 작업입니다. 창의적인 부분이 아니라, 고고학(archaeology) 작업 말입니다. 에이전트에게 리포지토리(repo)를 가리키며 컴포저(composer)의 슬래시 메뉴가 어디에서 조립되는지 물으면, 저녁 내내 걸릴 일을 90초 만에 해결할 수 있습니다.
새로운 계산법
# 과거의 포크
아이디어 → 팀 → 유지 관리 → 리베이스 → 당신의 인생 3년
...
따라서 포크는 더 이상 전략적 결단이 아니라, 그저 화요일에 할 수 있는 일이 됩니다.
이 모든 과정이 판단(judgment)을 없애주는 것은 아닙니다. 에이전트(agent)가 고고학적 조사(archaeology)를 수행할 뿐, 무엇을 변경할 가치가 있는지 결정하는 것은 여전히 당신이며, 저장소(repo)에 반영되는 결과물에 대한 소유권 또한 여전히 당신에게 있습니다. 이는 제가 From Coders to Owners에서 기술했던 것과 동일한 변화입니다. 타이핑(typing) 비용은 저렴해졌지만, 책임의 무게는 단 한 치도 움직이지 않았습니다. 포크(fork)는 그 사실을 구체화할 뿐입니다. AI가 차이점(diff)을 작성하면, 당신은 작업대(workbench)를 소유합니다.
내가 내 포크(Fork)에 반영한 것들
저는 T3 Code의 개인용 포크를 운영해 왔습니다. 이는 공개되어 있으며 — github.com/arjunagi-a-rehman/t3code — 제가 저 자신을 위해 여기에 반영한 기능들은 다음과 같습니다:
1. 컴포저(composer) 내 OpenCode 슬래시 명령어(slash commands). 기존의 슬래시 메뉴는 /model, /plan, /default와 같은 내장 명령어만 표시했습니다. 이제는 OpenCode 커스텀 명령어를 찾아냅니다. 즉, 설정(config) 디렉토리의 전역 명령어와 프로젝트별 .opencode/command/*.md 파일을 인식합니다. 새로운 providers.listProjectSlashCommands RPC가 스레드의 현재 작업 디렉토리(cwd)를 기준으로 이를 해결합니다. 로컬 모드에서는 파일 스캔을 통해, 외부 서버(external-server) 모드에서는 서버에 대한 command.list를 통해 수행됩니다. 프로젝트 명령어는 이름이 충돌할 경우 OpenCode 자체의 우선순위 규칙에 따라 스냅샷 명령어를 덮어씁니다. 또한, 새로운 턴(turn)에서 /name args로 시작하면 일반 프롬프트 텍스트로 전송되는 대신 session.command를 통해 라우팅됩니다.
2. 커스텀 앱 배경 이미지. 이미지를 업로드하면 기기에 데이터 URL(data URL) 형태로 저장되며, 불투명도(opacity)를 조절할 수 있습니다. 셸(shell) 요소들은 반투명한 스크림(scrim) 형태로 변하여 배경이 비쳐 보이도록 합니다.
3. 일괄 숨기기/표시 기능이 포함된 프로바이더(provider) 모델 필터링. 모델 카탈로그가 지나치게 방대해졌기 때문에, 서브 프로바이더(sub-provider) 필터링과 전체 숨기기/전체 표시 제어 기능을 추가했습니다.
세 가지 기능입니다. 이 중 어느 것도 업스트림(upstream)에 제안되지 않았습니다. 그 어느 것도 누군가의 로드맵을 기다리고 있지 않습니다. 그것이 핵심입니다.
기능이 반드시 유용할 필요는 없다
이 목록에서 한 가지 눈치챌 점이 있습니다. 1번 항목은 실제 엔지니어링입니다. 3번 항목은 실제적인 불편함(annoyance)을 해결하는 것입니다. 2번 항목은 그저 _배경 이미지_일 뿐입니다.
그것은 단 1초도 아껴주지 않습니다. 그 무엇도 더 빠르게 배포하지 못합니다. 스프린트 계획 회의(sprint planning meeting)에서 단 한 문장의 정당성조차 입증하지 못할 것입니다. 제가 그것을 만든 이유는 하루 종일 바라보는 대상이 마치 내 것인 것처럼 느껴지길 원했고, 그것을 보는 것이 기분이 좋았기 때문입니다.
과거에는 소프트웨어를 변경하는 이유로 이것이 완전히 정상적이었습니다. 하지만 어느 순간부터 우리는 모든 변경 사항이 생산성 재판소(productivity tribunal) 앞에서 스스로를 변호할 것을 요구하기 시작했고, 저는 그것이 작업이 더 이상 즐겁지 않게 된 가장 큰 이유라고 생각합니다.
Vim 사용자에게 컬러 스킴(colourscheme)을 정당화하라고 요구하는 사람은 아무도 없습니다. 셸(shell)의 커스텀 프롬프트에 대해 ROI(투자 대비 효율)를 요구하는 사람도 없습니다. 꾸미기(rice), 폰트, 투명도, 로그인 시의 ASCII 아트 — 이 중 그 어느 것도 출력(output)에 관한 것이 아니었습니다. 그것은 이것이 당신의 작업대이며, 당신이 그 모습이 어떻게 보일지를 결정할 수 있다는 사실에 관한 것이었습니다. 그 본능은 결국 좋은 결과물을 만들어내는 것과 같은 본능입니다. 도구에 대한 소유권을 느끼는 사람은 일반 사용자는 절대 알아차리지 못할 것들을 발견하기 시작하기 때문입니다.
그러니, 쓸모없는 기능을 만드세요. 그것은 당신의 것입니다. 그것이 전부입니다.
당신의 욕구가 한계입니다
포크(Fork)가 저렴해지면, 제약 조건이 이동합니다. '할 수 있는가'의 문제가 아니라 '내가 실제로 무엇을 원하는가'의 문제가 됩니다.
수년 동안 저를 괴롭혔던 작은 예시가 있습니다: 왜 Express 앱은 FastAPI처럼 코드 자체에서 OpenAPI 정의를 생성할 수 없을까요? 왜 저는 목요일이면 동기화가 어긋나 버리는 YAML 파일을 직접 손으로 쓰고 있는 걸까요?
제 경력의 대부분 동안 그 답은 'Express가 원래 그러니까'였습니다. 이제 그 답은 '미들웨어(middleware)를 작성하라'입니다. 또는 Express를 포크하여 라우터(router) 레벨에서 인트로스펙션(introspection)을 추가하고 당신의 포크를 실행하십시오. 두 가지 모두 오후 시간 정도면 충분합니다.
지난 5년 동안 당신이 삼켜왔던 모든 "왜 그냥 — 안 되는 거지?"라는 의문에 이 과정을 곱해 보십시오. 그 백로그(backlog)가 바로 여기에 있는 진짜 기회입니다.
포크가 목적지입니다
이 부분은 제가 가장 크게 강조하고 싶은 부분입니다. 왜냐하면 사람들이 이 부분을 거꾸로 이해하기 때문입니다.
당신의 변경 사항이 어디론가 갈 필요는 없습니다.
머지 (Merge)될 필요도 없습니다. 풀 리퀘스트 (PR)를 보낼 필요도 없습니다. 그 누구에게도 리뷰를 받거나, 승인되거나, 축복받거나, 수락될 필요가 없습니다. 낯선 사람들에게 충분히 훌륭할 필요도 없습니다. 유스케이스 (Use case), 벤치마크 (Benchmark), 또는 이것이 커뮤니티에 왜 가치 있는지 설명하는 문단 따위도 필요하지 않습니다.
당신은 무언가를 원했고, 그것을 만들었으며, 그것을 사용합니다. 그것이 전체 라이프사이클 (Lifecycle)의 전부입니다.
우리는 오픈 소스 소프트웨어를 변경한다는 것이 곧 오픈 소스 소프트웨어에 '기여하는 것'이라는 생각을 어떠한 방식으로든 흡수해 버렸습니다. 즉, 디프 (Diff)의 유일하고 정당한 종착지는 업스트림 (Upstream)뿐이라는 생각 말입니다. 그렇지 않습니다. 업스트리밍 (Upstreaming)은 여러 선택지 중 하나일 뿐이며, 당신이 만들 대부분의 것들에 있어서 그것은 잘못된 선택입니다. 저의 배경 이미지는 결코 T3 Code에 들어가서는 안 됩니다. 그것은 T3 Code를 위해 만들어진 것이 아닙니다. 그것은 저를 위한 것이며, 이미 정확히 있어야 할 곳에 있습니다. 바로 저의 포크 (Fork), 저의 로컬 머신에서 지금 실행되고 있습니다.
그것은 결코 덜 가치 있는 결과가 아닙니다. 그것이 '정상적인' 결과입니다. 포크는 PR을 기다리는 대기실이 아니라, 그 자체로 목적지입니다.
아무도 당신에게 닷파일즈 (Dotfiles)를 업스트림 하라고 요구한 적이 없습니다.
이제 규율 (Discipline)에 대하여
이 이야기는 제가 실제로 걱정하는 부분으로 이어집니다. 왜냐하면 "그냥 포크하세요"라는 말이 매우 빠르게 추한 무언가로 변질될 수 있기 때문입니다.
첫 번째 행동으로 풀 리퀘스트 (Pull Request)를 열지 마세요. 제발 부탁드립니다. 메인테이너 (Maintainer)들은 익사하고 있습니다. 에이전트 (Agent)들은 디프 (Diff)를 생성하는 것을 극적으로 쉽게 만들었지만, 그것을 '리뷰'하는 것을 쉽게 만드는 데에는 아무런 기여도 하지 않았습니다. 그리고 그 비대칭성의 부담은 전적으로 무보수 인력들에게 전가되고 있습니다. 참고로, T3 Code는 기여를 받지 않겠다고 명시적으로 밝히고 있는 동안에도 수백 개의 열려 있는 PR을 가지고 있었습니다.
그러니:
- 기본적으로 본인의 포크(Fork)를 사용하세요. 그곳에서 결과물을 만드세요. 당분간은 그 상태로 유지하세요. 대부분의 변경 사항은 영구적으로 그곳에 머물게 될 것이며, 그것은 괜찮은 일입니다.
- 다른 무엇을 고려하기 전에
CONTRIBUTING.md를 읽으세요. 매번 확인하세요. 만약 기여를 받지 않겠다고 명시되어 있다면, 그 말을 믿으세요. - 업스트림(Upstream)을 위해 빌드하기 전에 이슈(Issue)를 열고 먼저 물어보세요. 해결책이 아닌 문제를 설명하세요. 절반의 경우에는 왜 그렇게 작동하는지에 대한 이유가 있다는 것을 알게 될 것입니다.
- 당신이 원하는 것이 프로젝트가 원하는 것과 다를 수 있음을 받아들이세요. 그것은 당신에 대한 거절이 아닙니다. 프로젝트에는 범위(Scope)가 있으며, 그 범위를 방어하는 유지 관리자(Maintainer)는 자신의 직무를 수행하고 있는 것입니다.
업스트림에 기여하는 것은 변경 사항이 진정으로 모두에게 도움이 되고 유지 관리자들이 그것을 원한다는 신호를 보냈을 때 행하는 관대한 행동입니다. 그것은 당신이 작성하는 모든 코드 라인에 대해 지불해야 하는 세금이 아닙니다.
그리고 포크(Fork)에 어떤 비용이 드는지 솔직하게 인지하세요. 왜냐하면 지금조차 포크는 공짜가 아니기 때문입니다:
- 보안 패치는 당신의 책임입니다. 만약 업스트림에서 취약점을 수정한다면, 당신은 리베이스(Rebase)를 하거나 취약점에 노출될 것입니다.
- 머지 부채(Merge debt)는 복리로 쌓입니다. 당신의 포크가 업스트림에서 멀어질수록, 매번 진행하는 업스트림 동기화(Sync)는 더 고통스러워집니다.
- 변경 사항을 작고 정교하게 유지하세요. 파일 3개만 건드리는 패치는 1년 동안의 리베이스(Rebase) 과정을 견뎌낼 수 있습니다. 모듈을 재구조화하는 패치는 첫 번째 메이저 릴리스에서 사라질 것입니다.
- 당신이 읽지 않은 에이전트(Agent) 생성 코드는 당신의 모든 리포지토리(Repository)에 쓰기 권한을 가진 도구에 설치하기로 선택한 부채입니다. 디프(Diff)를 읽으세요.
제가 제안하는 규칙은 다음과 같습니다: 자유롭게 포크하고, 유지하며, 그것이 정말로 원해진다는 확신이 들 때만 업스트림에 반영하세요.
즐거움을 되찾으세요
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기