개발 도구/Git・협업

stash 걸고 빌드 다시 하던 13분, git worktree로 없애버렸습니다

stackD 2026. 8. 4. 18:00
반응형

 

얼마 전 오후 4시, 리뷰 코멘트 반영하던 중에 핫픽스 요청이 떨어졌습니다. stash 걸고 브랜치 바꾸고 Gradle 다시 돌리는데 13분. 그 사이 제가 뭘 하려던 건지도 까먹었더라고요.

 

이게 한두 번이면 그러려니 하는데, 하루에 두세 번씩 반복되니까 진짜 일이 안 됩니다. 빌드 자체가 느린 게 문제가 아니에요. 손에 쥐고 있던 작업을 내려놓고 다시 집어드는 그 전환 자체가 비용이거든요.

 

git worktree가 stash·재빌드를 없애는 이유

문제의 정체부터 짚어볼게요. git checkout 으로 브랜치를 갈아타면 작업 디렉터리의 파일이 통째로 바뀝니다. 그 순간 IDE 인덱싱도 무효화되고, Gradle 빌드 캐시도 새 브랜치 기준으로 다시 맞춰야 해요. 여기서 10분 안팎이 그냥 날아갑니다.

 

stash 는 또 어떤가요. 작업을 잠깐 보관함에 넣었다가 나중에 꺼내는 방식이라, 작업을 한 줄로 세워두는 셈입니다. 두 작업을 동시에 살려둘 수가 없어요. 핫픽스랑 리뷰를 같이 잡아야 하는데 방법 자체가 안 받쳐주는 거죠.

 

깃 워크트리(git worktree) 는 여기를 정확히 비집고 들어옵니다. 하나의 저장소(.git 공유)를 여러 폴더에 동시에 펼쳐두는 기능이에요. 비교하자면, stash 가 작업을 한 줄로 세운다면 워크트리는 작업을 옆으로 나란히 깔아두고 cd 로 건너다니는 방식입니다. clone 처럼 통째로 복사하는 게 아니라 객체 DB를 공유해서 디스크도 적게 먹어요.

 

 

git worktree add로 브랜치별 폴더 상시 유지하기

쓰는 법은 생각보다 단순합니다. 핵심 명령 세 개만 알면 돼요.

 

git worktree add ../project-hotfix hotfix
git worktree list
git worktree remove ../project-hotfix

 

git worktree add <경로> <브랜치> 로 새 폴더에 브랜치를 펼치고, list 로 어디에 뭐가 깔렸는지 보고, 끝나면 remove 로 정리합니다. 한 가지 규칙은, 같은 브랜치를 두 워크트리에 동시에 체크아웃하는 건 깃이 막아준다는 점이에요. 실수로 main을 두 군데 펼치는 사고는 안 난다는 얘기입니다.

 

저는 폴더를 아예 셋으로 고정해두고 씁니다.

 

  1. 기능 개발용 (main 계열)
  2. 리뷰 확인용 (review)
  3. 핫픽스용 (hotfix)

 

각 폴더는 자기만의 build/, .gradle/ 디렉터리를 들고 있어서 빌드 캐시가 폴더별로 보존됩니다. 그러니까 핫픽스 폴더로 cd 한 번 하면 재빌드 없이 바로 작업이 이어져요. dev 서버 띄워둔 채로 건너가도 그대로 살아있고요. 처음 그 폴더를 만들 때 한 번만 콜드 빌드를 거치면, 그 다음부턴 전환 비용이 거의 0에 수렴합니다.

 

 

워크트리 디스크 용량과 IDE 인덱스 함정 3가지

좋은 점만 있으면 다들 진작 썼겠죠. 직접 굴려보니 미리 알았으면 했던 함정이 몇 개 있더라고요.

 

1. 첫 빌드는 무조건 콜드 스타트입니다

 

워크트리는 작업 디렉터리를 공유하지 않아요. node_modules, .next, build 같은 산출물이 폴더마다 따로 만들어집니다. 그래서 새 워크트리의 첫 빌드는 캐시가 하나도 없는 상태에서 출발해요. 콜드 빌드가 5분 넘게 걸리는 대형 프로젝트라면, 워크트리 만드는 비용이 오히려 더 클 수도 있습니다.

 

2. 디스크가 생각보다 빨리 찹니다

 

node_modules 가 2GB인 프로젝트에서 워크트리 5개를 만들면, 소스 빼고도 10GB가 추가로 깔립니다. 10GB가 어느 정도냐면, 고화질 영화 두세 편 분량이 그냥 빌드 산출물로 날아가는 셈이에요. 안드로이드 쪽도 워크트리당 1~2GB는 잡고 가야 합니다.

 

3. IDE 창을 따로 띄워야 인덱스가 유지됩니다

 

워크트리마다 별도의 안드로이드 스튜디오(Android Studio) 창을 쓰셔야 인덱스 캐시가 안 날아갑니다. 한 창에서 폴더만 휙휙 바꾸면 인덱싱을 다시 도는 일이 생기거든요. 그러면 워크트리 쓰는 의미가 절반은 사라지는 거죠.

 

다행히 의존성을 저장하는 Gradle 글로벌 캐시(~/.gradle/caches)는 모든 워크트리가 공유합니다. 그래서 라이브러리를 폴더마다 다시 받는 사고는 안 나요. 자바스크립트 쪽이라면 pnpm을 쓰면 비슷하게 해결되는데요. 의존성 파일을 한 곳에 모아두고 각 폴더엔 링크만 걸어주는 방식이라 디스크를 크게 아낄 수 있습니다. 단 브랜치 간 의존성 버전이 다르면 깨질 여지가 있는 편이에요.

 

 

워크트리 정리와 AI 에이전트 병렬 작업

끝난 워크트리는 OS의 rm 으로 폴더를 통째로 지우지 마세요. git worktree remove <경로> 로 지워야 .git 안에 메타데이터가 안 남습니다. 혹시 rm 으로 이미 지웠다면 git worktree prune 으로 찌꺼기를 청소하면 돼요.

 

그리고 욕심내서 워크트리를 잔뜩 만들어두면, 어느새 "이 작업이 어느 폴더였더라" 하는 새로운 머릿속 부담이 생깁니다. 전환 비용 없애려다 폴더 미로에 빠지는 거죠. 개인적으로는 3~4개 선에서 끊는 게 딱 좋았어요. 그 이상은 관리가 일이 됩니다.

 

요즘 새로 뜨는 쓰임새도 하나 있는데요. 격리된 워크트리마다 클로드 코드(Claude Code) 같은 AI 코딩 에이전트를 따로 띄워서, 파일 충돌 없이 동시에 여러 작업을 맡기는 방식이 주목받고 있다고 합니다. 폴더가 물리적으로 분리돼 있으니 에이전트끼리 서로의 파일을 건드릴 일이 없는 거예요. 이건 stash 로는 아예 흉내도 못 내는 그림이지요.

 

다만 모든 상황에 답은 아닙니다. 10분 안에 끝나는 간단한 수정이라면 그냥 git checkout 이 더 빠르고, 빌드가 워낙 가벼운 프로젝트면 굳이 폴더를 늘릴 이유가 없어요. 워크트리는 "콜드 빌드는 무겁고, 전환은 잦은" 상황에서 가장 빛납니다. 그러니 다음에 stash 걸고 빌드 막대 쳐다보며 13분을 흘려보내게 되면, 그때가 바로 핫픽스용 폴더 하나를 따로 펼쳐둘 타이밍이지 싶어요.

 

 

반응형
LIST