Published on

Git Worktree는 왜 필요할까? AI 에이전트와 여러 브랜치 동시 작업하기

Authors
  • 테크버킷
    Name
    테크버킷
    Twitter

목차

AI 에이전트로 코딩하기 시작하면서 Git worktree를 자주 사용하게 됐습니다. 예전에는 프로젝트 폴더 하나에서 브랜치를 바꿔가며 일했습니다.

지금은 로그인 기능, 결제 오류 수정, 문서 작업마다 브랜치와 폴더를 하나씩 만들고 여러 에이전트를 동시에 실행합니다.

처음에는 폴더까지 늘려야 하는 이유를 잘 몰랐습니다. 브랜치만 나누면 되는 것 아닌가? 저장소를 한 번 더 clone하는 것과 무엇이 다른가? 작업이 끝나면 폴더만 지워도 되는가?

이 질문들은 브랜치와 작업 폴더를 같은 것으로 생각할 때 생깁니다. 둘의 역할을 구분하면 worktree가 필요한 이유도 간단해집니다. 브랜치는 변경 이력을 나누고, worktree는 각 브랜치에서 실제로 일할 공간을 나눕니다.

배경: Worktree를 이해하려면 브랜치부터 알아야 한다

브랜치는 프로젝트의 복사본이 아니다

브랜치는 Git의 핵심 개념입니다. 흔히 브랜치를 프로젝트의 복사본처럼 생각하지만, 실제로는 특정 커밋을 가리키는 이름에 가깝습니다.

로그인 기능을 개발하기 위해 feature/login 브랜치를 만들었다고 해보겠습니다. 처음에는 main과 같은 커밋에서 출발하지만, 로그인 코드를 커밋할 때마다 feature/login이 가리키는 위치가 앞으로 이동합니다.

하나의 Git 커밋 흐름에서 브랜치가 갈라지고 선택한 브랜치의 파일이 작업 폴더에 펼쳐지는 구조

브랜치 자체가 소스 파일 전체를 따로 보관하는 것은 아닙니다. Git은 커밋과 브랜치의 관계를 저장하고, 선택한 브랜치의 파일을 작업 폴더에 펼쳐줍니다.

브랜치를 바꾸면 작업 폴더가 바뀐다

git switch feature/login

이 명령을 실행하면 현재 작업 폴더의 파일이 feature/login 브랜치 상태로 바뀝니다. 편집기에서 보는 코드와 개발 서버가 읽는 코드도 이 폴더의 상태를 따라갑니다.

브랜치는 여러 개 만들 수 있습니다. 하지만 작업 폴더가 하나라면 실제 파일로 펼쳐둘 수 있는 브랜치는 한 번에 하나뿐입니다.

브랜치는 이력을 가리키는 이름이고, 작업 폴더는 그 이력을 실제 파일로 열고 수정하는 공간이기 때문입니다.

과거: 한 폴더에서 브랜치를 바꿔가며 작업했다

사람이 한 번에 하나의 작업을 진행할 때는 하나의 프로젝트 폴더로 충분했습니다. 기능 하나를 끝내고 다음 기능으로 넘어가거나, 필요할 때 브랜치를 전환하는 방식이 자연스러웠습니다.

project/
└─ 현재 feature/login 브랜치의 파일

긴급 수정이 끼어들면 stash부터 필요하다

로그인 기능을 수정하던 중 결제 오류를 급히 고쳐야 한다고 해보겠습니다. 아직 커밋하기 어려운 변경이 남아 있다면 먼저 stash에 임시 보관하고 브랜치를 바꿉니다.

git stash push -m "로그인 작업 중"
git switch main
git switch -c fix/payment

git stash는 커밋하지 않은 변경을 Git 내부에 잠시 보관하고 작업 폴더를 깨끗한 상태로 되돌립니다. 덕분에 진행 중인 로그인 작업을 잃지 않고 main으로 이동한 뒤 결제 수정 브랜치를 만들 수 있습니다.

결제 오류를 고치고 나면 다시 로그인 브랜치로 돌아와 보관했던 작업을 꺼냅니다.

git switch feature/login
git stash pop

