# 빌드를 깨지 않고 개발자 캐시 비우기

> 패키지 저장소와 의존성 트리를 정리하기 전에 소스, lockfile, 레지스트리 접근, 고유 로컬 아티팩트를 보존한다.

Published: 2026-06-03 | Updated: 2026-08-08

개발자 저장 공간은 패키지 다운로드, 빌드 결과물, SDK, 로컬
데이터베이스, 프로젝트별 의존성 트리에 걸쳐 흩어져 있습니다. 어떤 것은 재현 가능하고, 어떤 것은
나중에 사라질 수 있는 레지스트리와 락파일에 의존하며, 어떤 것은 고유한 로컬 데이터입니다. 안전한
정리는 모든 점(.) 폴더를 캐시로 가정하지 않고, 발견한 항목이 어느 종류인지 확인합니다.

## 도구별 전역 캐시

각 패키지 관리자는 직접 측정할 수 있는 전역 저장소를 유지합니다.

```
du -sh ~/.npm ~/.cargo ~/.cache/pip ~/Library/Caches/pip ~/.gradle 2>/dev/null | sort -h
```

이들은 기본값일 뿐 보장된 경로는 아닙니다. 가능하면 도구에 설정된 경로를 확인하세요. 예를 들어
`npm config get cache`, `python -m pip cache dir`,
`pnpm store path`입니다.

