pnpm install 오류 해결: lockfile·workspace 점검 순서

··설명 약 14분·작성: 해비·블로그 소개

요약

pnpm install 실패는 현재 폴더·Node·pnpm 버전·workspace·잠금 파일을 순서대로 봅니다. 설치 로그와 package.json을 먼저 맞추세요. node_modules나 잠금 파일을 바로 지우지 말고 누락·불일치 원인을 찾습니다.

pnpm install이 실패하면 무엇부터 확인하나요?

설치 로그의 첫 구체적인 오류를 기준으로 현재 폴더·실행 버전·workspace·lockfile을 확인합니다. 같은 설치 명령이 다시 통과하는지로 복구를 판단하며, lockfile 삭제를 첫 해결책으로 삼지 않습니다.

pnpm 설치 오류별 점검 순서
오류 범위 확인 방법 수정·재확인 기준
frozen lockfile 불일치 package.json과 pnpm-lock.yaml의 변경 내역 비교 같은 pnpm 버전으로 필요한 lockfile 변경을 검토한 뒤 CI 설치 재확인
workspace 패키지 누락·버전 불일치 루트 YAML 경로 패턴, 실제 폴더, 패키지 name·버전 확인 로컬 패키지와 의존성 선언을 일치시킨 뒤 재설치
registry·network 오류 로그에 나온 호스트와 registry 설정 확인 접속·인증 원인을 해결한 뒤 같은 요청 재확인
설치 script 실패 실패한 패키지·script 이름과 첫 오류 확인 script의 요구 환경을 확인하고 설치·빌드를 구분해 검증

이 글의 기존 실행 검증 환경은 Windows · Node.js 24.19.0 · pnpm 11.19.0입니다. 자신의 프로젝트는 packageManager와 lockfile의 버전을 우선하세요. pnpm install 공식 옵션과 workspace 공식 문서에서 현재 동작을 확인할 수 있으며, 이번 문서 보강은 독자 프로젝트의 설치 성공을 대신 검증하지 않습니다.

pnpm install 실패는 모두 같은 원인이 아닙니다.

현재 경로 문제
pnpm 버전 불일치
workspace 설정 오류
package.json 문법 오류
lockfile 불일치
존재하지 않는 workspace 패키지
registry/network 문제
설치 script 문제
파일 권한 문제

오류 메시지의 첫 실패 지점을 확인한 뒤 범위를 좁힙니다.

1. 현재 폴더 확인

Windows PowerShell:

Get-Location
Get-ChildItem

macOS/Linux:

pwd
ls

다음 파일이 보이는지 확인합니다.

package.json
pnpm-workspace.yaml
pnpm-lock.yaml

workspace 루트가 아닌 apps/web 안에서 실행하고 있는지 확인합니다.

2. pnpm 버전 확인

pnpm -v
node -v

package.json도 확인합니다.

{
  "packageManager": "pnpm@11.19.0"
}

실제 실행 버전과 프로젝트 기준이 크게 다르면 같은 환경을 재현했다고 보기 어렵습니다.

3. pnpm-workspace.yaml 확인

packages:
  - "apps/*"

경로 패턴과 실제 폴더가 맞는지 확인합니다. labs의 실습은 각 패키지 매니저와 lockfile로 독립 관리하므로 메인 workspace에 포함하지 않습니다.