짧은 작업에는 이 방식이 여전히 간단하고 유용합니다. 불편은 두 작업의 상태를 동시에 유지하고 싶을 때 생깁니다.

파일뿐 아니라 작업 문맥도 바뀐다

브랜치를 바꾸면 같은 폴더의 파일이 교체됩니다. 로그인 화면을 띄워둔 개발 서버를 끄고, 편집기에서 열어둔 파일을 정리한 뒤 결제 브랜치에 맞춰 다시 실행해야 합니다.

작업을 마치면 이 과정을 반대로 반복합니다. stash가 여러 개 쌓이면 어떤 작업을 넣어뒀는지 다시 확인해야 할 때도 있습니다.

브랜치를 전환한다는 것은 단순히 이름 하나를 바꾸는 일이 아니었습니다. 코드와 편집기, 개발 서버와 테스트까지 한 작업에 맞춰 구성한 문맥을 접고 다른 작업의 문맥을 다시 만드는 일이었습니다.

현재: AI 에이전트는 여러 브랜치를 동시에 작업한다

AI 코딩 에이전트가 등장하면서 작업 방식이 달라졌습니다. 사람은 여전히 한 번에 하나의 코드를 자세히 검토하지만, 여러 에이전트에는 서로 독립된 작업을 동시에 맡길 수 있습니다.

예를 들어 한 에이전트가 로그인 기능을 구현하는 동안 다른 에이전트는 결제 오류를 고치고, 또 다른 에이전트는 API 문서를 작성할 수 있습니다.

브랜치만 여러 개 만드는 것으로는 부족하다

세 에이전트를 같은 프로젝트 폴더에서 실행할 수는 없습니다. 한 에이전트가 브랜치를 바꾸면 다른 에이전트가 읽고 있던 파일도 함께 바뀝니다.

같은 파일을 동시에 수정하면 한쪽 변경이 다른 쪽 변경을 덮어쓸 수도 있습니다.

브랜치만 세 개 만드는 것으로는 부족합니다. 각 에이전트가 명령을 실행하고 파일을 수정할 별도의 작업 폴더도 필요합니다. 이때 다시 주목받은 Git 기능이 worktree입니다.

오래된 Git 기능이 다시 주목받는 이유

Git worktree는 AI 시대에 새로 생긴 기능이 아닙니다. 오래전부터 Git에 있었지만, 한 사람이 한 폴더에서 한 작업을 진행하던 방식에서는 굳이 사용할 이유가 많지 않았습니다.

최근에는 AI 에이전트를 병렬로 실행하는 도구들이 에이전트마다 별도의 worktree와 브랜치를 제공하면서 쓰임이 넓어졌습니다.

GitHub도 AI로 인해 개발자가 이전보다 많은 세션을 병렬로 실행하게 됐다고 설명합니다. GitHub Copilot 앱에서 새 세션의 기본 실행 위치로 worktree를 제공하는 이유이기도 합니다.

자세한 배경은 GitHub의 worktree 설명에서 확인할 수 있습니다.

최근 글과 도구에서는 이를 worktree-per-agent, worktree 기반 병렬 개발처럼 표현합니다. 간혹 worktree-driven development라는 말도 보이지만, 아직 Git이 정의한 공식 방법론이나 널리 합의된 고유명사는 아닙니다.

핵심은 이름보다 하나의 작업 또는 에이전트에 하나의 브랜치와 worktree를 배정하는 방식입니다.

하나의 작업 폴더에서 브랜치를 번갈아 여는 기존 방식과 여러 에이전트가 각자 worktree에서 병렬 작업하는 방식 비교

Worktree는 브랜치마다 작업 폴더를 하나씩 만든다

Worktree를 사용하면 진행 중인 로그인 작업을 stash에 넣지 않아도 됩니다. 원래 폴더는 그대로 두고 결제 오류를 고칠 작업 폴더를 옆에 하나 더 만듭니다.

git worktree add -b fix/payment ../project-payment-fix main

명령 한 줄로 생기는 것

이 한 줄은 세 가지 일을 합니다.

  • ../project-payment-fix 위치에 새 작업 폴더를 만듭니다.
  • fix/payment이라는 새 브랜치를 만듭니다.
  • 새 브랜치는 main 커밋에서 시작합니다.

