
최근 팀에서 다양한 플로우 서비스에 업무, 간트차트 기능을 라이브러리로 적용하기 위해 리포지토리를 분리하고 모노레포를 적용중이다.
모노레포를 구현하기 위해 pnpm을 사용하여 인스톨 및 빌드를 하는데 Turborepo를 이용해 빌드하다보면 이런 문제가 발생한다.

빌드하는데 다음과 같이 빌드가 안되는 문제가 있었는데, 이는 빌드 의존성이 있음에도 의존성을 무시한채 빌드되어서 생긴 문제다.
다시 말하면 Turborepo는 빌드 순서가 있고, 각 패키지들이 순서대로 빌드가 되어야 의존하고 있는 다른 패키지들이 빌드가 가능.
각 패키지의 package.json에 dependencies 추가.

그런데 이미 peerDependancies에 의존하고 있는 패키지들이 있는 상태인데 빌드가 안된다.
왜 그러냐면 Turbo는 패키지 그래프(dependencies/devDependencies/optionalDependencies)로 빌드 순서를 결정하는데, peerDependencies로만 선언하면 의존 에지가 없어 동시에 빌드된다고 함. 빌드 순서를 보장하려면 내부 패키지를 devDependencies(또는 dependencies)에도 추가해야한다고 함.
어짜피 빌드할때만 쓰는거 devDependencies에 넣으면 된다고 생각해서 다음과 같이 넣었음.

여기서 workspace:*와 workspace:^ 가 뭔지 궁금해서 검색후 정리함.
workspace:*는 워크스페이스 안에서는 로컬 패키지를 심볼릭 링크로 바로 사용하고, 패키지를 배포할 때는 해당 의존성의 정확한 버전 값으로 치환. 즉 “현재 이 패키지와 동일한 버전만 쓴다”는 의미.workspace:^역시 개발 중에는 로컬 패키지를 직접 링크하지만, 배포 시에는 ^1.2.3 같은 캐럿 범위(호환 가능한 마이너·패치)를 가진 의존성으로 바뀜. 최신 마이너/패치 업데이트를 허용하려면workspace:^를, 정확히 같은 버전만 고정하려면workspace:*를 쓰면 됨.
turbo.json 수정
하지만 모든 패키지에 package.json로 찾아 들어가서 devDependencies를 수정하는게 너무 비효율적이라고 생각함.
어떤것들이 서로 의존하고 있는지 한눈에 보기 힘들것 같아서 다른 방법을 찾아봤음. 이때 turbo.json을 발견하게 되었다.
package.json에 각각 devDependencies에 명시하지 않고, Turborepo의 turbo.json에서 명시적으로 의존성을 지정할 수 있다고 해서 수정함.
"@flow-library/grid-popup#build": {
"dependsOn": ["@flow-library/grid-core#build"],
"outputs": ["dist/**"]
},
"@flow-library/grid-gantt#build": {
"dependsOn": ["@flow-library/grid-core#build", "@flow-library/grid-popup#build"],
"outputs": ["dist/**"]
},
"@flow-library/grid-header#build": {
"dependsOn": ["@flow-library/grid-core#build", "@flow-library/grid-popup#build"],
"outputs": ["dist/**"]
},
"@flow-library/grid-toolbar#build": {
"dependsOn": ["@flow-library/grid-core#build", "@flow-library/grid-popup#build", "@flow-library/grid-gantt#build"],
"outputs": ["dist/**"]
},
"@flow-library/grid-tutorial#build": {
"dependsOn": ["@flow-library/grid-core#build"],
"outputs": ["dist/**"]
},
"@flow-library/grid-list-kit#build": {
"dependsOn": [
"@flow-library/grid-core#build",
"@flow-library/grid-popup#build",
"@flow-library/grid-gantt#build",
"@flow-library/grid-header#build",
"@flow-library/grid-toolbar#build",
"@flow-library/grid-tutorial#build"
],
"outputs": ["dist/**"]
},
"@flow-library/flow-grid#build": {
"dependsOn": [
"@flow-library/grid-core#build",
"@flow-library/grid-popup#build",
"@flow-library/grid-gantt#build",
"@flow-library/grid-header#build",
"@flow-library/grid-toolbar#build",
"@flow-library/grid-tutorial#build",
"@flow-library/grid-list-kit#build"
],
"outputs": ["dist/**"]
},
위와 같이 turbo.json을 수정하고 devDependencies를 모두 제거해도 정상적으로 빌드가 된다.
빌드 순서
- grid-core (의존성 없음)
- grid-popup, grid-tutorial (grid-core 의존)
- grid-gantt, grid-header (grid-core + grid-popup 의존)
- grid-toolbar (grid-core + grid-popup + grid-gantt 의존)
- grid-list-kit (모든 컴포넌트 의존)
- flow-grid (모든 패키지 의존)
#build 문법과 예시
문법: <패키지명>#<태스크명>
"@flow-library/grid-popup#build": {
"dependsOn": ["@flow-library/grid-core#build"]
}
- 의미: grid-popup 패키지의 build 태스크는 grid-core 패키지의 build 태스크 이후에 실행됨.
package.json 예시:
{
"name": "@flow-library/grid-popup",
"scripts": {
"build": "rollup -c",
"test": "vitest",
"lint": "eslint ."
}
}
turbo.json에서의 태스크 지정:
{
"@flow-library/grid-popup#build": { },
"@flow-library/grid-popup#test": { },
"@flow-library/grid-popup#lint": { }
}
여러 태스크 의존성 예시:
{
"@flow-library/grid-popup#build": {
"dependsOn": ["@flow-library/grid-core#build"]
},
"@flow-library/grid-popup#test": {
"dependsOn": ["@flow-library/grid-core#test"]
},
"@flow-library/grid-popup#lint": {
"dependsOn": []
}
}
의존성 체인 예시:
"@flow-library/grid-gantt#build": {
"dependsOn": [
"@flow-library/grid-core#build",
"@flow-library/grid-popup#build"
]
}
요약
#는 “패키지의 특정 태스크” 지정자- 예:
@flow-library/grid-popup#build= grid-popup의 build 태스크 - 패키지별 태스크 의존성을 Turborepo에 명확히 전달할 때 필수
참고 링크
https://turborepo.com/docs/core-concepts/package-and-task-graph
Package and Task Graphs | Turborepo
Turborepo builds a Task Graph based on your configuration and repository structure.
turborepo.com
'개발 아카이브 > 개발 관련 지식' 카테고리의 다른 글
| JWT (JSON Web Token) 설명 (0) | 2025.09.21 |
|---|---|
| Claude Code Usage Monitor for macOS - 메뉴바에서 클로드 토큰 사용량 실시간 모니터링 (3) | 2025.07.31 |
| iCalendar 기본 문법 (0) | 2025.02.01 |
| REST (Representational State Transfer)란 무엇인가? (1) | 2023.07.31 |
| [노션 API] 노션 API 연동으로 데이터베이스 사용하기 (3) | 2023.04.09 |