goodchuck 블로그

AI 코딩 세션을 여러 개 돌리면 왜 꼬일까 — git worktree 로 폴더를 나누고 규칙으로 막은 것들

7분 읽기

저는 모노레포 하나에 앱을 여러 개 두고, Claude Code 세션도 여러 개 띄워 놓고 일합니다. 한 세션은 버튜버 서비스, 다른 세션은 내부 공용 서버, 또 다른 세션은 이 블로그를 맡는 식입니다.

세션을 늘리는 건 쉽습니다. 어려운 건 세션들이 서로의 작업을 밟지 않게 하는 일이었습니다. 결론부터 적으면 세 가지로 나눴습니다.

  • 폴더를 나눕니다. 작업마다 git worktree 를 하나씩 만듭니다.
  • 역할을 나눕니다. 앱마다 맡는 세션을 정하고, 앱 사이의 약속이 바뀌면 세션끼리 알립니다.
  • 권한을 나눕니다. 코드와 PR 까지는 AI 가, 머지와 운영 배포는 사람이 정합니다.

컨텍스트를 쌓는 글이 AI 한 명을 잘 일하게 하는 이야기였다면, 이 글은 여러 명을 같이 일하게 하는 이야기입니다.

왜 꼬이나 — 세션은 달라도 폴더는 하나

git 저장소를 하나만 받아 두면 작업 폴더도 하나입니다. 그 폴더에서 세션 둘이 동시에 일하면 이런 일이 생깁니다.

  • A 세션이 브랜치를 바꾸면, B 세션이 보던 파일이 통째로 바뀝니다.
  • A 세션이 고치다 만 파일이 B 세션의 빌드에 끼어듭니다.
  • 커밋할 때 남의 변경까지 같이 담기기 쉽습니다.

사람 둘이 한 노트북을 번갈아 쓰는 것과 같습니다. 제 메인 폴더(dev 브랜치)에도 다른 세션이 하던 미커밋 변경이 남아 있는 때가 있어서, 지금은 새 작업을 메인 폴더에서 시작하지 않습니다.

git worktree — 저장소 하나, 작업 폴더 여럿

git worktree 는 저장소를 다시 받지 않고 작업 폴더만 하나 더 만드는 git 기본 기능입니다. 커밋 기록은 함께 쓰고, 파일과 현재 브랜치는 폴더마다 따로입니다.

# origin/dev 에서 새 브랜치를 따서, 새 폴더에 꺼낸다
git worktree add .claude/worktrees/blog-post -b feat/blog-post origin/dev

# 지금 있는 워크트리 목록
git worktree list

# 다 쓴 워크트리 지우기
git worktree remove .claude/worktrees/blog-post

세션은 자기 폴더 안에서만 일합니다. 옆 세션이 브랜치를 바꾸든 빌드를 돌리든 영향을 받지 않습니다.

위치도 규칙으로 정했습니다

한번은 AI 가 ../wt-hub 처럼 저장소 바깥에 워크트리를 만들었는데, 다른 프로젝트처럼 보였습니다. 그 뒤로 위치를 규칙으로 적어 두었습니다.

  • 위치는 항상 저장소 안 .claude/worktrees/<이름>
  • 이 경로는 .gitignore 에 넣어 커밋에 섞이지 않게 함

이런 결정은 말로 끝내면 다음 세션이 모릅니다. 그래서 왜 그렇게 정했는지와 함께 파일로 남겨, 세션이 시작할 때 읽게 합니다.

워크트리로도 안 막히는 것 네 가지

폴더를 나눠도 함께 쓰는 것은 남습니다. 모르고 있으면 오히려 찾기 어려운 문제가 됩니다.

항목일어나는 일대응
git stash모든 워크트리가 스택 하나를 함께 씀임시 커밋을 쓰거나, 이름을 붙이고 SHA 로 꺼냄
브랜치같은 브랜치를 두 폴더에 동시에 꺼낼 수 없음작업마다 새 브랜치
.env · node_modulesgit 에 없어 새 폴더엔 없음폴더마다 설치, env 는 금고에서 받기
개발 서버 포트같은 앱을 두 폴더에서 띄우면 겹침앱마다 포트 고정, 한 앱은 한 세션

가장 조심할 것은 stash 입니다. 맨몸의 git stash pop 은 스택 맨 위를 꺼내는데, 그 맨 위가 옆 세션이 넣어 둔 변경일 수 있습니다. 내 작업을 치워 둘 때는 임시 커밋이 가장 안전하고, 꼭 stash 를 써야 하면 이렇게 합니다.

git stash push -u -m "blog-post-wip"     # 이름을 붙여 넣고
git stash list --format='%H %gs'         # 내 항목의 SHA 를 확인해서
git stash apply <SHA>                    # 번호가 아니라 SHA 로 꺼낸다

.env 는 비밀값이라 git 에 없습니다. 새 워크트리에는 없으니 앱이 뜨지 않습니다. 저는 S3 금고에 원본을 두고 받아 오는 명령을 만들어 둬서, 폴더가 늘어도 손으로 복사하지 않습니다.

세션 역할 나누기 — 앱마다 맡는 세션을 정한다