두 작업을 동시에 열어둔다

project 폴더에는 수정 중이던 로그인 파일이 그대로 남아 있습니다. project-payment-fix 폴더에는 main에서 시작한 결제 수정용 파일이 펼쳐집니다.

두 폴더를 각각 다른 편집기 창과 터미널에서 열면 한쪽의 작업 파일을 바꾸지 않고 다른 작업을 진행할 수 있습니다.

Git은 처음 clone하거나 init할 때 생긴 공간을 main worktree, git worktree add로 추가한 공간을 linked worktree라고 부릅니다.

Worktree는 브랜치를 대체하지 않습니다. 브랜치가 무엇을 작업하고 있는지 기록한다면, worktree는 그 브랜치에서 실제로 작업할 장소를 제공합니다.

두 번째 clone과는 무엇이 다른가

프로젝트를 두 번 clone해도 서로 다른 브랜치를 동시에 열 수 있습니다. 겉으로 보면 worktree도 프로젝트 폴더를 하나 더 만들기 때문에 비슷해 보입니다.

Clone은 독립된 저장소를 하나 더 만든다

차이는 Git 데이터를 공유하는지에 있습니다. 두 번 clone하면 각각의 폴더가 커밋 객체, 브랜치와 원격 저장소 설정을 가진 독립된 Git 저장소가 됩니다.

한 clone에서 만든 로컬 커밋을 다른 clone에서 보려면 원격 저장소를 거쳐 push하고 fetch해야 합니다.

Worktree는 하나의 저장소를 공유한다

Worktree는 하나의 저장소에 연결됩니다. 커밋과 브랜치 데이터는 공유하고, 실제 작업 파일만 폴더별로 나눕니다.

한 worktree에서 만든 커밋은 다른 worktree에서도 바로 찾을 수 있습니다. 별도의 전체 clone보다 Git 데이터가 중복되지 않고, 새 작업 폴더도 빠르게 만들 수 있습니다.

반대로 저장소 데이터를 공유한다는 점도 기억해야 합니다. 한 worktree에서 만든 브랜치와 커밋은 다른 worktree에서도 보입니다. 브랜치 이름 변경이나 삭제처럼 저장소 전체에 영향을 주는 작업도 모든 worktree에 연결됩니다.

직접 만들어보기

처음에는 새 worktree를 하나 만들고, 목록을 확인한 뒤, 작업이 끝나면 제거하는 흐름만 익히면 충분합니다.

1. 새 브랜치와 worktree 만들기

현재 main을 기준으로 새 브랜치와 작업 폴더를 함께 만들려면 다음 명령을 사용합니다.

git worktree add -b feature/example ../project-example main

원격 저장소의 최신 main에서 시작하고 싶다면 먼저 변경 내용을 가져오고 origin/main을 기준으로 지정합니다.

git fetch origin
git worktree add -b feature/example ../project-example origin/main

새 폴더는 현재 저장소의 바깥에 두는 편이 관리하기 쉽습니다. 저장소 안에 만들면 그 폴더가 원래 저장소의 추적 대상에 들어가지 않도록 .gitignore도 신경 써야 합니다.

2. 기존 브랜치를 worktree로 열기

이미 존재하는 브랜치는 -b 없이 작업 폴더에 연결합니다.

git worktree add ../project-review feature/review

Git은 같은 로컬 브랜치를 두 worktree에 동시에 체크아웃하지 못하게 막습니다. 같은 브랜치를 두 폴더에서 서로 다르게 커밋하면 브랜치가 어느 상태를 가리켜야 하는지 혼란스러워질 수 있기 때문입니다.

따라서 worktree마다 별도의 브랜치를 사용해야 합니다.

3. 연결된 worktree 확인하기

현재 저장소에 연결된 worktree는 다음 명령으로 확인합니다.

git worktree list

명령을 실행하면 각 worktree의 경로와 현재 커밋, 체크아웃된 브랜치가 표시됩니다.

/workspace/project          a1b2c3d [feature/login]
/workspace/project-example  e4f5g6h [feature/example]