예를 들어 실제 폴더가 app/web인데 설정이 apps/*라면 해당 package가 workspace로 인식되지 않습니다.

4. 각 workspace의 package.json 확인

apps/web/package.json 예시:

{
  "name": "@taskflow/web",
  "private": true,
  "scripts": {
    "dev": "vite",
    "build": "vite build",
    "lint": "eslint ."
  }
}

filter 이름과 package name이 일치해야 합니다.

pnpm --filter @taskflow/web dev

5. lockfile을 무조건 삭제하지 않기

pnpm-lock.yaml에는 실제 의존성 해석 결과가 저장됩니다.

install이 실패했다고 바로 삭제하면 문제의 원인이 package.json 변경인지 lockfile 충돌인지 구분하기 어려워질 수 있습니다.

Git을 사용한다면 먼저 변경 상태를 확인합니다.

git status
git diff -- pnpm-lock.yaml

다른 브랜치의 lockfile 변경이 섞였는지 확인합니다.

6. frozen lockfile 오류

CI나 엄격한 설치 설정에서는 package.json과 lockfile이 일치하지 않으면 실패할 수 있습니다.

핵심은 “lockfile을 없애서 통과”가 아니라 package.json 변경과 lockfile 변경이 같은 의도인지 확인하는 것입니다.

로컬에서 정상적으로 lockfile을 갱신한 뒤 저장소에 함께 반영합니다.

7. workspace 의존성 확인

workspace 패키지를 참조하는 프로젝트에서는 로컬 패키지가 실제로 존재하는지 확인합니다.

예:

{
  "dependencies": {
    "@taskflow/shared": "workspace:*"
  }
}

그런데 packages/shared 또는 해당 name의 workspace가 없다면 설치가 실패할 수 있습니다.

workspace:* 사용
→ 실제 workspace 존재 확인
→ package.json name 확인
→ pnpm-workspace.yaml 포함 여부 확인

8. registry와 network는 별도 문제

패키지를 찾지 못하거나 다운로드에 실패하는 경우 workspace와 다른 범주일 수 있습니다.

pnpm config get registry

회사 네트워크, 프록시, 사설 registry를 사용하는 경우 해당 설정을 확인합니다.

인증 토큰이 포함된 설정을 본문이나 로그에 그대로 공유하지 않습니다.

9. 설치 script 오류 확인

패키지를 내려받는 단계는 성공했지만 postinstall이나 native build script가 실패할 수도 있습니다.

이 경우 “pnpm install 실패”라는 결과만 보고 lockfile을 수정하면 안 됩니다.

로그에서 실패한 script 이름과 패키지를 먼저 찾습니다. pnpm의 의존성 build script 승인 정책에 의해 실행이 차단된 경우도 구분합니다. 필요한 script와 정확한 패키지 버전을 검토한 뒤 해당 lab 범위에서만 허용합니다. 예제 Storybook lab은 esbuild@0.28.2만 allowBuilds로 허용하며, 모든 패키지 script를 일괄 허용하지 않습니다.

10. 캐시와 node_modules 정리는 마지막

설정과 의존성 상태가 맞는데 로컬 설치 결과가 손상된 정황이 있을 때 정리를 고려합니다.

Windows PowerShell 예시:

Remove-Item -Recurse -Force node_modules
pnpm install

하지만 이 단계 전에 반드시 원인을 확인합니다.

pnpm store 자체를 지우는 작업은 더 넓은 영향을 주므로 근거 없이 반복하지 않습니다.

오류 해결 체크리스트

현재 workspace 루트인가
Node.js 버전 확인
pnpm 버전 확인
packageManager 확인
pnpm-workspace.yaml 확인
workspace package name 확인
package.json 변경 확인
pnpm-lock.yaml diff 확인
registry/network 확인
install script 첫 실패 확인
필요할 때만 node_modules 정리
같은 명령으로 재검증

자주 발생하는 실수

lockfile부터 삭제합니다

원인과 변경 이력을 먼저 확인합니다.

workspace root와 app 폴더를 혼동합니다

Get-Location 또는 pwd로 현재 위치를 확인합니다.

npm과 pnpm을 섞습니다

TaskFlow 루트에서는 pnpm만 사용합니다.

오류 로그의 마지막 줄만 봅니다

실제 원인은 더 앞의 첫 실패 지점에 있을 수 있습니다.

학습 완료 체크리스트

  • pnpm install 오류를 설정·workspace·network·script 문제로 구분할 수 있습니다.
  • packageManager와 실제 pnpm 버전을 비교할 수 있습니다.
  • pnpm-workspace.yaml과 실제 폴더 구조를 비교할 수 있습니다.
  • lockfile을 삭제하기 전에 diff를 확인합니다.
  • workspace:* 참조가 실제 패키지와 연결되는지 확인할 수 있습니다.
  • clean install 후 dev와 lint까지 검증합니다.

독립 실습: workspace 누락 원인 분리

작은 workspace 전체 파일을 별도 폴더에 준비한 뒤 아래 순서로 비교합니다. 프로젝트 앱은 필요하지 않습니다.

pnpm install
pnpm --filter @practice/hello hello

정상 상태에서는 workspace connected가 출력됩니다. pnpm-workspace.yaml의 apps/*를 app/*로 바꾼 사본에서 같은 filter 명령을 실행하면 일치하는 프로젝트가 없다는 진단을 볼 수 있습니다. 실제 폴더는 apps/hello이므로 패턴을 apps/*로 복구하고 pnpm install 뒤 같은 명령을 다시 실행합니다. 이 경우에는 registry 변경이나 lockfile 삭제가 해결책이 아닙니다. lockfile 불일치는 별도의 문제이며 아래 진단 절에서 첫 오류와 manifest 변경을 비교합니다.

변형 과제: 패키지 폴더 이름과 package.json의 name을 각각 다르게 바꾸었을 때 workspace 패턴 문제와 filter 이름 문제를 어떻게 구분할지 설명합니다.

선택 실습: 같은 프로젝트로 연습하기

TaskFlow는 작업을 관리하는 예제 앱입니다. 이 선택 실습에서는 앱을 실행·개발하는 환경과 설정을 준비합니다.

이번 글에서는 TaskFlow 메인 프로젝트의 설치 재현성을 복구하는 순서를 정리합니다.

선택: 연재 프로젝트와 전체 자료

연재 프로젝트를 이어 만드는 분을 위한 자료입니다. 이 글의 개념과 예제만 찾으셨다면 필요한 파일과 실행 방법만 펼쳐보세요.

TaskFlow 프로젝트 적용

시작 체크포인트: 이전 글의 적용·완료 확인과 이전 회차 시작 ZIP을 기준으로 아래 변경 파일을 수정합니다. 메인 앱은 루트에서 실행하고, labs는 해당 폴더의 package.json과 잠금 파일을 기준으로 따로 실행합니다.

이전 완료본과 달라진 파일: docs/development-environment.md, README.md. 전체 코드에서 같은 경로를 찾아 기존 내용을 대조합니다. ZIP의 자동 생성 lockfile도 해당 패키지 폴더와 함께 유지합니다.

이번 글에서는 TaskFlow 메인 프로젝트의 설치 재현성을 복구하는 순서를 정리합니다.

1회차에서 pnpm workspace를 구성한 상태를 기준으로 합니다.

package.json
pnpm-workspace.yaml
pnpm-lock.yaml
apps/web
labs/*

TaskFlow clean install 검증

최종적으로 새 설치 상태를 확인합니다.

pnpm install
pnpm --filter @taskflow/web dev
pnpm --filter @taskflow/web lint

개발 서버와 lint가 모두 정상 동작해야 환경 복구가 끝난 것입니다.

이 글을 읽고 바로 확인할 것

독자 질문: pnpm install 실패에서 workspace와 lockfile 문제를 어떻게 구별하나요?

얻을 결과: 루트 경로·packageManager·workspace 범위·잠금 파일 불일치를 순서대로 확인할 수 있습니다.

직접 따라 할 순서

  1. 현재 경로와 루트의 package.json, pnpm-workspace.yaml을 확인합니다.
  2. 오류에 나온 패키지 이름을 각 workspace의 package.json과 대조합니다.
  3. 원인을 수정하고 잠금 파일을 유지한 pnpm install --frozen-lockfile, pnpm lint, pnpm build를 다시 확인합니다.

확인 결과 기준: 같은 설치 명령이 새 환경에서도 통과해야 복구로 판단합니다. lockfile 삭제는 원인 확인 전 실행하지 않습니다.

편집 검증 범위: 이번 보강에서 위 명령과 화면은 다시 실행하지 않았습니다(미확인). 본문 아래의 기존 실행 검증표는 이전 작업에서 기록한 결과이며, 독자는 자신의 환경에서 위 기준으로 확인해 주세요.

다음 학습: Tailwind CSS Unknown at rule 경고 해결: VS Code와 PostCSS 설정 확인

이전 체크포인트

dev-env-step-06-npm-eresolve-fixed

현재 상태

npm 오류 lab은 복구됐지만 TaskFlow 메인 pnpm 환경의 재현성 기준을 최종 확인하지 않았습니다.

이번 변경

workspace 진단 순서 문서화
packageManager 기준 확인
lockfile diff 확인 절차 추가
clean install 검증 절차 추가

변경 파일

package.json
pnpm-workspace.yaml
pnpm-lock.yaml
docs/development-environment.md

실제 파일은 오류 원인에 따라 필요한 부분만 수정합니다.

실행 확인

pnpm install
pnpm --filter @taskflow/web dev
pnpm --filter @taskflow/web lint

완료 체크포인트

dev-env-step-07-pnpm-recovery
전체 파일·코드 보기

실습 프로젝트 전체 코드

아래는 이번 회차 완료 시점의 전체 소스입니다. 파일 경로는 압축을 푼 체크포인트 폴더를 기준으로 합니다. 자동 생성되는 lockfile은 ZIP에 포함하며, node_modules·빌드 결과·실제 비밀값은 포함하지 않습니다. 메인 앱과 각 lab은 별도의 설치 범위를 유지합니다.

.gitignore

node_modules/
dist/
storybook-static/
.env.local
.env.*.local

apps/web/.env.example

VITE_API_URL=https://api.example.invalid
VITE_APP_NAME=TaskFlow

apps/web/eslint.config.js

import js from '@eslint/js';
import { defineConfig } from 'eslint/config';
import globals from 'globals';

export default defineConfig([
  { ignores: ['dist/**'] },
  js.configs.recommended,
  {
    files: ['src/**/*.js'],
    languageOptions: { globals: globals.browser },
    rules: { 'no-console': 'warn' },
  },
]);

