가령, 앱 foo가 공유 패키지 bar에 의존한다고 선언하면 공유 패키지로 있는 bar를 사용하게 함
공통 lockfile을 관리하고, 패키지간 의존 관계를 고려해 빌드 스크립트를 실행하거나, 특정 패키지만 선택할 수도 있음 (cf. pnpm -r build)
Node.js 패키지 매니저 — 의존성 해결·설치·버전 관리와 저장 공간의 효율화가 주안점
Workspace
여러 프로젝트를 하나의 저장소에서 관리하며, 프로젝트 간 로컬 의존성을 연결하고 명령을 실행할 수 있도록 지원
‘어떤 프로젝트들을 하나의 모노레포로 묶을 것인가?’
pnpm이 모노레포를 지원하는 방식 — 여러 패키지를 하나의 작업 공간으로 연결, 관리
# apps와 packages 아래의 프로젝트들은 각각 독립적인 패키지이면서,
# 동시에 하나의 Workspace에 속한다.
packages:
- "apps/*"
- "packages/*"
기능
내부 패키지 참조 : 각 애플리케이션이 공유 패키지를 로컬 의존성으로 사용할 수 있음
통합 의존성 관리 : 루트의 pnpm install로 전체 패키지 설치
공유 lockfile : 기본적으로 루트의 pnpm-lock.yaml 하나로 버전 관리
선택적 명령 실행 : pnpm --filter @foo/api build 처럼, 특정 패키지만 실행 가능
workspace:* 프로토콜 사용 시, 해당 의존성이 반드시 로컬 Workspace에서 해결되도록 강제 가능 → 같은 모노레포에 있는 다른 패키지를 의존성으로 사용할 때 선언
{
"name": "@foo/app",
"dependencies": {
// @bar/types는 npm에서 내려받지 말고, 반드시 현재 Workspace 내부에서 찾아 연결할 것
"@bar/types": "workspace:*",
"next": "^16.0.0"
}
}
Turborepo
의존성 관계를 파악해서 공유 패키지를 먼저 빌드하고, 이후 독립적인 앱 빌드를 병렬로 진행한다던가를 가능케함
소스 코드와 관련 input이 변경되지 않았다면 — 기존 결과를 캐시에서 복원하여 불필요한 빌드를 생략 가능 (작업 입출력, 환경 변수 등 구성 필요)
공유 패키지가 늘고, CI의 중복 빌드가 부담스러워지면 Turborepo의 캐싱과 작업 그래프가 효과적
패키지들이 수행하는 작업의 실행 순서, 결과 재사용 최적화에 주안점
빌드 캐시
다음 빌드에서 입력이 같다면 — 컴파일을 또 하는 대신, 이전 작업 산출물을 다시 가져오는 것
빌드 : dist, .next 등의 산출물
테스트·린트 : 작업 실행 결과 및 로그
캐시할 파일은 turbo.json의 outputs로 명시해야 함
입력에는 소스 코드뿐 아니라 패키지 의존성, 설정, 관련 환경변수 등이 포함될 수 있음
Turborepo는 입력을 비교할 식별값을 만듦 — 일치하는 결과가 있으면 복원
공유 패키지처럼 애플리케이션이 사용하는 코드를 수정하면, 입력이 달라지므로 다시 빌드
공유 패키지처럼 애플리케이션이 사용하는 코드를 수정하면, 입력이 달라지므로 다시 빌드
pnpm의 다운로드 캐시와 다름
pnpm은 패키지를 다시 다운로드하는 시간을 줄일 수 있음
하지만 그것만으로 애플리케이션의 컴파일을 건너뛰지는 않음
CI가 매번 새 컴퓨터에서 실행된다면, 이전 빌드 결과를 재사용하기 위해 원격 캐시, 혹은 CI 캐시 저장소 필요
pnpm은 패키지를 다시 다운로드하는 시간을 줄일 수 있음
하지만 그것만으로 애플리케이션의 컴파일을 건너뛰지는 않음
CI가 매번 새 컴퓨터에서 실행된다면, 이전 빌드 결과를 재사용하기 위해 원격 캐시, 혹은 CI 캐시 저장소 필요