각 worktree 안에서는 평소와 똑같이 파일을 수정하고 커밋하고 push합니다. GitHub에서 Pull Request를 만들고 merge하는 방식도 달라지지 않습니다.

AI 에이전트와 함께 사용하는 방식

에이전트가 아니라 작업을 기준으로 나눈다

AI 에이전트를 병렬로 실행할 때는 작업마다 worktree를 하나씩 만듭니다. 여기서 중요한 단위는 에이전트의 종류가 아니라 작업입니다.

하나의 작업에 하나의 브랜치와 worktree를 주면 어떤 에이전트를 사용하더라도 변경 범위를 확인하기 쉽습니다.

각 에이전트는 자신의 폴더 안에서 파일을 읽고 수정하고 테스트합니다. 작업 중에는 서로의 파일을 덮어쓰지 않으며, 결과는 각 브랜치의 diff로 남습니다.

같은 문제의 결과를 비교할 수도 있다

같은 문제를 두 에이전트에 맡겨 결과를 비교할 수도 있습니다. Codex와 Claude Code가 각각 로그인 오류를 수정하도록 한 뒤, 두 worktree에서 테스트를 실행하고 diff를 비교합니다.

더 적합한 결과만 선택해 merge하거나 필요한 커밋만 가져올 수 있습니다.

Orca는 작업 폴더와 주변 도구를 함께 묶는다

Orca는 이 작업 흐름을 화면에서 관리하는 도구입니다. 작업을 만들면 실제 Git worktree와 브랜치를 만들고, 해당 worktree에 에이전트 터미널, 편집기, 브라우저와 diff를 연결합니다.

명령줄에서 따로 관리하던 폴더와 도구를 하나의 작업 단위로 묶는 방식입니다.

Orca 안에서 만든 공간도 실제 Git worktree입니다. 터미널에서 평소처럼 git status, git commit, git rebase를 사용할 수 있습니다.

사용하기 전에 알아둘 주의사항

의존성과 환경 변수는 자동으로 복사되지 않는다

새 worktree에는 Git이 추적하는 파일만 펼쳐집니다. 일반적으로 Git에서 제외하는 node_modules, 빌드 캐시와 .env 파일은 자동으로 생기지 않습니다.

따라서 worktree를 만든 뒤에는 프로젝트에 맞는 의존성을 설치하고 로컬 환경 변수를 준비해야 합니다. Worktree마다 의존성을 설치하면 디스크 사용량도 늘어납니다.

운영용 비밀 정보가 포함된 .env를 무조건 복사하기보다 해당 작업에 필요한 개발용 값만 준비하는 것이 안전합니다.

포트와 데이터베이스는 별도로 관리해야 한다

Worktree는 코드 폴더를 나누지만 실행 환경 전체를 자동으로 격리하지는 않습니다. 두 worktree에서 웹 앱을 동시에 실행한다면 3000, 3001처럼 서로 다른 포트를 사용해야 합니다.

같은 데이터베이스를 바라보면 한쪽 작업이 만든 데이터가 다른 쪽에서도 보입니다. 테스트 데이터가 서로 영향을 주면 worktree별 데이터베이스나 스키마를 준비해야 할 수도 있습니다.

Merge conflict는 여전히 발생한다

작업 폴더를 나누면 두 에이전트가 개발 중에 같은 파일을 덮어쓰는 문제는 줄어듭니다. 하지만 두 브랜치가 같은 코드를 수정했다면 최종적으로 merge할 때 충돌이 발생할 수 있습니다.

Worktree는 병렬 작업을 가능하게 하는 도구이지, 여러 변경을 자동으로 통합하는 도구는 아닙니다. 서로 관련이 적은 작업을 나눌수록 효과가 크고, 같은 파일을 크게 수정하는 작업을 동시에 맡기면 나중에 검토와 통합 비용이 커집니다.

보안 샌드박스는 아니다

AI 에이전트를 다른 worktree에서 실행해도 운영체제의 파일 권한과 네트워크 접근까지 격리되지는 않습니다. Worktree 밖의 파일을 읽거나 시스템 명령을 실행할 수 있는지는 에이전트 권한과 실행 환경에 따라 달라집니다.