apps/web/index.html

<!doctype html>
<html lang="ko">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>TaskFlow 개발환경</title></head>
<body><main id="app"></main><script type="module" src="/src/main.js"></script></body>
</html>

apps/web/package.json

{
  "name": "@taskflow/web",
  "private": true,
  "type": "module",
  "scripts": {
    "dev": "vite --host 127.0.0.1",
    "build": "vite build",
    "lint": "eslint ."
  },
  "devDependencies": {
    "vite": "8.3.0",
    "eslint": "10.11.0",
    "@eslint/js": "10.0.1",
    "globals": "17.12.0"
  }
}

apps/web/src/config/env.js

const apiUrl = import.meta.env.VITE_API_URL;
const appName = import.meta.env.VITE_APP_NAME;

if (!apiUrl) {
  throw new Error('VITE_API_URL 환경 변수가 필요합니다.');
}

export const env = {
  apiUrl,
  appName: appName || 'TaskFlow',
};

apps/web/src/main.js

import './style.css';
import { env } from './config/env.js';

const app = document.querySelector('#app');
const title = document.createElement('h1');
title.textContent = env.appName;
const status = document.createElement('p');
status.textContent = '개발환경 스타터가 실행 중입니다.';
const api = document.createElement('p');
api.id = 'api-url';
api.textContent = `API URL: ${env.apiUrl}`;
app.append(title, status, api);

