패키지 구성
많은 모노레포는 모든 패키지에 적용되는 태스크 설명과 함께 루트 디렉토리에 turbo.json을 선언할 수 있습니다. 그러나 때로는 모노레포에 태스크를 다르게 구성해야 하는 패키지가 포함될 수 있습니다.
이를 수용하기 위해 Turborepo는 모든 패키지에서 turbo.json을 사용하여 루트 구성을 확장할 수 있도록 합니다. 이러한 유연성을 통해 더 다양한 앱과 패키지 세트가 워크스페이스에 공존할 수 있으며, 패키지 소유자가 모노레포의 다른 앱과 패키지에 영향을 주지 않고 전문화된 태스크와 구성을 유지할 수 있습니다.
작동 방식
루트 turbo.json에 정의된 태스크의 구성을 재정의하려면 모노레포의 모든 패키지에 최상위 extends 키를 사용하여 turbo.json 파일을 추가합니다:


현재 extends 키의 유효한 값은 ["//"]뿐입니다. //는 모노레포의 루트
디렉토리를 식별하는 데 사용되는 특수 이름입니다.
패키지의 구성은 태스크 구성 중 어느 것이라도 재정의할 수 있습니다. 포함되지 않은 키는 확장된 turbo.json에서 상속됩니다.
예제
하나의 워크스페이스에 다른 프레임워크
모노레포에 여러 개의 Next.js 앱과 하나의 SvelteKit 앱이 있다고 가정해 봅시다. 두 프레임워크 모두 각각의 package.json에서 build 스크립트로 빌드 출력을 생성합니다. 다음과 같이 루트에 단일 turbo.json으로 이러한 태스크를 실행하도록 Turborepo를 구성할 수 있습니다:


Next.js 앱은 .svelte-kit 디렉토리를 생성하지 않고 그 반대도 마찬가지이지만 .next/**와 .svelte-kit/** 모두 outputs로 지정해야 합니다.
패키지 구성을 사용하면 apps/my-svelte-kit-app/turbo.json의 SvelteKit 패키지에 사용자 정의 구성을 추가할 수 있습니다:


그리고 루트 구성에서 SvelteKit 특정 outputs를 제거합니다:


이것은 각 구성을 더 쉽게 읽을 수 있게 할 뿐만 아니라 사용되는 위치에 더 가까이 구성을 배치합니다.
전문화된 태스크
다른 예에서는 한 패키지의 build 태스크가 compile 태스크에 dependsOn한다고 가정해 봅시다. 이를 dependsOn: ["compile"]로 보편적으로 선언할 수 있습니다.
이는 루트 turbo.json에 빈 compile 태스크 항목이 있어야 함을 의미합니다:


패키지 구성을 사용하면 해당 compile 태스크를 apps/my-custom-app/turbo.json으로 이동할 수 있습니다,


그리고 루트에서 제거합니다:


이제 my-app의 소유자는 build 태스크에 대한 전체 소유권을 가질 수 있지만 루트에 정의된 다른 태스크는 계속 상속받습니다.
패키지별 태스크와의 비교
첫눈에 패키지 구성은 루트 turbo.json의 package#task 구문과 많이 비슷해 보일 수 있습니다. 기능은 비슷하지만 한 가지 중요한 차이점이 있습니다: 루트 turbo.json에서 패키지별 태스크를 선언하면 기본 태스크 구성을 완전히 덮어씁니다. 패키지 구성을 사용하면 태스크 구성이 대신 병합됩니다.
여러 Next.js 앱과 Sveltekit 앱이 있는 모노레포의 예를 다시 생각해 봅시다. 패키지별 태스크를 사용하면 다음과 같이 루트 turbo.json을 구성할 수 있습니다:


이 예에서 my-sveltekit-app#build는 Sveltekit 앱의 build를 완전히 덮어쓰므로 outputLogs와 inputs도 복제해야 합니다.
패키지 구성을 사용하면 outputLogs와 inputs가 상속되므로 이를 복제할 필요가 없습니다. my-sveltekit-app 구성에서 outputs만 재정의하면 됩니다.
패키지별 태스크 구성을 제거할 계획은 없지만 대부분의 사용 사례에는 패키지 구성을 대신 사용할 수 있을 것으로 예상합니다.
Boundaries 태그 실험적
패키지 구성은 Boundaries에 대한 태그를 선언하는 데에도 사용됩니다. 이를 위해 turbo.json에 tags 필드를 추가합니다:


여기에서 태그가 가질 수 있는 의존성 또는 종속 항목에 대한 규칙을 정의할 수 있습니다. 자세한 내용은 Boundaries 문서를 참조하세요.
제한 사항
일반적인 아이디어는 루트 turbo.json과 동일하지만 패키지 구성에는 패키지가 잠재적으로 혼란스러운 상황을 만드는 것을 방지할 수 있는 가드레일 세트가 함께 제공됩니다.
패키지 구성은 태스크 항목으로 the workspace#task 구문을 사용할 수 없습니다
package는 구성 위치를 기반으로 추론되며 다른 패키지의 구성을 변경할 수 없습니다. 예를 들어 my-nextjs-app에 대한 패키지 구성에서:


build 태스크는 여전히 패키지별 태스크에 의존할 수 있습니다:


패키지 구성은 tasks 키의 값만 재정의할 수 있습니다
패키지 구성에서 globalEnv 또는 globalDependencies와 같은 전역 구성을 재정의할 수 없습니다. 패키지 구성에서 변경해야 하는 구성은 진정으로 전역이 아니며 다르게 구성해야 합니다.
루트 turbo.json은 extends 키를 사용할 수 없습니다
패키지에 대한 순환 의존성 생성을 방지하기 위해 루트 turbo.json은 어떤 것도 확장할 수 없습니다. extends 키는 무시됩니다.
문제 해결
대규모 모노레포에서는 Turborepo가 구성을 어떻게 해석하는지 이해하기 어려울 수 있습니다. 이를 돕기 위해 Dry Run 출력에 resolvedTaskDefinition을 추가했습니다. 예를 들어 turbo run build --dry-run을 실행하면 출력에 build 태스크를 실행하기 전에 고려된 모든 turbo.json 구성의 조합이 포함됩니다.