- **npm**은 기본적으로 `~/.npm`에 다운로드를 캐시합니다. 먼저
  [`npm cache verify`](https://docs.npmjs.com/cli/commands/npm-cache)를 사용하세요. npm은
  캐시를 자가 복구형으로 설명하므로, `npm cache clean --force`는 주로 의도적인
  공간 확보나 문제 해결용입니다.
- **Cargo**는 레지스트리와 git 체크아웃을 `~/.cargo` 아래에 두지만,
  [Cargo home](https://doc.rust-lang.org/cargo/guide/cargo-home.html)에는
  설치된 바이너리, 설정, 패키지 기록, 레지스트리 자격 증명도 포함될 수 있습니다.
  현재 Cargo는 빌드 및 fetch 명령 중에 사용하지 않는 전역 캐시 항목을 주기적으로
  제거합니다. 그 정책을 따르거나 정확한 캐시 하위 디렉터리를 확인하세요.
  `~/.cargo` 전체를 삭제하지 마세요.
- **pip**는 기본적으로 `~/Library/Caches/pip`에 휠과 HTTP 응답을 캐시합니다.
  `python -m pip cache info`는 실제 위치와 크기를 보고하고,
  [`python -m pip cache purge`](https://pip.pypa.io/en/stable/cli/pip_cache/)는
  이를 비웁니다.
- **pnpm**과 **yarn**은 각자의 저장소를 유지합니다. `pnpm store prune`과
  [`yarn cache clean`](https://yarnpkg.com/cli/cache/clean)은 참조되지 않거나
  캐시된 패키지를 정리합니다. 저장소 레이아웃과 로컬·전역 캐시 동작이 다르므로
  사용 중인 패키지 관리자 버전을 확인하세요.
- **Gradle**과 **Maven**(`~/.gradle`, `~/.m2`)은 Android 및 JVM Mac에서 매우 커질 수 있습니다.
  Gradle은 이미
  [주기적 캐시 정리](https://docs.gradle.org/current/userguide/directory_layout.html)를
  수행합니다. 수동으로 검토하기 전에 데몬을 중지하세요. Maven 저장소에는 다시 다운로드할 수 없는
  로컬 빌드 또는 비공개 아티팩트가 있을 수 있으므로, 기본적으로 전체 저장소를 삭제하기보다
  먼저 확인하세요.

비용에는 대용량 다운로드, 네이티브 재빌드, 또는 레지스트리 버전이 사라진 뒤 실패한 과거 빌드가
포함될 수 있습니다. 저장소를 재현 가능하다고 말하기 전에 각 의존성의 락파일과 출처를
확인하세요.

## 흩어진 node_modules 문제

더 큰 놀라움은 보통 단일 캐시가 아니라, 한 번이라도 다룬 모든 JavaScript 프로젝트에 흩어진
`node_modules` 폴더입니다. 각각이 독립적이며 종종 200~500 MB에 달하므로, 오래된 프로젝트 열 개면
수 기가바이트를 숨길 수 있습니다. 위치와 크기를 찾으세요.

```
find ~/www ~/Projects -name node_modules -type d -prune -exec du -sh {} + 2>/dev/null
```

예시 루트를 프로젝트를 두는 폴더로 바꾸세요. `-prune`은 일치한 의존성 트리 안으로
`find`가 내려가지 않게 하고, `-exec`는 경로의 공백과 특수 문자를 안전하게 처리합니다. 프로젝트는
소스, 락파일, 패키지 관리자 버전, 레지스트리 접근, 필요한 네이티브 툴체인이 여전히 있을 때만
의존성을 다시 빌드할 수 있습니다. 이런 입력을 보전한 뒤 `npm ci`처럼 락파일 전용 명령을
우선 사용하세요.

## 삭제하지 말아야 할 것

패키지 캐시는 대체 가능할 수 있지만, 옆의 두 가지는 그렇지 않습니다. 프로젝트 **소스와 락파일**
(`package.json`, `package-lock.json`, `Cargo.lock`)은 캐시가 아니라 빌드를 정의하므로
절대 일괄 삭제하지 마세요. 그리고 여러 프로젝트가 공유하는 pnpm 콘텐츠 주소 저장소처럼
지금 사용 중인 전역 저장소는 다시 다운로드될 뿐이지만, 설치 중에 삭제하면 손상될 수 있으므로
빌드가 돌지 않을 때 캐시를 비우세요.

## 내부 구조: 콘텐츠 주소 저장소, 그리고 node_modules가 예외인 이유

많은 패키지 관리자는 반복 다운로드를 줄이기 위해 콘텐츠 주소 저장소를 사용합니다. pnpm은
모든 패키지 버전의 전역 저장소 하나를 두고 각 프로젝트의 `node_modules`로 하드 링크하므로,
같은 라이브러리를 쓰는 프로젝트 열 개가 디스크상 한 사본을 공유합니다. Cargo와 Go 캐시도
다운로드한 내용을 버전 또는 체크섬으로 키잉합니다. 이는 무결성을 지키지만 향후 가용성을
보장하지는 않습니다. 일반적인 npm 설치는 프로젝트마다 의존성 트리를 실체화하고, pnpm은
프로젝트를 공유 저장소에 연결할 수 있습니다. 그래서 하나의 `node_modules` 디렉터리를 지우는 것과
공유 저장소를 prune하는 것의 영향 범위가 다릅니다.

<figure class="blog-diagram">
  <img src="https://mole.fit/img/blog/content-addressed-store.webp" width="1360" height="454" loading="lazy" alt="왼쪽은 여러 프로젝트에 하드 링크된 하나의 공유 전역 저장소이고, 오른쪽은 모든 프로젝트의 node_modules에 복사되어 중복된 같은 라이브러리입니다">
  <figcaption>공유 콘텐츠 주소 저장소와 프로젝트별 실체화된 의존성 트리는 저장 비용과 정리 경계가 다릅니다.</figcaption>
</figure>

## 탐색에는 맵, 정리에는 패키지 관리자

흩어져 있다는 점이 곧 탐색 문제입니다. [Mole](https://mole.fit/)의 Analyze 뷰 같은 트리맵은 어느 프로젝트나
저장소가 큰지 보여 줄 수 있지만, 패키지 관리자 자체의 verify, prune, clean 명령이
인덱스와 참조를 이해합니다. 맵으로 대상을 고르고, 소유 도구로 변경하세요.

## 안전한 작업 순서

빌드와 데몬을 중지하고, 선택한 프로젝트 루트를 측정하고, 패키지 관리자 저장소를 확인한 뒤,
의존성 트리를 제거하기 전에 소스와 락파일을 보전하세요. 홈 디렉터리의 점(.) 폴더 전체를
삭제하기보다 문서화된 prune 명령을 사용하세요. 휴지통을 비우기 전에 프로젝트 하나를 다시
빌드해 보세요. 목적은 재현 가능한 결과물을 제거하면서, 다시 재현하는 데 필요한 정보는
남기는 것입니다.

---

Canonical HTML page: https://mole.fit/ko/blog/how-to-clear-dev-caches-mac
Blog index for agents: https://mole.fit/ko/blog/llms.txt
Site index for agents: https://mole.fit/llms.txt
