AI 시대의 아키텍처 다시 생각하기 — 파트 1: 저장소 관리
Source: Dev.to
위 링크에 포함된 전체 텍스트를 제공해 주시면, 해당 내용을 한국어로 번역해 드리겠습니다. (코드 블록, URL 및 마크다운 형식은 그대로 유지됩니다.)
Repository Management – 모노레포가 합리적인 이유
AI가 프로토타이핑을 얼마나 빠르게 가속화할 수 있는지에 대한 내용은 부족하지 않지만, 중기적인 유지보수성도 동일하게 주목받아야 합니다.
(이 글이 일회성 기사로 끝난다면, 미리 사과드립니다.)
앞서 말한 결론
모노레포를 선택하세요.
모노레포란 무엇인가?
모노레포는 여러 애플리케이션을 하나의 저장소에서 관리하는 방식을 말합니다. “여러 앱”은 다음 중 하나를 의미할 수 있습니다:
- 프론트엔드와 백엔드가 함께 존재하는 경우
- 서비스 A와 서비스 B의 풀스택 앱이 나란히 배치된 경우
- 애플리케이션 코드와 공유 라이브러리가 함께 있는 경우
마이크로서비스에 대한 간단한 부연
모노레포가 마이크로서비스 맥락에서 종종 논의되지만, 저는 두 방식을 동시에 적용해 본 실무 경험이 없으므로 여기서는 다루지 않겠습니다. 제 직감으로는 모노레포를 최대한 활용하려면 기술 스택을 어느 정도 통일된 상태로 유지해야 하는데, 이는 마이크로서비스가 추구하는 목표와 어느 정도 충돌할 수 있습니다. 제가 설명하는 모노레포 스타일은 마이크로서비스와는 잘 맞지 않을 가능성이 높습니다.
실용적인 답변: Turborepo
Turborepo는 TypeScript 프로젝트에서 모노레포 설정의 사실상 표준이 되었습니다. 비록 기술적으로는 범용 빌드 도구로 포지셔닝되어 있지만, 실제로는 모노레포를 도입할 때(또는 더 스마트한 빌드 캐싱을 원할 때) 사용하게 됩니다.
대표적인 디렉터리 구조 (웹 프론트엔드 + 백엔드)
my-turborepo/
├── apps/
│ ├── web/ # Frontend app (e.g. Next.js)
│ │ ├── src/
│ │ ├── package.json
│ │ └── tsconfig.json
│ └── api/ # Backend app (e.g. Hono, Express)
│ ├── src/
│ ├── package.json
│ └── tsconfig.json
├── packages/
│ ├── ui/ # Shared UI component library
│ │ ├── src/
│ │ ├── package.json
│ │ └── tsconfig.json
│ ├── tsconfig/ # Shared TypeScript config
│ │ ├── base.json
│ │ ├── nextjs.json
│ │ └── package.json
│ └── utils/ # Shared utilities
│ ├── src/
│ ├── package.json
│ └── tsconfig.json
├── .claude/
│ ├── CLAUDE.md
│ └── skills/
├── .codex/
│ └── skills/
├── turbo.json
├── biome.json
├── package.json
├── pnpm-workspace.yaml
└── tsconfig.json
- **
apps/**는 개별 애플리케이션을 보관합니다. - **
packages/**는 공유 코드—유틸리티, UI 컴포넌트,tsconfig와 같은 설정 파일들을 보관합니다.
Turborepo 없이도 이 레이아웃을 복제할 수 있지만, Turborepo는 다음과 같은 실제 가치를 제공합니다:
- 각
package.json을 읽어들입니다. - 빌드와 테스트를 대량으로 혹은 병렬로 실행합니다.
- 빌드 캐시를 지능적으로 관리합니다 — 빌드 시간이 길어지기 시작할 때 큰 장점이 됩니다.
AI 시대의 지식‑베이스 관리
지식 베이스는 실제로 참조될 때만 가치가 있습니다. 쉽게 참조되려면 지식이 서로 가깝게 배치되어 있어야 합니다.
모노레포(monorepo)를 사용하면 단일 GitHub 저장소를 복제하는 것만으로 모든 것을 한 곳에서 얻을 수 있습니다:
- 애플리케이션 코드
- 개발 문서
- 에이전트 스킬(예: Claude, Codex)
여러 저장소를 동일 프로젝트에 속한 것으로 AI가 인식하도록 방법을 고안할 수도 있겠지만, 굳이 그렇게 할 필요가 있을까요? 모노레포는 그 일관성을 무료로 제공합니다.
Common Objection & Re‑framing
“프론트엔드와 백엔드는 API 계약을 통해서만 통신하면 되며, 컨텍스트를 섞을 필요는 없습니다.”
AI‑지원 코딩 시대에, 전체 그림을 볼 수 있고 빠르게 움직일 수 있게 해주는 아키텍처에서 얻는 이점이 중요하며, 엄격한 컨텍스트 분리에서 오는 것이 아닙니다.
모노레포가 빛나는 경우 (특히 AI 시대 개발에서)
-
백엔드가 TypeScript로 작성되었습니다
- TypeScript 프론트엔드와 Python 백엔드 같은 혼합 스택도 기술적으로는 모노레포가 될 수 있지만, 공유
packages/는 프론트엔드 전용이 되어 그 가치가 제한됩니다. - 또한 두 가지 다른 언어에 대한 린팅, 포맷팅, 도구 관리를 모두 해야 합니다.
- Note: Turborepo는 TypeScript(및
package.json을 기본 설정 단위) 중심으로 설계되었으므로, 스택을 TypeScript에 맞추는 것이 가장 저항이 적은 경로입니다.
- TypeScript 프론트엔드와 Python 백엔드 같은 혼합 스택도 기술적으로는 모노레포가 될 수 있지만, 공유
-
리뷰 프로세스가 AI 지원 개발에 맞게 조정되었습니다
- AI 코딩이 포함된 모노레포에서는 하나의 기능을 구현할 때 AI가 프론트엔드 와 백엔드 코드를 동시에 작성하는 경우가 많습니다. 풀 리퀘스트는 자연스럽게 그 엔드‑투‑엔드 구현을 반영합니다.
- 여전히 AI 이전 시대의 리뷰 관행을 강제한다면 인간이 병목이 됩니다. 최소한 AI 지원 코드 리뷰를 통합하는 것이 필요하며, PR 워크플로 전체를 재고하는 것이 좋습니다.
실제 예시: Chronock
내 앱인 Chronock은 전체 스택에 걸쳐 TypeScript를 사용한 모노레포 형태로 구축되었습니다.
chronock/
├── apps/
│ ├── chronock-app/ # 프론트엔드 (React + TanStack Start)
│ ├── chronock-backend/ # 백엔드 (Bun + Connect RPC)
│ ├── chronock-book/ # 예약 페이지 (React + TanStack Start)
│ └── chronock-www/ # 마케팅 사이트 (Astro)
│
├── packages/
│ ├── contract/ # Proto 정의 및 생성된 코드
│ ├── i18n/ # 국제화 유틸리티
│ └── typescript-config/ # 공유 TypeScript 설정
│
├── specs/ # 제품 사양
│
├── .claude/
│ ├── CLAUDE.md
│ └── skills/
├── .codex/
│ └── skills/
├── biome.jsonc # Linter / Formatter 설정
├── bunfig.toml # Bun 설정
├── docker-compose.local.yml
├── package.json
└── turbo.json # Turborepo 설정
주목할 만한 몇 가지 사항
- 마케팅 사이트(Astro)가 메인 앱과 같은 모노레포에 존재하여, 공개용 사이트를 포함한 전체 제품이 하나의 진실된 소스를 가집니다.
- 공유 계약, i18n 유틸리티, TypeScript 설정이
packages/에 중앙 집중화되어 중복을 줄입니다. - 사양 및 AI 에이전트 스킬 정의(
.claude/,.codex/)가 해당 코드를 바로 옆에 두어, 지식 베이스에 즉시 접근할 수 있습니다.
TL;DR
- Monorepos는 코드, 문서, AI‑에이전트 스킬에 대한 단일 진실 원본을 제공합니다.
- Turborepo는 TypeScript 중심 모노레포를 위한 필수 도구로, 병렬 빌드, 지능형 캐시, 통합 워크플로를 제공합니다.
- 스택을 TypeScript에 맞추고 리뷰 프로세스를 AI 지원 개발에 맞게 조정하여 가장 큰 이점을 얻으세요.
다음 편을 기대해 주세요. AI‑우선 모노레포를 위한 버전 관리 전략과 CI/CD 파이프라인을 살펴볼 예정입니다.
Overview
이러한 작업, 예를 들어 “reflect new feature messaging on the website” 또는 “check for inconsistencies between the latest implementation and the landing page copy” 등을 AI 에이전트에 자연스럽게 맡길 수 있습니다.
Front‑end ↔ Back‑end Communication
- Connect RPC(Protocol Buffers)를 사용합니다.
.proto정의 파일은packages/contract에 위치하여, 인터페이스 정의를 관리하고 프론트‑엔드와 백‑엔드 모두에 대한 코드 생성을 한 곳에서 원활하게 수행할 수 있습니다.
Repository Structure
- Product specs와 agent skills가 동일한 리포지토리에 존재합니다.
- 이러한 중앙화는 코딩 에이전트를 현저히 더 효율적으로 만들며, 에이전트가 필요한 컨텍스트를 레포지토리를 오가며 찾을 필요가 없습니다.
요약
AI 시대를 위한 아키텍처 선택
- 컨텍스트를 모노레포에 중앙 집중화하고 이를 살아있는 지식 베이스로 다루세요.
- 스택을 TypeScript에 맞추세요 – 여러 면에서 큰 이득이 있습니다.
- 풀 리퀘스트 문제는 스스로 해결되지 않으며, 전용 솔루션이 필요합니다.
파트 1을 마칩니다.