모노레포 vs 폴리레포와 AI 코딩 어시스턴트
요약
본 가이드는 AI 코딩 어시스턴트 관점에서 Monorepo와 Polyrepo 두 가지 코드 구성 방식을 비교 분석합니다. 각 방식의 장단점과 트레이드오프를 제시하며, 팀이 어떤 구조를 선택할지 고민하는 데 도움을 줍니다. 궁극적으로는 특정 구조보다 명확한 소유권과 접근 규칙 유지가 중요함을 강조합니다.
핵심 포인트
- AI 어시스턴트의 성능은 코드 구성 방식에 영향을 받습니다.
- Monorepo는 모든 코드가 한 곳에 있어 검색이 용이하지만, 느려지거나 의존성 관리가 어려울 수 있습니다.
- Polyrepo는 독립적이지만, 공유되는 부분을 관리하고 일관성을 유지하는 데 노력이 필요합니다.
- 어떤 구조든 명확한 소유권과 접근 규칙을 확립하는 것이 가장 중요합니다.
서론
AI 어시스턴트는 이제 매일 코드 작성과 변경을 돕습니다. 어시스턴트는 자신이 볼 수 있는 것만으로 작동할 수밖에 없는데, 이는 간단한 질문을 제기합니다. 즉, 팀이 코드를 구성하는 방식이 어시스턴트가 얼마나 잘 도움을 줄 수 있는지에 영향을 미칠까요?
코드를 구성하는 일반적인 방법은 두 가지가 있으며, 역량 있는 팀들은 이 둘 모두를 사용합니다. 본 가이드에서는 이를 쉬운 말로 설명하고, 선택에 대해 생각할 방법을 제시하며, 팀 스스로 시도해 볼 수 있는 간단한 테스트를 제안합니다. 어느 한쪽 방식을 선호하지는 않습니다.
출처. 이것은 제가 지금까지 읽고 경험한 내용을 바탕으로 작성한 메모입니다. 최종 답변이라기보다는 시작점으로 간주해 주시기 바랍니다.
1. 코드를 구성하는 두 가지 방식
- Monorepo (하나의 공유 공간): 여러 프로젝트의 코드가 함께 존재하며, 이들이 의존하는 공유 부분도 포함됩니다.
- Polyrepo (분리된 공간): 각 프로젝트 또는 팀이 자신의 코드와 그 역사를 독립적인 공간에 보관하며, 접근 권한에 대한 자체 규칙을 가집니다.
폴리레포에서는 일반적으로 프로젝트가 공유되는 모든 부분의 게시된 버전을 사용합니다. 이는 마치 다른 팀에서 완성된 제품을 사용하는 것과 같습니다. 많은 조직들은 이 두 가지를 혼합하여 사용하는데, 예를 들어 비즈니스 영역별로 하나의 모노레포를 두고 공유 라이브러리는 별도의 저장소에 보관하는 방식입니다.
실선 화살표는 직접적인 사용을, 점선 화살표는 게시된 버전을 통한 사용을 나타냅니다.
2. 한눈에 보는 일반적인 트레이드오프
| 주제 | 하나의 공유 공간 | 분리된 공간 |
|---|---|---|
| 코드 찾기 | 검색할 곳이 하나임 | 여러 곳에 걸쳐 검색해야 하며 추가 도구가 필요할 수 있음 |
| ... |
좋은 도구는 구조만큼이나 중요합니다. 잘 지원되는 폴리레포가 소홀히 관리된 모노레포보다 나을 수 있으며, 그 반대도 마찬가지입니다.
3. 어떤 설정이든 건강하게 유지하기
어느 쪽 설정도 스스로 건강하게 유지되지는 않습니다. 각각 고유의 실패 패턴을 가지고 있으며, 몇 가지 알아볼 수 있는 징후로 나타납니다.
| 문제가 발생하는 경우 | 조치가 필요하다는 신호 | |
|---|---|---|
| 모노레포(Monorepo) | 프로젝트 간 불필요한 연결이 쌓여서, 사소한 변경에도 예상보다 많은 부분이 영향을 받고 검사 속도가 느려집니다. | 검색하거나 빌드하는 데 눈에 띄게 느려졌습니다; 한 번의 변경이 관련 없는 팀까지 계속 끌어들입니다. |
| 폴리레포(Polyrepo) | 수정 사항이 일부 프로젝트에는 도달하지만 다른 프로젝트에는 도달하지 못하고, 팀 간 습관이 흐트러집니다. | 동일한 수정 사항이 여러 곳에서 반복됩니다; 팀들이 서로의 릴리스를 기다립니다. |
어느 쪽이든, 공유되는 부분을 포함하여 모든 부분에 대한 명확한 소유권은 이러한 문제 대부분을 방지합니다. 누가 무엇을 볼 수 있는지와 같은 접근 규칙의 변경 또한 이 선택을 재검토해야 하는 이유가 됩니다.
4. 도움이 되는 경험칙: 함께 변경되는 것은 함께 유지하라
단일 변경 사항이 경계를 가로질러 얼마나 자주 이동해야 하는지 살펴보세요. 만약 두 프로젝트가 보통 함께 변경된다면, 그것들을 같은 곳에 두는 것이 조정(coordination)을 줄여줍니다. 만약 그들이 거의 함께 변경되지 않거나, 접근 또는 소유권상의 이유로 분리되어야 한다면, 별도의 장소가 더 적합합니다.
팀 구조 역시 코드 구조를 형성하므로, 이 둘을 일치시키는 것이 도움이 됩니다.
5. AI 어시스턴트가 관심을 가질 수 있는 이유
공유되는 부분을 업데이트하고 그것을 사용하는 모든 것을 업데이트하는 도움을 요청한다고 상상해 보세요. 모노레포에서는 변경이 한 곳에서 일어나고 하나의 검토를 거칩니다. 폴리레포에서는 공유 부분이 먼저 변경되고, 새로운 버전이 게시된 다음, 이를 사용하는 각 프로젝트가 하나씩 순차적으로 업데이트되며, 각각 고유의 검토와 검사를 거칩니다.
폴리레포 경로는 게시 단계와 프로젝트당 하나의 검사를 추가합니다.
풀 리퀘스트(pull request)란 누군가에게 승인되기 전에 검토하는 변경 사항을 의미합니다. 폴리레포(polyrepo) 방식은 이러한 풀 리퀘스트의 수가 더 많다는 것을 의미하며, 이는 수정 및 검토 노력의 추가적인 단계를 발생시킬 수 있습니다. 실제 설정은 다양하며, 도구들이 이 긴 과정을 단축할 수 있습니다.
여기서 테스트해 볼 만한 아이디어가 하나 있습니다: 관련 정보는 어시스턴트에게 도움이 되는 경향이 있지만, 너무 많은 양의 정보는 신뢰도를 떨어뜨릴 수 있습니다. 가장 많은 정보보다 적절한 정보가 더 중요할 수 있습니다. 다음 두 섹션에서는 이를 실제 사례를 통해 살펴보겠습니다.
6. 실습 예시
과제: customer_name이라는 필드를 full_name으로 변경해야 합니다. 이 필드는 공유 데이터 정의에 나타나며, 웹 앱, 모바일 앱, 백엔드 서비스의 세 가지 곳에서 사용됩니다.
모노레포(monorepo) 방식일 경우
- 어시스턴트가 한 곳을 검색하여 공유 정의와 세 사용자 모두를 찾습니다.
- 네 군데 모두를 한 번에 변경하고 영향을 받는 부분에 대한 검사를 실행합니다.
- 하나의 풀 리퀘스트로 모든 것을 처리할 수 있습니다.
잘못될 수 있는 점: 이 풀 리퀘스트가 여러 팀의 코드를 건드리므로, 여러 명의 검토자가 필요하며, 한 가지 실수가 세 앱 모두를 동시에 망가뜨릴 수 있습니다.
폴리레포(polyrepo) 방식일 경우
- 어시스턴트가 자체 리포지토리에서 공유 정의를 변경하고 새로운 버전을 게시합니다.
- 세 프로젝트 각각이 자체 업데이트, 자체 풀 리퀘스트, 그리고 자체 검사를 거쳐야 합니다.
- 만약 어시스턴트가 하나의 리포지토리만 볼 수 있다면, 어떤 다른 곳들이 이 필드를 사용하는지 알 수 없습니다. 첫 번째 단계를 완료하고 멈출 수도 있습니다.
잘못될 수 있는 점: 한 프로젝트가 누락되어 이전 버전에 머물고, 세 가지 업데이트가 서로 다른 시점에 적용될 수 있습니다.
두 방식 모두 공통점: 모든 것을 한 번에 이름을 변경하는 것은 어느 쪽이든 위험합니다. 더 안전한 방법은 새 필드를 추가하고, 각 사용자를 그곳으로 옮긴 다음, 기존의 필드를 제거하는 것입니다. 이 순서가 리포지토리 구조보다 더 중요합니다.
각 방식에서 도움이 되는 것
- Monorepo: 영향을 받은 검사만 실행하는 도구와 각 폴더의 소유권을 명시하는 파일 이름 지정 방식을 사용하며, 적절한 사람이 리뷰하도록 합니다.
- Polyrepo: 업데이트된 풀 리퀘스트(pull requests)를 자동으로 여는 봇과 공유 정의가 각 프로젝트가 예상하는 것과 여전히 일치하는지 확인하는 테스트, 그리고 어떤 프로젝트가 어떤 공유 부분을 사용하는지에 대한 명시적인 지도가 필요합니다. 어시스턴트에게 여러 레포지토리(repos)를 나란히 체크아웃한 작업 공간을 제공하는 것도 도움이 됩니다.
7. AI 어시스턴트가 코드를 실제로 처리하는 방식
섹션 5에서는 어시스턴트가 '무엇을 볼 수 있는지'에 대해 이야기했습니다. 그 배후의 메커니즘이 어떤 레이아웃이 얼마나 잘 작동할지 결정합니다.
1. 제한된 양만 읽습니다. 어시스턴트는 한 번에 처리할 수 있는 텍스트 양에 한계가 있습니다. 이 한계를 종종 컨텍스트 윈도우(context window)라고 부릅니다. 대규모 코드베이스 전체를 담을 수는 없기 때문에, 어시스턴트는 무엇을 읽을지 선택해야 합니다. 이는 두 레이아웃 모두에서 사실입니다. 모노레포가 '모두 보이는' 것은 아니며, 폴리레포가 '숨겨진' 것도 아닙니다. 진정한 질문은 어시스턴트가 적절한 몇몇 파일을 얼마나 잘 찾아내느냐 하는 것입니다.
2. 검색을 통해 코드를 찾습니다. 대부분의 어시스턴트는 개발자가 검색하는 방식과 유사하게 작동합니다. 즉, 이름과 텍스트를 찾고, 일치하는 파일을 열어 참조 관계를 따라갑니다. 일부 도구는 의미로 코드를 찾거나 조각들이 어떻게 연결되는지에 대한 지도를 제공하는 인덱스를 추가합니다.
- 모노레포의 경우, 하나의 검색으로 모든 것을 커버할 수 있지만, 코드가 커짐에 따라 결과가 노이즈(noisy)가 될 수 있습니다. 좋은 폴더 구조와 명확한 이름 지정이 큰 도움이 됩니다.
- 폴리레포의 경우, 검색은 어시스턴트가 열어둔 레포지토리만 다룹니다. 추가적인 설정 없이는 다른 곳에서 누가 공유 부분을 사용하는지 알 수 없습니다.
3. 명시된 지침을 따릅니다. 많은 어시스턴트는 코드와 함께 보관되는 평문(plain text)의 지침 파일, 예를 들어 테스트를 실행하는 방법, 무언가를 이름 짓는 방법, 피해야 할 것 등에 대한 내용을 읽습니다. 일반적인 예로는 CLAUDE.md나 AGENTS.md 같은 파일이 있지만, 이름은 도구마다 다르므로 사용 중인 도구의 최신 문서를 확인해야 합니다.
- 모노레포(monorepo)의 경우, 팀은 공유된 규칙을 위한 최상위 파일 하나와 각 프로젝트 내에 로컬 규칙을 위한 작은 파일을 유지할 수 있습니다.
- 폴리레포(polyrepo)의 경우, 각 레포지토리마다 자체 파일이 필요하며, 이 파일들이 서로 달라질 수 있습니다. 공통 템플릿이나 공통 규칙을 가리키는 짧은 메모가 이를 일치시킵니다.
4. 여러 레포에 걸친 도달 범위는 설정에 따라 다릅니다. 기본적으로 많은 어시스턴트는 하나의 레포 내부에서 작동합니다. 여러 곳에 걸쳐 발생하는 변경 사항을 처리하려면, 팀들은 보통 다음 중 하나를 수행합니다:
- 관련된 레포지토리들을 나란히 체크아웃하여 하나의 작업 공간에서 함께 엽니다.
- 레포 전반에 걸쳐 검색할 수 있는 도구를 어시스턴트에게 제공합니다.
- 어떤 프로젝트가 어떤 프로젝트에 의존하는지에 대한 짧은 서면 지도를 유지합니다.
이는 한 번의 변경이 여러 곳에 영향을 미쳐야 하는 작업 예시에서 가장 중요합니다.
5. 접근 권한 역시 안전 문제입니다. 어시스턴트는 일반적으로 접근 권한을 받은 모든 내용을 읽고, 때로는 수정할 수 있습니다. 모노레포는 기본적으로 태스크와 관련 없는 코드까지 포함하여 광범위한 도달 범위를 제공할 수 있습니다. 개별 레포지토리는 필요한 곳에만 접근 권한을 부여하기 쉽게 만듭니다. 어느 쪽이든, 어시스턴트가 수정할 수 있는 내용을 제한하고, 태스크에 필요한 관련 코드만 제공하며 그 이상은 주지 않도록 하고, 승인되기 전에 모든 변경 사항을 사람이 검토하도록 합니다.
실제 적용 시 의미하는 바. 어떤 레이아웃도 자체적으로 우수하지 않습니다. 어시스턴트는 관련 코드를 빠르게 찾고, 명확한 서면 지침을 읽으며, 빠른 검사를 실행할 수 있을 때 가장 잘 작동합니다. 모노레포는 기본적으로 첫 번째(관련 코드 검색)를 더 쉽게 만듭니다. 폴리레포는 기본적으로 두 번째(제한된 접근 권한)를 더 쉽게 만듭니다. 각 방식 모두 위의 도구링을 통해 개선될 수 있습니다.
8. 어느 설정에도 적용 가능한 실질적인 아이디어
- 자동 검사를 빠르고 쉽게 실행할 수 있도록 하여, 어시스턴트가 빠르게 피드백을 받게 합니다.
- 사람이 검토하기에 충분히 작은 변경 사항을 유지합니다.
- 여러 곳에 걸쳐 발생하는 변경 사항이 어떻게 조정될지 사전에 결정합니다.
9. 명세서(spec)를 먼저 작성하기
명세(spec)란 기능이 무엇을 해야 하는지 그리고 어떻게 검증할 수 있는지에 대한 짧은 서면 설명입니다. 어시스턴트는 이를 기반으로 구축합니다. 이는 두 레이아웃 모두에서 도움이 되며, 단위는 풀 리퀘스트가 아니라 기능 자체입니다. 즉, 하나의 명세로 여러 개의 작은 풀 리퀘스트들이 연결됩니다.
각 설정별 역할
- 모노레포(Monorepo): 여러 단계의 변경 사항을 풀 리퀘스트 전반에 걸쳐 일관되게 유지하고 검토자에게 하나의 참조점을 제공합니다.
- 폴리레포(Polyrepo): 조정 지점 역할을 합니다. 영향을 받는 저장소 목록, 단계 순서, 그리고 각 저장소별 작업을 나열하여 공유된 뷰가 없는 간극을 채웁니다. API 스키마나 데이터 정의와 같이 기계가 확인할 수 있는 명세는 각 저장소의 검사가 여전히 일치하는지 확인하도록 합니다.
실제 예시에서는 하나의 명세에 'full_name 추가, 모든 프로젝트 이동, customer_name 제거'라는 내용과 함께 각 저장소별 작업이 포함되어 있습니다.
보관 위치. 모노레포: 공유되는 부분 옆. 폴리레포: 공유되는 부분의 저장소 내부 또는 각 작업에서 링크된 작은 명세 전용 저장소에 보관합니다.
한계점
- 명세가 구식이 될 수 있습니다. 소유자를 지정하고, 각 작업 옆에 간략한 상태를 유지하며, 기능이 배포되면 폐기해야 합니다.
- 작은 변경 사항에는 비용이 절감하는 것보다 더 클 수 있습니다.
- 이는 어시스턴트에게 무엇을 구축할지 알려줄 뿐이며, 빠르고 자동화된 검사가 실제로 작동했는지 여부를 결정합니다.
- 어시스턴트 결과를 개선한다는 증거는 아직 미미하며, 섹션 10에서는 현재 알려진 내용과 테스트 방법을 다룹니다.
10. 우리가 아는 것, 그리고 팀이 알아낼 수 있는 방법
AI 어시스턴트가 하나의 공유된 장소에서 작동하는 것과 분리된 여러 곳에서 작동하는 것을 신중하고 측정적으로 비교한 사례는 여전히 제한적입니다. 오늘날의 대부분의 사고방식은 추론과 일상적인 관행에 의존하고 있으며, 이는 유용하지만, 측정된 결과가 많이 추가될 것입니다. 여기 간단하게 결과를 도출할 수 있는 방법이 있습니다.
여러 프로젝트에 영향을 미치는 현실적인 변경 사항을 선택해 보세요. 예를 들어 소프트웨어의 많은 부분이 사용하는 필드 이름을 변경하는 경우입니다. 다른 모든 것을 동일하게 유지하면서 두 설정 모두에서 같은 작업을 시도해 보세요:
같은 AI 어시스턴트와 같은 지침을 사용하고,
팀의 습관과 규칙을 보여주는 방식도 동일하며,
결과가 작동하는지 확인하기 위한 자동 검사(automatic checks) 역시 동일합니다.
여러 번 시도해야 하는데, 결과는 실행마다 다르기 때문입니다.
선택적 추가 변수: 기능별 명세서(spec)(섹션 9)를 작성하여 한 번 변경을 실행하고, 그렇지 않은 경우에 다시 한번 실행한 후, 아래의 동일한 측정 항목들을 비교합니다.
그다음 다음 내용을 기록합니다:
| 기록할 내용 | 일반적인 말로 표현하면 |
|---|---|
| 검사를 통과하기까지 수정 라운드 횟수 | 얼마나 많은 주고받음이 필요했는지 |
| ... |
또한 어시스턴트가 어떻게 설정되었는지도 기록해야 합니다. 왜냐하면 그것이 레이아웃만큼 결과에 영향을 미칠 수 있기 때문입니다.
어떤 설정을 선택하든, 좋은 도구와 명확한 습관이 레이아웃만큼 중요할 가능성이 높습니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기
