본문 바로가기
IT & Tech 정보

모노레포 의존성 자동화: Nx & Lerna를 활용한 빌드 그래프 관리 끝판왕 가이드

by 지식과 지혜의 나무 2025. 5. 26.
반응형




1. 서론: 모노레포가 대세인 이유

실리콘밸리·심천 톱티어 IT기업들은 수십~수백 개의 프론트엔드·백엔드·공유 라이브러리를 단일 레포로 관리하며, 서비스 간 의존성을 자동으로 추적·병렬 빌드·테스트합니다. 이렇게 하면:
• 코드 재사용성 극대화
• 버전 불일치 방지
• 팀 간 협업 지연 최소화

단, 레포가 커지면 단순한 npm install·lerna bootstrap만으로는 감당할 수 없으므로, **Nx(넥스)**와 **Lerna(러너)**를 결합해 빌드 그래프를 정의하고, 캐싱·분산 실행으로 속도를 비약적으로 끌어올립니다.



2. 전체 아키텍처 개요

mono-repo/
├── apps/
│   ├── web-app/
│   └── api-server/
├── libs/
│   ├── ui-components/
│   └── shared-utils/
├── tools/
│   └── scripts/
├── nx.json
├── workspace.json (또는 angular.json)
└── package.json

• Nx
• apps/·libs/ 폴더 스캔 후, 의존성 그래프 자동 생성
• nx run-many 명령어로 의존하는 패키지만 선택적 빌드/테스트
• Lerna
• 버전 관리·퍼블리시 자동화
• lerna bootstrap으로 symlink 의존성 설정

두 툴을 조합하면, Nx가 그래프 최적화를 맡고, Lerna가 릴리즈 워크플로우를 담당하는 완벽 분업 구조를 구현할 수 있습니다.



3. Nx 심화: 빌드 그래프 자동화

3.1 그래프 생성 및 시각화

npx nx dep-graph --file=graph.html

• 동적 시각화: 서비스·라이브러리 간 의존선을 HTML로 렌더링
• affected: 변경된 파일만 추적

npx nx affected:build --base=origin/main --parallel=4

• --base 옵션으로 메인 브랜치와 diff 비교
• --parallel로 멀티 스레드 빌드

3.2 태스크 패이프라이닝

// workspace.json
"tasksRunnerOptions": {
  "default": {
    "runner": "@nrwl/workspace/tasks-runners/default",
    "options": {
      "parallel": 5,
      "cacheableOperations": ["build", "test", "lint"],
      "cacheDirectory": ".nx/cache"
    }
  }
}

• cacheableOperations: 변경없으면 캐시 활용
• distributed caching: 원격 캐시(Redis·S3)와 연동 가능

3.3 Custom Executor

// tools/executors/custom-executor/index.ts
import { ExecutorContext } from '@nrwl/devkit';

export default async function runExecutor(
  options: { foo: string },
  context: ExecutorContext
) {
  console.log(`Running custom executor with foo=${options.foo}`);
  // 복잡 로직 수행…
  return { success: true };
}

// workspace.json
"custom-exec": {
  "executor": "./tools/executors/custom-executor:default",
  "options": { "foo": "bar" }
}

• 특정 프로젝트만 Custom Executor로 빌드·배포 워크플로우 내장 가능



4. Lerna 고급 설정: 버전·퍼블리시 자동화

4.1 독립(Independent) vs 고정(Fixed) 모드

lerna init --independent

• Independent: 각 패키지가 개별 버전
• Fixed: 루트 version 으로 통제

4.2 부트스트랩 최적화

lerna bootstrap \
  --hoist \
  --no-ci \
  --registry=https://registry.npmjs.org

• --hoist: 공통 의존성 루트로 이동, 전체 설치 속도 개선
• --no-ci: CI 환경에서 devDependencies 미설치
• 사내 레지스트리와 연동하여 설치 안정성 확보

4.3 Git Hooks & Conventional Commits

// package.json
"scripts": {
  "preversion": "npm test",
  "version": "lerna version --conventional-commits --yes",
  "postversion": "git push && git push --tags"
}

• 커밋 타입(feat:, fix:) 기반 자동 버전 결정
• 배포 전후 Git 푸시 자동화



5. Nx + Lerna 융합 패턴
1. 의존성 분석: Nx가 libs/ 그래프 완성
2. 부트스트랩: Lerna bootstrap으로 symlink
3. 빌드 큐:

npx nx affected:build --base=origin/main --parallel


4. 버전 결정:

git checkout main && lerna version --conventional-commits


5. 퍼블리시:

lerna publish from-package


6. 캐시 정리(옵션):

rm -rf .nx/cache && npm ci



이 워크플로우로 변경된 패키지만 빌드·배포, 병렬 처리, 자동화된 버전 정책을 한 번에 만족시킵니다.



6. 캐싱 & 분산 실행 최적화

6.1 원격 캐시 구성

// nx.json
"tasksRunnerOptions": {
  "default": {
    "options": {
      "remoteCache": {
        "url": "https://my-cache-server/api/cache"
      }
    }
  }
}

• Redis 서버, S3 기반 캐시 백엔드
• CI 에이전트 간 캐시 공유로 빌드 시간 수십 % 단축

6.2 분산 빌드 실행
• nx-cloud 연동: Nx Dev Tools에서 제공하는 분산 실행
• self-hosted: GitHub Actions Matrix + self-hosted runner로 병렬화



7. CI/CD 통합 포인트
1. GitHub Actions 예시

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v3
    - name: Setup Node
      uses: actions/setup-node@v3
      with: { node-version: 18 }
    - name: Install & Bootstrap
      run: npm ci && npx lerna bootstrap
    - name: Affected Build
      run: npx nx affected:build --base=origin/main --parallel
    - name: Affected Test
      run: npx nx affected:test --base=origin/main


2. GitLab CI

stages: [build, test, release]
build:
  script:
    - npm ci
    - npx lerna bootstrap
    - npx nx affected:build --base=$CI_MERGE_REQUEST_TARGET_BRANCH_NAME --parallel





8. 트러블슈팅 & 팁
• 의존성 사이클 오류
• nx lint --fixCycles로 순환 참조 감지·제거
• 캐시 불일치
• nx reset 으로 캐시 초기화
• Lerna 퍼미션 이슈
• npm config set unsafe-perm true 설정
• 대용량 레포 그라프트
• git sparse-checkout으로 필요한 폴더만 체크아웃



9. 결론: “끝판왕” 모노레포 의존성 자동화
• Nx로 빌드 그래프 완전 자동화 → 영향받은 패키지만 선택 빌드
• Lerna로 버전·퍼블리시 자동화 → Conventional Commits 기반 릴리즈
• 캐시·분산 실행으로 CI 속도 수십 % 단축

“교과서론 설명 못하는, 실리콘밸리·심천 IT기업 최정예 개발자 수준의 모노레포 자동화”를 직접 구현해 보세요! 여러분의 레포가 초당 수십 개 패키지를 병렬 빌드하는 그날까지, 이 워크플로우가 든든한 버팀목이 되어 드립니다.

반응형