apps/web/src/style.css

body { margin: 0; color: #202020; background: #f6f6f6; font: 16px/1.6 system-ui, sans-serif; }
main { max-width: 720px; margin: 64px auto; padding: 24px; }
h1 { font-size: 30px; font-weight: 500; }
p { overflow-wrap: anywhere; }

docs/development-environment.md

# TaskFlow 개발환경

이 스타터는 개발환경 진단을 위한 최소 Vite/vanilla JavaScript 앱입니다. 할 일 관리 기능이나 API 서버는 포함하지 않습니다.

Node.js 24.19.0, pnpm 11.19.0으로 검증했습니다. 루트는 pnpm만 사용하며 apps/*만 workspace입니다. labs의 npm/Yarn/pnpm 실습은 독립 프로젝트입니다.

## 2회차

메인 앱은 pnpm을 유지합니다. labs/yarn-modern은 독립 Yarn 실습입니다.

## 3회차

apps/web/.env.example을 apps/web/.env.local로 복사합니다. .invalid 주소는 표시만 하며 실제 API 호출은 하지 않습니다. 공개 샘플값만 제공하고 로컬 파일은 ZIP에서 제외합니다.

## 4회차

Vite 루트는 apps/web입니다. env.js가 필수 VITE_API_URL을 검사하고 화면에 공개 URL을 표시합니다.

## 5회차

ESLint 설정과 의존성은 apps/web에 있습니다. 루트 pnpm lint가 앱의 eslint .을 호출합니다.

## 6회차

npm ERESOLVE 실습은 labs/npm-eresolve에서 실행합니다. 최종본은 react와 react-dom 19.3.0 호환 조합입니다.

## 7회차

설치 오류는 경로 → Node/pnpm 버전 → workspace → package.json → lockfile 순으로 확인합니다. 새 폴더에서 pnpm install --frozen-lockfile로 재현합니다.

package.json

{
  "name": "taskflow",
  "private": true,
  "packageManager": "pnpm@11.19.0",
  "engines": {
    "node": ">=24"
  },
  "scripts": {
    "dev": "pnpm --filter @taskflow/web dev",
    "build": "pnpm --filter @taskflow/web build",
    "lint": "pnpm --filter @taskflow/web lint"
  }
}

pnpm-workspace.yaml

packages:
  - "apps/*"

README.md

# TaskFlow 개발환경 07 완료 체크포인트

Node.js 24.19.0 / pnpm 11.19.0 검증 기준입니다. pnpm을 별도로 설치한 환경에서 실행하세요. ZIP에는 node_modules, dist, 로컬 환경 변수, 실제 비밀값이 없습니다.

1. 이 폴더에서 `pnpm install --frozen-lockfile`
2. PowerShell: `Copy-Item apps/web/.env.example apps/web/.env.local` 또는 macOS/Linux: `cp apps/web/.env.example apps/web/.env.local`
3. `pnpm dev` 후 http://127.0.0.1:5173 확인
4. `pnpm build`
5. `pnpm lint`

apps/web가 Vite 루트입니다. 환경 변수도 이 폴더에 둡니다. 표시용 API 주소에 실제 요청을 보내지 않습니다. labs는 메인 workspace에서 제외되어 각 폴더에서 별도 설치합니다.

원문 단계별 전체 파일과 실행 검증 범위는 docs/development-environment.md를 확인하세요.

labs/yarn-modern/.yarnrc.yml

nodeLinker: node-modules

labs/yarn-modern/package.json

{
  "name": "taskflow-yarn-lab",
  "private": true,
  "type": "module",
  "packageManager": "yarn@4.18.0",
  "scripts": {
    "dev": "node src/main.js",
    "lint": "node --check src/main.js"
  }
}

labs/yarn-modern/src/main.js

console.log('TaskFlow Yarn 독립 실습');

labs/npm-eresolve/package.json

{
  "name": "taskflow-npm-eresolve",
  "private": true,
  "type": "module",
  "packageManager": "npm@11.16.0",
  "scripts": {
    "test": "node verify.mjs"
  },
  "dependencies": {
    "react": "19.3.0",
    "react-dom": "19.3.0"
  }
}

labs/npm-eresolve/README.md

# npm ERESOLVE 실습

이 폴더에서만 npm을 사용합니다.

오류 재현: `npm install react@18.3.1 react-dom@19.3.0 --save-exact`

복구: `npm install react@19.3.0 react-dom@19.3.0 --save-exact`

검증: `npm ls react react-dom`, `npm test`

react-dom 19.3.0의 peerDependencies는 react ^19.3.0입니다. 최종 package.json은 복구된 상태입니다.

labs/npm-eresolve/verify.mjs

import { createElement } from 'react';
import { renderToString } from 'react-dom/server';
import assert from 'node:assert/strict';
const html = renderToString(createElement('p', null, 'TaskFlow'));
assert.equal(html, '<p>TaskFlow</p>');
console.log('React 서버 렌더링 통과');

실행 검증 결과

검증 환경: Windows · Node.js 24.19.0 · pnpm 11.19.0 · Vite 8.3.0 · ESLint 10.11.0.

항목 확인 결과
메인 앱 pnpm install --frozen-lockfile 성공
메인 앱 pnpm build 성공
메인 앱 pnpm lint 성공
메인 앱 설치 재현 lockfile을 유지한 새 설치와 lint·build 확인

메인 앱의 개발 서버 응답과 환경 변수 변환은 1·4·5·11회차에서 대표 확인했습니다. 선택 lab과 에디터 기능은 위에 표시한 범위만 검증했으며, 운영 배포 검증은 포함하지 않습니다.

다음 학습

다음 글부터는 선택 도구 문제를 다룹니다.

먼저 Tailwind CSS의 Unknown at rule 경고를 재현하고, 실제 빌드 실패와 VS Code 에디터 경고를 구분합니다.

다음 글: Tailwind CSS Unknown at rule 경고 해결: VS Code와 PostCSS 설정 확인

공식 문서

체크포인트 다운로드

dev-env-step-07-pnpm-recovery 완료 ZIP 다운로드

이전 회차 시작 체크포인트 ZIP

글 소개·학습 준비·전체 목차
pnpm 설치 오류 점검을 표현한 패키지와 돋보기, 곰 표지

개발환경 · 7 / 11 · 오류 해결 · pnpm install

pnpm install이 실패하면 node_modules와 pnpm-lock.yaml을 바로 삭제하기보다 “지금 어느 workspace에서 어떤 설정을 기준으로 설치하고 있는지”부터 확인해야 합니다.

바로 점검하기: 실패한 프로젝트의 설치 로그와 package.json을 준비하세요. 아래 진단은 TaskFlow 이전 회차 없이 현재 프로젝트에서 시작할 수 있습니다. 첫 오류 메시지에 맞는 항목부터 확인합니다.

원인을 좁힌 뒤 같은 설치 명령으로 다시 확인합니다. 작은 예제로 비교하려면 workspace 누락 독립 실습으로 이동하세요.

이번 글에서 배우는 내용

  • pnpm install 오류를 분류하는 방법
  • 현재 실행 경로 확인
  • packageManager와 pnpm 버전 확인
  • pnpm-workspace.yaml 확인
  • lockfile 변경 여부 확인
  • workspace 패키지 경로 문제
  • registry와 network 오류 분리
  • 캐시와 node_modules 정리를 마지막 단계로 두는 이유
  • clean install 검증

선수 지식

현재 프로젝트의 package.json·설치 로그를 준비합니다. workspace를 사용하는 경우 pnpm-workspace.yaml과 패키지 폴더도 확인합니다. 아래 진단에는 TaskFlow 이전 회차가 필요하지 않습니다. 작은 workspace로 재현하려는 독자는 독립 실습에 연결된 전체 파일을 사용합니다.

Node.js·pnpm 설치와 공통 실행 기준은 pnpm 환경 준비에서 확인합니다.

목차

  1. 먼저 오류 종류를 구분하기
  2. 1. 현재 폴더 확인
  3. 2. pnpm 버전 확인
  4. 3. pnpm-workspace.yaml 확인
  5. 4. 각 workspace의 package.json 확인
  6. 5. lockfile을 무조건 삭제하지 않기
  7. 6. frozen lockfile 오류
  8. 7. workspace 의존성 확인
  9. 8. registry와 network는 별도 문제
  10. 9. 설치 script 오류 확인
  11. 10. 캐시와 node_modules 정리는 마지막
  12. 오류 해결 체크리스트
  13. 자주 발생하는 실수
  14. 학습 완료 체크리스트
  15. 독립 실습: workspace 누락 원인 분리
  16. TaskFlow 프로젝트 적용
  17. TaskFlow clean install 검증
  18. 이 글을 읽고 바로 확인할 것
  19. 실습 프로젝트 전체 코드
  20. 실행 검증 결과
  21. 다음 학습
  22. 공식 문서

이 글이 도움이 되었나요?

조회 중

읽음 기록

읽음 — / 전체 11개 · 필수 6개

이 글을 쓴 해비

웹사이트를 제작·운영하고, 개인 서비스와 자동화·AI 도구를 만듭니다. 직접 만들며 배운 내용과 문제 해결 과정을 BlogFlow에 기록합니다.

새 글 받아보기

RSS 리더에서 BlogFlow의 새 글을 확인할 수 있습니다.

RSS 피드 구독하기

댓글 남기기