-
Turborepo 사용해보기Study 2022. 7. 31. 17:46
Turborepo
홈페이지: https://turborepo.org/
소개: Turborepo is a high-performance build system for JavaScript and TypeScript codebases.
빠른 속도의 빌드를 지원하는 모노레포 툴.
모노레포로 프로젝트를 진행하다가 사용해보고 싶어서 홈페이지의 내용을 정리해보았다.모든 내용은 공식문서를 참고했다.
터보레포를 사용할 이유 (장점)
- Incremental Building
빌드를 여러번 하는 경우, 이전 빌드 내용을 기억해뒀다가, 이미 계산된 것들에 대해서는 빌드를 스킵한다. - Content-aware hashing
빌드할 때 타임스탬프를 보는게 아니라 콘텐츠의 변화를 감지해서 어떤 파일이 빌드가 필요한지 파악한다. - Remote caching
더 빠른 빌드를 위해서 remote 캐싱까지도 사용한다. 로컬에서는 빌드 한 적 없더라도 팀원들이 빌드를 한 적이 있다면 해당 빌드를 사용 가능 - Parallel execution
노는 CPU 없이 모든 코어를 사용해 최대의 병렬성으로 빌드한다. - Zero runtime overhead
런타임 코드를 방해하거나 소스맵을 건드리지 않는다. - Pruned subsets
모노레포 내에서 특정 서브셋만 배포할 수 있도록 해줘서 빠른 배포가 가능하게 한다. - Task pipelines
태스크 사이의 관계를 정의해라 그리고 터보레포가 무엇을 언제 빌드할 지 최적화하도록 해라. - Meets you where you’re at
- Profile in your browser
빌드 프로파일을 크롬, 엣지 등에서 보고 분석할 수 있다.
시작하기
아래 명령어로 새로운 모노레포를 만들 수 있다.
npx create-turbo@latest
워크스페이스 설정하기
모노레포를 사용할 때 모노레포 내에서 패키지를 관리하기 위해 yarn, npm 등 패키지 매니저의 워크스페이스를 대부분 사용한다. 터보레포는 여기에 잘 맞춰져있다.
apps/
,packages/
구조를 사용한다면 루트의package.json
에 아래와 같이 워크스페이스 설정 가능.{ "workspaces": [ "packages/*", "apps/*" ] }
turbo
설치npm install turbo -D
설정파일
루트에
turbo.json
을 만들 수 있다.{ "$schema": "https://turborepo.org/schema.json", "baseBranch": "origin/main" }
설정파일 DOCS: https://turborepo.org/docs/reference/configuration
cf) JSON 내의 $schema는 JSON dialect를 정의하는 JSON의 스펙이다. JSON이 해당 schema에 맞게 사용될 수 있도록 한다.
ex 1) 스키마에 없는 키 사용 시, key가 allowed 되지 않았다고 알려줌.
ex 2) 새로운 키를 추가할 때 스키마에 맞는 키를 미리 알 수 있음.
참고 링크 - [JSON Declaring a Dialect](https://json-schema.org/understanding-json-schema/reference/schema.html#:~:text=The %24schema keyword is used,to the dialect %24schema identifies.)
파이프라인 만들기
lerna
나yarn
의workspaces run
과 같은 커맨드는 dependency의 빌드를 먼저 수행한 후 다음 빌드가 수행되는 방식을 사용한다. (i.e. run topologically)이 경우 모노레포의 의존성 그래프에 따라, CPU의 core가 idle한 상태로 남아있을 수 있다. 이는 시간과 리소스의 낭비이다.
turbo는 태스크를 효과적으로 스케줄링하여 이런 낭비를 막을 수 있다.
{ "$schema": "https://turborepo.org/schema.json", "pipeline": { "build": { // 한 패키지의 `build` 스크립트는 해당 패키지의 dependency 및 devdependency의 // `build` 태스크가 먼저 종료된 후 빌드가 된다는 것을 의미 // (`^` 기호가 upstream을 의미) "dependsOn": ["^build"], // note: 아웃풋은 루트가 아닌 각 package.json의 상대경로 "outputs": [".next/**"] }, "test": { // 한 패키지의 `test` 스크립트는 해당 패키지의 `build`스크립트가 종료된 후 실행됨 // (`^` 기호가 없음) "dependsOn": ["build"], "outputs": [], // 패키지의 `test` 스크립트는 `src` 또는 `test` 폴더의 // `.ts`, `.tsx` 파일이 변경되는 경우에만 재실행돼야 한다는 것을 의미 "inputs": ["src/**/*.tsx", "src/**/*.ts", "test/**/*.ts", "test/**/*.tsx"] }, "lint": { // `lint` 스크립트는 의존성이 없기 때문에 언제든 실행될 수 있음. // 출력 파일 또한 없음 "outputs": [] }, "deploy": { // `deploy` 스크립트는 해당 패키지의 `build`, `test`, `lint` 스크립트가 // 모두 종료된 후 실행. 출력 파일 없음. "dependsOn": ["build", "test", "lint"], "outputs": [] } } }
더 자세한 내용: https://turborepo.org/docs/core-concepts/pipelines
full pipeline 실행
npx turbo run build test lint deploy
실행하면 turbo가 머신의 리소스를 최적화하기 위해 태스크 실행을 스케줄링함.
.gitignore
수정.turbo
폴더에는 turbo의 로그와 특정 태스크 아웃풋이 저장된다.태스크 아티팩트들 - 캐시되길 원하는 파일과 폴더들 - 또한
.gitignore
에 추가해준다..turbo build/** dist/** .next/**
package.json
수정루트의
package.json
에 스크립트들을 작성해준다.{ "scripts": { "build": "turbo run build", "test": "turbo run test", "lint": "turbo run lint", "dev": "turbo run dev" } }
npm run build
나yarn build
와 같이 빌드를 실행할 수 있다.리모트 캐싱
혼자 개발하는 경우 위 내용으로도 충분하다.
팀원들과 개발하는 경우, 리모트 캐싱을 통해서 더 빠른 빌드를 할 수 있다.
자세한 내용은 공식문서 참고
728x90 - Incremental Building