중요한 환경 변수, 운영 데이터와 실행 권한은 별도로 관리해야 합니다. 더 강한 격리가 필요하다면 컨테이너나 가상 머신 같은 별도의 실행 환경이 필요합니다.

Worktree가 분리하는 범위는 코드 작업 폴더까지입니다. Git의 커밋과 브랜치는 공유되고, 포트·데이터베이스·환경 변수 같은 실행 환경은 사용자가 별도로 나눠야 합니다.

하나의 Git 저장소가 세 worktree와 커밋 데이터를 공유하고 포트와 데이터베이스 등은 별도로 관리하는 구조

작업이 끝난 worktree 정리하기

1. 남은 변경 확인하기

제거하기 전에 해당 worktree에 커밋하지 않은 변경이 남아 있는지 확인합니다.

git -C ../project-example status

필요한 변경이 있다면 먼저 커밋하고 push합니다.

2. Worktree 제거하기

상태가 깨끗한 것을 확인했다면 worktree를 제거합니다.

git worktree remove ../project-example

커밋하지 않은 변경이 남아 있으면 Git은 일반적으로 제거를 거부합니다. --force로 강제할 수 있지만, 먼저 필요한 파일이 없는지 확인해야 합니다.

Worktree 제거와 브랜치 삭제는 별개입니다. 위 명령은 작업 폴더와 연결 정보를 정리하지만 feature/example 브랜치는 남깁니다.

작업 장소를 지운다고 커밋 이력까지 자동으로 삭제하지 않는 것입니다.

3. 필요하면 브랜치도 삭제하기

병합이 끝나 브랜치도 필요 없다면 따로 삭제합니다.

git branch -d feature/example

4. 폴더를 먼저 지웠다면 연결 정보 정리하기

파일 탐색기에서 worktree 폴더를 먼저 지웠다면 Git에 연결 정보가 남을 수 있습니다. 이때는 다음 명령으로 더 이상 존재하지 않는 worktree의 관리 정보를 정리합니다.

git worktree prune

가능하면 폴더를 직접 삭제하기보다 git worktree remove를 사용하는 편이 안전합니다.

모든 작업에 worktree가 필요한 것은 아니다

Worktree가 잘 맞는 상황

오탈자 수정이나 금방 끝나는 작은 변경이라면 브랜치를 한 번 전환하는 편이 더 단순합니다. Worktree마다 폴더, 의존성, 포트와 실행 상태를 관리하는 것도 비용이기 때문입니다.

반대로 다음 상황에서는 worktree가 유용합니다.

  • 끝나지 않은 작업을 그대로 둔 채 긴급 수정을 해야 할 때
  • 두 브랜치의 앱을 동시에 실행하거나 비교할 때
  • 오래 걸리는 테스트와 다른 개발 작업을 함께 진행할 때
  • 서로 독립된 작업을 여러 AI 에이전트에 맡길 때
  • 같은 요구사항을 여러 방식으로 구현해 결과를 비교할 때

판단 기준은 작업 문맥의 개수다

판단 기준은 간단합니다.

지금 동시에 유지해야 할 작업 문맥이 둘 이상인가?

그렇다면 worktree를 고려할 수 있습니다. 한 번에 하나의 작업만 한다면 기존의 git switch와 stash로도 충분합니다.

과거에는 브랜치를 바꿔가며 일하는 것이 자연스러웠습니다. 이제는 한 사람이 여러 AI 에이전트에 일을 나눠주고, 완료된 결과를 검토하는 시간이 늘고 있습니다. 이때 브랜치만 나누는 것으로는 부족합니다. 각 작업이 머무를 폴더도 필요합니다.

Worktree는 새로운 개발 방법론이라기보다 이 오래된 문제를 해결하는 작은 Git 도구입니다.

다만 한 작업에 하나의 브랜치와 하나의 작업 폴더를 배정한다는 단순한 원칙이 지금의 병렬 개발 방식과 잘 맞습니다.

직접 시작할 때는 worktree 하나만 추가해 기존 작업을 그대로 둔 채 다른 브랜치를 열어보는 것으로 충분합니다.

참고 자료