| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | 5 | 6 | 7 |
| 8 | 9 | 10 | 11 | 12 | 13 | 14 |
| 15 | 16 | 17 | 18 | 19 | 20 | 21 |
| 22 | 23 | 24 | 25 | 26 | 27 | 28 |
- CLI
- Cold Publisher
- Depromeet
- 건국대학교
- 큐시즘
- claude code
- 파이썬
- time slice
- 마블 다이어그램
- oh-my-claudecode
- js 개발자라면 알아야하는 핵심 컨셉
- RxJava
- Hot Publish
- spring
- 생활코딩
- CPU Scheduling
- Hot Publisher
- AI parallel develop
- 자바스크립트
- 버전관리
- OOAD
- 원격 저장소
- js
- Git
- github
- Round Robin
- Observable
- spring boot
- OS
- 병렬 피처 개발
- Today
- Total
글쓰는 개발자
Claude와 git worktree를 결합해 생산성을 2배 향상한 경험담 본문
문제 인식
AI와 함께 몇년간 개발을 하면서, 문득 비효율적인 패턴을 발견했다.
나: "이 API에 validation 로직 추가해줘"
AI: (코드 분석 10초, 작성 20초, 테스트 30초...)
나: (메신저 확인, 스크롤, 물 떠오기...)
AI에게 일을 시키는 동안 개발자는 Idle 상태에 빠지기 십상이다. 그렇다고 아무것도 안할 수는 없으니, 멍하니 기다리거나, 잠깐 휴대폰을 확인하거나, 화장실에 다녀온다. AI가 사람 대신 일을 빠르게 처리해준다는 건 좋은데, 그 사이에 개발자가 놀고 있으면 이게 진짜 생산성 향상인지 모르겠다.
게다가 요즘은 프롬프트 한 줄이 수천줄의 코드를 만들어 내는 초생산성의 시대 아니던가. 비는 시간을 조금씩 모았으면 다른 피처들도 많이 진행시켜 놓을 수 있었을텐데. 화장실에 버리기에는 아까운 시간이다.
이러한 생각으로부터 나는 새로운 워크 플로우를 실험해보기 시작했고, 결과적으로 나의 생산성을 약 2배 가량 향상시켜준 성공적인 프로젝트가 되어 이곳에 공유하고자 한다.
TL;DR
- Claude 서브에이전트 + Git worktree 조합으로 병렬 개발 구현
- rsync로 IDE 전환 문제 해결
- 결과: 월간 커밋 +92%, 주당 이슈 처리량 2배
- 핵심은 사전 설계 — 충돌 회피가 병렬 개발의 성패를 가름
Git Worktree란
브랜치를 전환한다면 보통은 이런 패턴이 될 것이다.
git stash # 또는 불필요한 git commit
git checkout feature-B
# IDE 작업
git checkout feature-A
git stash pop
텍스트 에디터로 코드를 보기 힘든 인간에겐 당연한 흐름일지 모르겠으나, 굳이 IDE로 예쁘게 코드를 보지 않아도 되는 AI에게 일을 시키기에는 느리기고 하고 작업 공간도 보존되지 않아서 불편하다.
나도 이런 식으로 매번 작업을 하다가 우연히 git worktree라는 기능을 알게 되었다. git worktree란 한마디로, 작업 디렉토리를 버전별로 copy해서 여러 디렉토리로 구성하는 방식이다. 가령, feature-A와 feature-B에 대한 worktree를 만들면 아래처럼 내가 지정해준 위치에 각 feature를 위한 디렉토리가 구성된다.
project/
├── main/ ← develop 브랜치
└── worktrees/
├── feature-A/ ← feature-A 브랜치 (독립 폴더)
└── feature-B/ ← feature-B 브랜치 (독립 폴더)
즉, checkout은 하나의 디렉토리에서 브랜치를 바꾸는 것이고, worktree는 브랜치마다 디렉토리를 따로 두는 것이다.
이걸 알고 나니 "AI한테 각 폴더에서 동시에 작업시키면 되겠다"는 생각이 들었다.
| Git Checkout | Git Worktree | |
| 브랜치 전환 | 파일 교체 | 폴더 이동 |
| 동시 작업 | 불가능(또는 비효율) | 가능 |
| 디스크 | 1배 | N배 |
첫 번째 시도: 직접 구현 (실패)
처음엔 MCP로 Git worktree를 제어하는 멀티 브랜치 시스템을 직접 만들어봤다. 당시엔 AI 에이전트 오케스트레이션 개념을 몰랐기에, "여러 브랜치에서 동시에 작업하려면 멀티 AI 인스턴스를 직접 관리해야겠지"라고 생각했다. 결과는 대실패였다. 병렬 처리가 제대로 안 됐고, 에이전트가 무엇을 하려는지 이해하지 못했으며, 명령을 내릴 때마다 엉뚱한 답을 내놓아 몇번 해보다가 폐기해버렸다.
'무모한 도전이었나?'라는 생각을 하던 와중에, oh-my-opencode의 후속 버전인 oh-my-claudecode를 알게 되었다.
전환점: 서브에이전트 오케스트레이션
oh-my-claude(OMC)에는 서브에이전트 오케스트레이션이 이미 구현되어 있었다. 내가 삽질했던 게 이미 다 구현되어 있었던 것이다. 역시.. 바퀴를 발명하기전에 먼저 파는게 없는지 찾아봤어야 했는데. 명령만 내리면 뚝딱뚝딱 구현해주는 시대다보니, 역설적으로 찾아볼 생각을 못했던 것 같다. 무튼 OMC를 이용하니 내가 생각했던 worktree 기반의 병렬 개발이 훨씬 잘 작동했다.
물론 "병렬로 해줘"라고만 말하면 되는 건 아니다. 실제로는 각 피처별로 상세한 설계를 먼저 토의해야 했다. 우리 팀은 사내 메신저인Dooray를 쓰는데, 여기에도 Jira 같은 티켓 시스템이 있어서 이걸 MCP로 연동해뒀다. 그래서 클로드가 티켓 내용을 직접 읽고 요구사항을 파악할 수 있다.
나: "쇼핑몰 기능을 3개 피처로 나눠서 병렬 개발하려고 해.
티켓 #1234, #1235, #1236 내용 읽어보고 설계 토의하자."
AI: (MCP로 티켓 조회 후)
"#1234: 상품 목록 API - 페이지네이션 필수, 카테고리 필터..."
"#1235: 장바구니 기능 - 비회원도 담기 가능해야 함..."
"#1236: 주문 생성 - 토스페이먼츠 연동 필요..."
이후 각 피처별로 구현 범위, 수정 파일, 테스트 기준을 정리하고, 충돌 분석까지 한다. 이 과정을 거친 후 프레임워크가 알아서 작업을 분석해 적절한 에이전트 타입을 선택하고, 독립적인 작업은 병렬로, 의존성 있는 작업은 순차로 처리한다.
설계 문서 = 맥락 보존
각 worktree마다 spec.md와 implement.md 두 개의 문서를 꼭 작성한다.
worktrees/feature-A/
├── A-spec.md ← 기능 명세, 테스트 기준
├── A-implement.md ← 구현 계획, 수정 파일 리스트
└── src/
이렇게 하는 이유는, 한 세션에서 AI 에이전트와 여러 브랜치에 대한 설계를 토의하다 보면 나중에 맥락을 잊어버리는 경우가 많았기 때문이다. Context window에 한계가 있고, 긴 세션에서는 context compaction이 일어나기 때문이다. 그래서 설계 토의 결과를 스냅샷으로 문서화해둔다. 세션이 끊겨도 맥락 복구가 가능하고, 다른 브랜치 작업하다 돌아와도 "spec.md 읽고 이어서 작업해줘"라고만 하면 된다.
IDE 전환 문제와 해결
이렇게 하니 병렬 개발은 원활히 잘 되었는데, 또 다른 문제가 나타났다. 당연하게도 에이전트를 시켜서 코드 개발을 하고 나면, 개발자가 손수 컨벤션에 어긋나거나 미처 맥락을 파악하지 못해 이상하게 구현된 코드들을 살펴보고 고치는 작업이 필요하다.
worktrees/feature-A/ # AI가 여기서 작업
worktrees/feature-B/ # AI가 여기서 작업
worktrees/feature-C/ # AI가 여기서 작업
문제는, 나는 Kotlin + Spring boot 기반 프로젝트를 개발하고 있는데, 각 worktree 코드를 리뷰하기 위해선 IntelliJ를 브랜치 수만큼 열어야 했다. 그 이유는, worktree가 브랜치를 점유하면 해당 브랜치로 checkout이 불가능해지기 때문이다. Git이 같은 브랜치를 두 곳에서 동시에 수정하는 걸 막기위해 일종의 lock을 걸어놓은 셈이다. (왜 worktree간 switching 기능은 제공하지 않을까 의문이다.)
처음엔 무식하게 여러 창을 켜보기도 하고, module을 import 해서 여러 프로젝트인 것처럼 사용해보기도 했지만, 굉장히 무거운 IntelliJ 창이 하나 늘어날 때마다 내 생산성을 실시간으로 저하시키는걸 느낄 수 있었다. 그리하여 "IDE로 해결한다"는 접근법은 포기했고, 또 다시 AI와의 토의를 거쳐 방식을 두 가지로 좁혔다.
Symlink 방식
Symlink(심볼릭 링크)는 파일이나 폴더를 가리키는 바로가기 같은 것이다. main project에서 worktree의 특정 피처 디렉토리에 symbolic link를 만들면, 굳이 창을 전환하지 않고도 코드가 바뀐 것처럼 관리할 수 있지 않을까? 생각했다.
Intellij -> main-project -> symlink(worktrees/feature-product/)
문제는 IDE 캐시가 symlink 변경을 제대로 감지하지 못한다는 점이었다. 링크 대상을 변경해도 이전 파일 인덱싱이 남아서 전혀 switching한다는 느낌을 받지 못했다. 이걸 해결하려면 invalidate cache로 cache를 날리고 프로젝트를 re-open 해줘야 하는데, 이럴 바엔 여러 intellij 창을 키는게 효율적이란 생각이 들었다.
Rsync 방식 (최종 선택)
결국 내가 원한 건 git checkout의 동작을 모사하는 것이다. checkout이 "브랜치 내용을 현재 폴더에 덮어쓰는 것"이니까, 그걸 rsync로 수동으로 하면 된다. 참고로, Rsync는 폴더 간 파일을 동기화하는 유닉스 명령어다. 변경된 파일만 복사하고, --delete 옵션으로 원본에 없는 파일은 삭제한다.
rsync -av --delete worktrees/feature-product/ main-project/
개발자는 main-project만 IDE로 열어두고, AI는 worktree에서 작업한다. worktree의 작업이 끝나면, rsync를 통해 worktree의 내용을 main-project로 읽어온다. 이렇게 하니 git checkout만큼은 아니더라도 체감 95% 정돈 checkout 같은 느낌을 줄 수 있었고, 이 5%는 병렬 개발로 인해 늘어난 생산성에 대한 trade-off 비용으로 내기로 했다.
최종 워크플로우
shop-project/
├── main/ ← IDE는 여기만 열어둠 (뷰어 전용)
└── worktrees/
├── feature-product/ ← AI가 실제 작업
├── feature-cart/
└── feature-order/
많은 삽질을 거쳐, 현재 적용된 워크 플로우는 아래와 같다.
- AI와 각 브랜치에 대해 사전 설계 토의(이것도 스킬로 만들어두면 편하다)
- AI가 각 worktree에서 작업 (독립 브랜치에서 동시 개발)
- 코드 리뷰:
rsync -av --delete worktrees/feature-cart/ main/(보통 zsh 명령어로 대체해서 사용) - 각 브랜치별 PR 생성, 리뷰 완료된 것부터 순차 병합
충돌 회피 전략
아직 작성하지 않은 내용이 있는데, 충돌 관리는 병렬 개발에서 어쩌면 가장 신경써야 하는 부분일지 모른다. 무작정 병렬로 돌리면 merge hell을 경험하게 될 지도 모르니까. 해결책은 사전 설계 투자다. 물론 이것도 내가 할 일은 아니고, AI에게 자연어로 열심히 시키면 된다. 그러기 위해 사전 설계를 다음과 같이 구성한다.
[Phase 1: 전체 피처 설계]
- 병렬 개발할 피처 A~E에 대한 개별 요구사항 정리
- 각 피처별 구현 명세 작성 (spec.md, implement.md)
- 테스트 기준 문서화
- 수정/추가될 파일 리스트 도출
[Phase 2: 충돌 분석]
- 공통 수정 파일 확인
- 충돌 위험도 평가
[Phase 3: 실행 계획]
- 독립적인 피처 → 병렬 진행
- 의존성 있는 피처 → 순차 처리
- 공통 모듈 변경 → 별도 PR 먼저 병합
실제 예시
쇼핑몰 MVP에서 5개 피처를 구현한다고 하자.
[피처 목록]
1. 상품 목록/상세
2. 장바구니
3. 주문/결제
4. 리뷰 작성
5. 마이페이지
[충돌 분석]
Product 엔티티 → 피처 1, 4에서 수정
User 엔티티 → 피처 3, 5에서 수정
장바구니 → 주문에 의존성 있음
[실행 계획]
Sprint 1 (병렬): product, cart
Sprint 2 (순차): order (cart 머지 후), review (product 머지 후)
Sprint 3: mypage (order 머지 후)
이렇게 하면 병렬 개발의 속도는 유지하면서 충돌은 최소화할 수 있다.
정량적 결과
스택: Kotlin + React
기간: 2025년 11월 ~ 2026년 1월
대상: 담당 개발 중인 서비스
| 지표 | Before(11-12월) | After(1월) | 변화 |
| 월간 커밋 수 | 평균 50개 | 96개 | +92% |
| 주당 티켓 처리 | 2~3개 | 4~6개 | ~2배 |
| 피크 주간 커밋 | 21개 | 43개 | 2배 |
| 동시 활성 브랜치 | 1~2개 | 6개 | 3배 |
커밋이 많다고 생산성이 높은 건 아니다라는 반론이 있을 수 있다. 그래서 티켓 처리량을 함께 보았다. 주당 2~3개에서 4~6개로 늘었고, 동시 활성 브랜치도 눈에 띄게 증가했다. 물론 그럼에도 일감의 성격이나 당시 상황에 따라 처리 속도가 다를 수도 있겠지만, 정성적인 평가를 내려보더라도 확실히 업무 중간 유휴 시간이 줄었고, 컨텍스트 관리만 잘 해준다면 기존보다 훨씬 많은 일을 빠르게 처리할 수 있다는 생각이 들었다.
이런 방식이 손에 익으면, 브랜치를 빠르게 스위칭하면서 정확성 또한 놓치지 않고 여러 일감을 병렬 개발할 수 있는 능력 또한 향상하리라 생각한다.
느낀 점
좋았던 점
- 작업 리듬이 붙는다: 하나의 피처를 기다리지 않고 계속 다음 작업으로 이동. 유휴 시간이 거의 사라진다.
- 피처 간 연관성이 보인다: 여러 피처를 한 세션에서 다루다 보니 전체 그림이 보인다. "이 기능은 저 피처가 끝나고 해야되겠는데?" 같은 통찰이 생긴다. AI도 알게되는건 덤.
- 업무 텐션이 올라간다: 피처 1~2개만 개발할 때는 중간에 집중력이 저하되는데, 여러 피처 돌아가며 개발하면 계속 새로운 문제에 집중하게 된다.
주의할 점
- AI 코드 검증 책임은 여전히 개발자에게: 병렬 개발은 리뷰할 코드량 증가를 의미한다. 병렬로 개발하더라도 리뷰 및 테스트는 여전히 직렬로 한땀한땀 진행한다.
- 충돌 관리 필수: 사전 설계 없이 무작정 병렬 진행하면 merge hell이 발생할테니, 시간 절약보다 충돌 해결에 더 많은 시간이 소모될 수 있다.
- 모든 작업이 병렬 가능한 건 아니다: 복잡한 리팩토링은 순차 처리가 낫고, 탐색적 개발은 한 가지에 집중해야 할 때도 있다.
로컬 환경이 꼭 필요할까?
여기부터는 주제에서 벗어나는 얘기지만, 기록을 위해 남긴다. 이런 방식으로 개발하다 보니 의문이 생겼다.
- AI 에이전트가 실제 코딩을 하고
- IDE는 그저 코드 뷰어 역할이고
- rsync로 원격 동기화도 가능하다면
리모트 서버에 worktree들을 두고, 거기서 AI 에이전트가 작업하게 하면 어떨까.
[Local] [Remote Server]
IDE (뷰어) <-- rsync --> worktrees/feature-A (AI Agent 1)
worktrees/feature-B (AI Agent 2)
worktrees/feature-C (AI Agent 3)
로컬 머신 리소스 절약도 가능하고, 에이전트를 PC on/off와 관계없이 24시간 어디서든 돌릴 수 있고, 어쩌면 여러 개발자가 같은 에이전트 풀을 공유할 가능성도 생긴다. 물론 네트워크 지연, 보안, 비용, 개발자별 환경 관리 및 충돌 등 고려할 게 많지만, 상황이 허락한다면 실험해볼 만한 주제이다.
결론
AI 코딩 시대의 개발자 역할이 바뀌고 있다.
예전: 개발자 → 직접 코딩 → 커밋
지금: 개발자 → 설계 & 지휘 → AI들이 병렬 코딩 → 검증 & 병합
마치 오케스트라 지휘자처럼 전체 아키텍처를 설계하고, 각 AI 에이전트에게 파트를 할당하며, 조화롭게 연주되는지 검증하는 역할이다. Git worktree + AI 서브에이전트 조합은 이런 오케스트레이션을 가능하게 만드는 인프라가 되어준다.
실전 팁
작게 시작하기
처음부터 6개 브랜치 병렬은 무리일지 모른다. 독립적인 2개 피처로 시작해서 충돌 경험을 쌓은 후 확장하자.
자동화 투자
worktree 스위칭은 rsync 기반으로 파일만 훔쳐오는 방식이기 때문에, git의 사용성만큼 끌어올리기 위해선 몇가지 명령어 예약을 해두면 좋다. 아래는 반드시 추가하면 좋을 명령어들.
- worktree -> main directory로 rsync하기 (checkout 역할)
- main directory -> worktree로 rsync하기 (checkout후 파일 수정하여 worktree에 재반영)
- 현재 어떤 worktree로 switching 했는지 확인하기 (파일만 가져간거라 git은 모르기 때문에 시스템 어딘가에 기록해두고 사용해야 함)
참고 자료
(추가)
글을 쓰고 며칠이 지나 클로드 코드 팀이 추천하는 실전 팁이라는 글에 worktree를 활용해 병렬 세션으로 개발하는게 최고의 생산성 향상 팁이라는 글이 올라왔다. 야호! 물론 나는 단일 세션 - 병렬 서브 에이전트를 사용한다는 점에서 좀 달랐지만... 그래도 큰 방향은 일치하는 것 같아 기분이 좋았다. 심지어 worktree에 이름을 붙이고 shell alias(za, zb, zc)를 설정해 한 번의 키 입력으로 전환하는 방식도 활용한다고 하니, 사실상 내 방식이 검증된 것이나 다름없지 않을까. 좀 더 업무 방식이 정형화되면, 팀이나 사내에도 공유해봐야겠다.
https://news.hada.io/topic?id=26330
Claude Code 창시자가 공개한 실전 사용 팁 | GeekNews
1. 병렬 작업을 최대한 활용3~5개의 git worktree를 동시에 실행하고 각각 별도의 Claude 세션을 병렬로 운영하는 것이 클로드 코드 팀 내부에서 최고의 생산성 향상 팁일부는 git checkout 방식을 선호하
news.hada.io
'Development > 기타' 카테고리의 다른 글
| [이론]js 개발자라면 알아야하는 핵심 컨셉 33개 #8.IIFE, Modules and Namespace (0) | 2019.08.26 |
|---|---|
| [이론]js 개발자라면 알아야하는 핵심 컨셉 33개 #7.Expression vs Statement (0) | 2019.06.22 |
| [이론]js 개발자라면 알아야하는 핵심 컨셉 33개 #6.Scope (0) | 2019.06.17 |
| [이론]js 개발자라면 알아야하는 핵심 컨셉 33개 #5.Typeof (0) | 2019.06.14 |
| [이론]js 개발자라면 알아야하는 핵심 컨셉 33개 #4.Type Coercion (0) | 2019.06.11 |