풀스택 프로젝트 CI/CD 최적화: Turborepo의 원격 캐싱 및 온디맨드 빌드 활용
Lukas Schneider
DevOps Engineer · Leapcell

소개
현대의 풀스택 JavaScript 애플리케이션은 점점 더 복잡해지고 있으며, 여러 상호 의존적인 서비스, 프론트엔드 애플리케이션 및 공유 라이브러리를 관리하기 위해 모노레포 아키텍처를 채택하는 경우가 많습니다. 모노레포는 코드 공유 및 종속성 관리 단순화 측면에서 상당한 이점을 제공하지만, 특히 지속적 통합/지속적 전달(CI/CD) 파이프라인에서 어려움을 초래할 수도 있습니다. 일반적인 병목 현상은 모든 커밋마다 변경되지 않은 코드베이스 부분을 다시 빌드하는 데 낭비되는 시간과 리소스입니다. 한 프론트엔드 앱의 작은 CSS 변경으로 인해 모노레포의 모든 서비스와 애플리케이션을 전체 다시 빌드하고 다시 테스트해야 하는 시나리오를 상상해 보세요. 이는 비효율적일 뿐만 아니라 클라우드 리소스와 개발자 대기 시간 측면에서도 비용이 많이 듭니다. 이 기사는 Turborepo의 강력한 원격 캐싱 및 온디맨드 빌드 조합이 풀스택 JavaScript 프로젝트의 CI/CD 프로세스를 대폭 최적화하여 더 빠른 피드백 루프와 감소된 인프라 비용을 보장하는 방법을 탐색하여 이러한 과제를 해결하는 것을 목표로 합니다.
핵심 개념 및 구현
최적화에 대한 자세한 내용에 들어가기 전에 Turborepo의 효과에 핵심적인 개념을 명확하게 이해해 봅시다.
모노레포란 무엇인가?
모노레포는 공유 종속성 및 구성이 있는 여러 개의 별도 프로젝트를 포함하는 단일 리포지토리입니다. 일반적인 풀스택 JavaScript 설정에서는 React 프론트엔드, Node.js 백엔드 API, 공통 UI 구성 요소 및 유틸리티 라이브러리가 모두 동일한 Git 리포지토리 내에 있을 수 있습니다.
Turborepo란 무엇인가?
Turborepo는 JavaScript 및 TypeScript 모노레포를 위한 고성능 빌드 시스템입니다. 빌드 아티팩트를 지능적으로 캐싱하고 필요한 것만 다시 빌드하여 개발 및 CI/CD 경험을 최적화하도록 설계되었습니다.
Turborepo의 주요 기능
우리의 논의와 특히 관련이 있는 두 가지 기능은 다음과 같습니다.
- 원격 캐싱: Turborepo는 빌드 아티팩트(예: 컴파일된 코드, 테스트 결과, 번들링된 자산)를 원격 캐시에 저장할 수 있습니다. 이 캐시는 여러 개발자 및 CI/CD 파이프라인에서 공유될 수 있습니다. 특정 프로젝트에 대한 특정 작업(예:
build
또는test
)이 이전에 동일한 입력을 사용하여 실행되었다면 Turborepo는 작업을 다시 실행하는 대신 캐시된 출력을 검색할 수 있습니다. - 온디맨드 빌드 (또는 증분 빌드): Turborepo는 모노레포의 종속성 그래프를 분석하고 변경 사항의 영향을 받은 프로젝트 및 작업을 결정합니다. 그런 다음 영향을 받은 프로젝트에 대해서만 작업을 실행하고 영향을 받지 않은 프로젝트는 건너뜁니다. 이를 통해 불필요한 작업을 방지하여 빌드 시간을 크게 단축할 수 있습니다.
Turborepo 설정
먼저 모노레포에 Turborepo를 설정해야 합니다. 모노레포의 루트에 package.json
파일이 있고 작업 공간 패키지(예: apps/web
, packages/ui
) 내에 개별 package.json
파일이 있다고 가정합니다.
// root package.json { "name": "my-fullstack-monorepo", "version": "1.0.0", "private": true, "workspaces": [ "apps/*", "packages/*" ], "scripts": { "build": "turbo run build", "dev": "turbo run dev --parallel", "test": "turbo run test" }, "devDependencies": { "turbo": "^LatestVersion" } }
다음으로, 파이프라인 작업과 캐싱 동작을 정의하기 위해 모노레포의 루트에 turbo.json
파일을 구성합니다.
// turbo.json { "$schema": "https://turbo.build/schema.json", "globalDependencies": [ "**/.env" // 예: .env 파일 변경 시 캐시가 무효화됨 ], "pipeline": { "build": { "dependsOn": ["^build"], "outputs": ["dist/**", ".next/**"], "cache": true }, "test": { "dependsOn": [], "outputs": ["coverage/**"], "cache": true }, "lint": { "outputs": [] }, "dev": { "cache": false, // 개발 서버는 일반적으로 장시간 실행되므로 캐싱이 필요 없음 "persistent": true } } }
이 turbo.json
에서:
build
:^build
에 종속되며, 이는 현재 패키지의 종속성을 먼저 빌드한다는 것을 의미합니다.dist/**
및.next/**
출력 디렉토리를 캐싱합니다.test
: 테스트를 실행하지만 특정 프로젝트 종속성은 없습니다.coverage/**
를 캐싱합니다.build
및test
에 대한cache: true
는 Turborepo의 캐싱 메커니즘을 활성화합니다.
원격 캐싱 구현
Turborepo는 전용 Turborepo 원격 캐시 서비스(Vercel의 제품 또는 자체 호스팅 가능한 대안)에 대한 암호화된 네트워크 연결을 통해 원격 캐싱을 지원합니다.
-
Vercel 통합 (가장 쉬운 방법): 모노레포가 Vercel에 호스팅되어 있다면 원격 캐싱은 대체로 자동입니다. Turborepo를 Vercel 팀과 연결하기만 하면 Vercel의 원격 캐시가 사용됩니다.
-
자체 호스팅 (AWS S3, Google Cloud Storage 등): 자체 호스팅의 경우 환경 변수를 구성해야 합니다. AWS S3의 경우:
# CI/CD 환경 변수에 설정 TURBO_REMOTE_CACHE_SIGNATURE_KEY="캐시 요청 서명에 사용할 비밀 키" TURBO_REMOTE_CACHE_API="https://my-self-hosted-cache-endpoint.com" # 또는 직접 S3 URL TURBO_REMOTE_CACHE_READ_ONLY=false # 일부 CI 단계에서는 읽기 전용으로 설정
S3와 같은 스토리지 제공 업체를 사용하여 Turborepo의 원격 캐시 API를 구현하는 백엔드 서비스도 필요합니다. Turbo는 이를 위한 오픈 소스 예제와 도구를 제공합니다.
CI/CD 워크플로우 예시 (GitHub Actions):
# .github/workflows/ci.yml name: CI on: push: branches: - main pull_request: branches: - main jobs: build-and-test: runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v3 - name: Setup Node.js uses: actions/setup-node@v3 with: node-version: 18 - name: Install dependencies run: npm install # 또는 yarn install / pnpm install - name: Turborepo Remote Cache configuration env: TURBO_TOKEN: ${{ secrets.VERCEL_TOKEN }} # Vercel 원격 캐시 사용 시 TURBO_TEAM: your-vercel-team-id # Vercel 원격 캐시 사용 시 # 또는 자체 호스팅: # TURBO_REMOTE_CACHE_SIGNATURE_KEY: ${{ secrets.TURBO_REMOTE_CACHE_SIGNATURE_KEY }} # TURBO_REMOTE_CACHE_API: ${{ secrets.TURBO_REMOTE_CACHE_API }} run: | # 이 명령어는 env var가 설정되어 있거나 `vercel link`를 통해 Vercel에 연결된 경우 # 원격 캐시에 자동으로 연결됩니다. echo "Configuring Turborepo for remote caching..." - name: Build affected projects run: npm run build # `turbo run build`를 호출합니다. # Turborepo가 여기서 원격 캐시를 자동으로 활용합니다. # 프로젝트 빌드가 캐시된 경우 복원됩니다. # 그렇지 않으면 빌드하고 출력을 캐시에 저장합니다. - name: Test affected projects run: npm run test # `turbo run test`를 호출합니다. # 빌드와 마찬가지로 테스트는 캐싱을 활용합니다.
작동 중인 온디맨드 빌드
Turborepo의 온디맨드 빌드 기능은 원격 캐싱과 원활하게 작동합니다. turbo run build
또는 turbo run test
를 실행하면 Turborepo는 다음 단계를 수행합니다.
- 그래프 분석: 모노레포의 종속성 그래프를 구성합니다.
- 지문 인식: 각 작업(예:
apps/web
에 대한build
)에 대해 작업의 입력(소스 파일, 종속성, 환경 변수,turbo.json
구성 등)을 기반으로 고유한 "지문"을 계산합니다. - 캐시 조회: 먼저 로컬 캐시에서, 그런 다음 원격 캐시에서 이 지문이 있는지 확인합니다.
- 실행 또는 복원:
- 캐시 히트가 발생하면 캐시에서 출력을 복원하고 작업을
cache hit
으로 표시합니다. - 캐시 히트가 없으면 작업을 실행한 다음 로컬 및 원격 캐시에 출력을 저장합니다.
- 캐시 히트가 발생하면 캐시에서 출력을 복원하고 작업을
- 영향을 받는 프로젝트: 변경 사항이 발생하면 Turborepo는 해당 변경 사항에 직접적 또는 간접적으로 영향을 받은 프로젝트만 다시 지문 인식하고 다시 평가합니다. 영향을 받지 않은 프로젝트는 작업이 완전히 캐시되어 있을 가능성이 높습니다.
실제 예시:
모노레포에 apps/web
(React 앱)과 packages/ui
(공유 UI 구성 요소)가 있다고 가정해 봅시다.
apps/web
의 파일을 변경하는 경우:apps/web
의build
및test
작업만 잠재적으로 실행됩니다.packages/ui
의 작업은 캐시에서 가져옵니다.packages/ui
의 파일을 변경하는 경우:packages/ui
의 작업과apps/web
의 작업(apps/web
이packages/ui
에 종속되어 있으므로) 모두 잠재적으로 실행됩니다. 다른 관련 없는 프로젝트는 캐시에서 가져옵니다.
이러한 지능형 오케스트레이션은 CI/CD 파이프라인에서 더 이상 모든 커밋마다 모든 것을 다시 빌드하지 않아 실행 속도가 크게 향상되고 리소스 소비가 줄어든다는 것을 의미합니다.
결론
Turborepo의 원격 캐싱 및 온디맨드 빌드는 CI/CD에서 풀스택 JavaScript 모노레포 관리 방식을 근본적으로 변화시킵니다. 빌드 아티팩트를 지능적으로 저장하고 검색하며 영향을 받는 작업만 선택적으로 실행하여 Turborepo는 불필요한 작업을 제거하고 빌드 시간과 CI/CD 비용을 대폭 절감합니다. Turborepo를 채택하는 것은 개발 주기 속도를 높이고 풀스택 모노레포 워크플로우의 효율성을 향상하려는 모든 팀에게 전략적인 움직임입니다.