정의
워크스페이스 프로토콜은 모노레포(하나의 저장소에 여러 패키지가 함께 사는 구조)에서 내부 패키지 의존을 버전 문자열 대신 "pkg": "workspace:*" 처럼 로컬 소스로 직접 링크하는 표기다. 배포(publish) 시점에 워크스페이스를 아는 패키지 매니저가 이 표기를 실제 버전 범위로 다시 써서 레지스트리에 올린다.
즉 개발 중에는 로컬 링크, 배포 순간에는 진짜 버전 — 두 얼굴을 갖는다.
왜 필요한가
한 저장소 안에서 패키지 @scope/ui가 @scope/utils에 의존한다고 하자. @scope/utils를 ^1.0.0처럼 버전으로 박아 두면, utils를 한 줄 고칠 때마다 버전을 올리고 다시 설치·링크해야 로컬에 반영된다. 개발 속도가 크게 느려진다.
"@scope/utils": "workspace:*"로 쓰면 로컬 소스가 곧바로 링크되어 즉시 반영된다. 하지만 이 workspace:* 문자열을 그대로 npm에 올리면, 설치하는 외부 사용자의 패키지 매니저는 workspace:*를 해석하지 못해 설치가 깨진다. 그래서 배포 시 반드시 실제 버전으로 치환돼야 하고, 이 치환은 워크스페이스를 이해하는 명령으로만 일어난다.
동작 원리
- 개발 시:
install이workspace:*의존을 lockfile에link:../utils형태로 기록하고,node_modules에 로컬 패키지를 심볼릭 링크한다. - 배포 시:
pnpm publish(또는 yarn)가 tarball을 만들기 직전package.json의workspace:*를 대상 패키지의 실제 배포 버전으로 치환한다. 예:workspace:*→^1.3.0. - 순서: 의존 그래프의 잎(하위 패키지)부터 publish해야, 상위 패키지가 참조할 하위 버전이 레지스트리에 이미 존재한다.
npm publish는 이 치환을 하지 않는다 — workspace:*가 날것 그대로 올라가 설치 불가 tarball이 된다.
실무 적용
배포 전 pnpm pack으로 tarball을 열어 package.json의 의존 버전이 workspace:*가 아니라 실제 값으로 치환됐는지 눈으로 확인하면 사고를 막는다.
트레이드오프
- 얻는 것: 로컬 개발 속도(즉시 반영), 버전 수동 관리 제거, 단일 저장소의 원자적 변경.
- 치르는 것: 배포 파이프라인이 워크스페이스 인지 매니저에 묶인다.
npm publish습관, OIDC 기대, 잘못된 순서가 모두 깨질 지점이 된다. - 버전 자동화 도구(release 도구)와 결합하면 편하지만, 그만큼 CI 배선(러너·토큰·순서)이 늘어난다.
사용하면 안 되는 경우
- 패키지가 하나뿐이거나 서로 의존하지 않는다면 워크스페이스 프로토콜의 이점이 없다.
- 배포를 반드시
npm publish로만 해야 하는 제약이 있다면workspace:*를 쓰면 안 된다 — 치환되지 않는다.
흔한 실수
npm publish로 배포:workspace:*가 그대로 올라가 외부 설치가 깨진다.pnpm publish를 쓴다.- 내부 의존에 존재하지 않는 외부 버전을 박음:
^1.0.0이 레지스트리에 없으면 CIinstall이 404.workspace:*로 바꾸고 relock한다. - 배포 순서 뒤집힘: 상위를 먼저 올리면 하위 최신 버전을 못 찾는다. 잎부터 올린다.
- OIDC 기대:
pnpm publish는 OIDC 미지원 → 배포 권한 자동화 토큰이 없으면 403.
관련 개념
- [[library-esm-packaging-dangling-exports]] — 같은 배포 파이프라인에서 export 필드 누락으로 함께 터지는 문제