폴더만 나눠서는 같은 파일을 두 세션이 고치는 일을 막지 못합니다. 나중에 합칠 때 충돌로 돌아옵니다. 그래서 세션의 담당을 앱 단위로 정했습니다.

세션맡는 곳
chzzk 인프라내부 공용 서버
chzzk-vtuber오시레이더 웹 · API
chzzk-watcherFinisxh (별도 저장소)
블로그이 블로그

앱을 나누면 파일이 잘 겹치지 않습니다. 이 리포는 앱끼리 코드를 직접 import 하지 않는다는 규칙이 있어서 나누기가 더 쉬웠습니다. 다만 앱 사이의 약속은 남습니다. 공용 서버의 응답 모양이 바뀌면 쓰는 쪽도 알아야 합니다. 그래서 약속은 문서 한 곳에 두고, 바뀌면 세션끼리 메시지로 알리게 했습니다.

세션끼리 일을 넘기기

세션은 서로의 대화를 보지 못합니다. 그래서 필요한 내용만 골라 메시지로 보냅니다. 최근 블로그 세션에서 실제로 보낸 것은 이런 것들입니다.

  • Vercel 사용량을 분석해 보니 사용량 대부분이 오시레이더 쪽이어서, 분석 결과를 그 세션에 넘겼습니다.
  • 블로그에서 오시레이더로 가는 링크의 UTM 규칙을, 글을 내기 전에 그 세션과 맞췄습니다.
  • Finisxh 쪽 사용량은 문제가 없다는 것도 그 세션에 참고로 알렸습니다.

제가 양쪽 창을 오가며 옮겨 적지 않아도 됩니다. 다만 받은 내용은 그 세션의 보고일 뿐이라, 믿기 전에 실제 코드와 수치를 다시 확인해야 합니다.

머지와 배포는 사람이 — 두 번 데이고 만든 규칙

세션이 많아질수록 제가 모든 대화를 따라가기 어렵습니다. 이때 가장 위험한 건 코드가 아니라 되돌리기 어려운 행동이었습니다.

실제로 사고가 있었습니다. 10월 22일에 제가 글을 보고 "좋아, 이 정도로 해 보자"라고 했는데, AI 가 이걸 공개 승인으로 읽고 PR 을 머지하고 배포 태그까지 붙였습니다. 같은 날 다음 글에서는 "이대로 배포까지 하고 싶어"를 승인으로 읽어 또 머지했습니다.

그 뒤로 해석의 여지를 없애도록 경계를 규칙으로 정했습니다.

행동누가
코드 수정, 테스트, 빌드AI
PR 만들기AI (요청받았을 때 커밋)
PR 머지사람
운영 배포 태그사람이 매번 확인한 뒤

"배포하자"라고 해도 PR 까지만 올리고 멈춥니다. 제가 머지한 뒤에 태그를 붙입니다. 이 글도 같은 순서로 나갑니다.

비슷하게 배포 횟수도 사람이 관리해야 할 몫이었습니다. 세션이 PR 을 잘게 나눠 올리면 머지할 때마다 배포가 돌아, Vercel 배포 한도가 걱정이었습니다. 그래서 같은 앱의 연달은 작업은 열려 있는 PR 하나에 이어 쌓게 했습니다.

단점 — 폴더가 쌓인다

오늘 세어 보니 워크트리 폴더가 38개, 합계 30GB 였습니다. 폴더마다 설치한 의존성과 빌드 결과물 때문입니다.

폴더크기
블로그 (Next.js 빌드 포함)1.9GB
오시레이더 웹 작업 하나649MB
Python 서버 작업 하나67MB

"머지하고 배포한 뒤 자기 폴더를 지운다"는 규칙을 적어 두었는데도, 이 정도로 쌓였습니다. 10월 말에 머지된 작업의 폴더도 그대로 남아 있습니다. 임시 경로에 만들었다가 폴더만 사라져서, 목록에 기록만 남은 항목도 하나 있었습니다. 이런 기록은 git worktree prune 으로 지웁니다.

정리할 때도 조심할 점이 있습니다. 다른 세션이 아직 쓰는 폴더일 수 있으니, 세션은 자기 폴더만 지우게 했습니다. 다만 이 규칙은 아직 잘 지켜지지 않아서, 앞으로 고칠 부분입니다.

정리

충돌막는 방법
같은 폴더를 함께 씀작업마다 워크트리, 위치는 .claude/worktrees/
stash 가 섞임임시 커밋, 또는 이름 + SHA
새 폴더에 env 가 없음금고에서 받기
같은 파일을 함께 고침앱마다 맡는 세션
앱 사이의 약속이 어긋남문서 한 곳 + 세션 간 메시지
AI 가 승인을 넓게 해석머지 · 배포 태그는 사람
배포가 너무 잦음같은 앱은 PR 하나에
폴더가 쌓임끝나면 지우기 (아직 덜 지켜짐)

세션을 늘려서 실제로 얼마나 빨라졌는지는 재 보지 않았습니다. 분명한 건 세션이 늘수록 코드를 쓰는 일보다 경계를 정하는 일이 제 몫으로 남는다는 것입니다. 그리고 그 경계는 처음부터 설계했다기보다, 대부분 한 번씩 부딪히고 나서 파일에 적어 둔 것들입니다.