모노레포를 쪼갰다
worktree마다 쌓이는 빌드랑 1TB 디스크 때문에, 메인 레포는 참조만 남기고 작업할 레포만 받아서 쓰는 구조로 바꿨다.
지금까지는 앱, 웹, 백엔드, 문서까지 전부 모노레포 하나에 넣고 관리했다. 안드로이드 앱만 70개가 넘는다. 한 레포에 다 있으니까 클코한테 "이거 고쳐줘" 하면 어디든 다 보고 고칠 수 있어서 편했다.
문제는 세션이 늘어나면서부터였다. 요즘은 클코랑 코덱스 세션을 여러개 띄워놓고 일하는데, 세션마다 git worktree를 하나씩 쓴다. worktree 하나가 곧 레포 전체라서 빌드 결과물도 worktree마다 따로 쌓인다. Gradle이든 Xcode든 cargo든.
맥북 SSD는 1TB인데 생각보다 금방 찬다. 새 세션 시작할 때마다 체크아웃 기다리는 것도 점점 느려졌고..
그래서 이번에 쪼갰다. 메인 레포는 그냥 가볍게 레퍼런스만 갖고 있고, 작업할 때는 git worktree에 필요한 submodule 레포만 받아서 작업하는 형태로 만들었다. 안드로이드, iOS, Flutter, 웹, 백엔드 같은 그룹이 각자 레포가 되고, 앱 하나하나도 자기 레포를 갖는다. 메인 레포에 남은건 submodule 참조랑 문서, 스크립트, 에이전트 설정 정도.
그래도 내가 아는 레포는 여전히 메인 하나다. "OO 앱 고쳐줘" 하면 스크립트가 그 앱이 어느 레포에 있는지 찾아서 그것만 받아온다. 이슈도 메인 레포에서만 관리하고.
디스크는 작업 시작 전에 미리 잡아두게 했다. 남은 공간이 기준보다 적으면 새 작업을 안받는다. 테스트로 작업 10개를 한번에 넣어봤더니 4개만 들어가고 6개는 거절 ㅋㅋ 끝난 작업 85개 정리했을 땐 6GB 정도 돌아왔다.
처음엔 메인 레포가 각 레포의 특정 커밋을 고정해서 가리키게 했다 (submodule 기본 방식). 언제든 전체를 그 시점으로 되돌릴 수 있으니까 안전해 보였는데, 막상 써보니 너무 과했다. 10월 4일부터 9일까지 고정된 커밋을 최신으로 올리는 커밋만 93개. 세션끼리 그 업데이트 PR이 계속 충돌했고, 손으로 푼 머지만 283번이었다. 이 관리 스크립트 고치는 PR만 34개 ㅠㅠ
근데 그 고정된 스냅샷으로 빌드하거나 배포하는 데가 한 군데도 없었다. 그래서 다시 날리고 단순하게 바꿨다. 지금은 레포마다 자기 main이 기준이고, 고칠게 있으면 그 레포에 PR 하나 올리면 끝. 레포끼리 안맞아서 깨지는건 정해진 시간마다 전체 main을 모아서 한번에 검증하고, 실패하면 이슈 하나 열게 해뒀다.
마침 앤트로픽에서 소스 관리를 다시 설계한 글이 올라왔다. 하루 머지가 3만건이 넘어가면서 git이 병목이 됐다고. 거긴 모노레포를 그대로 두고, git이 데이터 저장하고 주고받는 부분을 자체 시스템으로 갈아끼웠다. 7명이서 5개월. 클라이언트는 필요한 파일만 그때그때 받아가는 구조다.
규모는 비교가 안되지만 고민은 비슷했다. 에이전트가 많아지니까 레포 전체를 다 들고 있는게 문제가 된거. VCS를 새로 만드는건 1인 개발 환경에서는 무리고, 생각도 안해봤다 ㅋㅋ
읽다가 반가웠던건 거기도 main이랑 릴리스 브랜치 말고는 ref를 되도록 안쓴다는 부분. 전역 상태가 많을수록 규모 키우기 어렵다는 이유였는데, 나도 커밋 고정 날리면서 비슷한 생각을 했어서.
엔지니어 일의 상당 부분이 Claude한테 "그건 안돼"라고 말하는 거였다는 얘기도 있었는데 ㅋㅋ 공감. 클코랑 같이 만들다보니 내 워크스페이스 스크립트도 테스트 빼고 만이천줄 가까이 된다. 커밋 고정은 날렸지만 아직 덜어낼게 더 있을거 같다.
남은건 공유 코드를 따로 버전 관리하는 작업. 이번엔 처음부터 너무 과하게 안가게 해야지 홍홍