# Mole에서 npm cache verify보다 캐시를 적게 지우는 이유

> npm 캐시 복사본으로 정리 기준을 비교하고, Go 캐시의 보관 기간과 전역 도구·이전 Xcode 프로젝트에 남은 빌드 산출물을 살펴봅니다.

Published: 2026-10-05

최근 한 사용자가 Mole로 Mac을 관리한 뒤에도 npm 캐시가 남았고, 직접 정리하니 8 GB에서 2 GB로 줄었다고 알려주었습니다. 이 일을 계기로 개발 도구의 캐시를 다시 살펴봤습니다. 아직 쓰는 파일, 참조가 사라진 파일, 도구가 이미 자체적으로 정리하는 파일을 구분하지 않으면 다음 빌드만 느려질 수 있습니다.

이 글의 조사와 변경은 10월 5일에 이루어졌습니다. 코드는 반영됐지만 현재 공개된 Preview 버전에는 포함되지 않았으며, 이후 버전으로 제공할 예정입니다.

## npm 캐시가 계속 커지는 이유

npm의 기본 캐시는 `~/.npm/_cacache`입니다. `content-v2`에는 패키지와 레지스트리 응답을 저장하고, `index-v5`는 요청과 내용을 연결합니다. 파일 이름은 내용의 해시이며, 여러 인덱스 항목이 같은 파일을 참조할 수 있습니다.

패키지 정보가 바뀌면 새 응답을 저장합니다. 이후 조회에서 이전 인덱스 항목이 정리돼도 내용 파일은 남을 수 있어, 참조 없는 파일이 쌓입니다. [npm 문서](https://docs.npmjs.com/cli/v11/commands/npm-cache/)도 캐시가 데이터를 스스로 삭제하지 않으며 설치할수록 커진다고 설명합니다.

사용자는 이미 캐시를 정리한 상태라 정리 전 복사본도, 정확히 실행한 명령도 확인할 수 없었습니다. 8 GB에서 2 GB로 줄었다는 보고는 조사의 출발점이지, Mole로 6 GB를 회수했다는 측정 결과나 그 모두가 참조 없는 내용이었다는 증거는 아닙니다.

## 이번 실험에서 verify가 삭제한 파일

실험에는 이 Mac의 캐시 복사본과 npm 11.19.1, cacache 20.0.4를 사용했습니다. 원본은 바꾸지 않았습니다. 생성된 지 약 하루 된 캐시로 저장된 데이터는 309796162바이트였으며, 몇 달간 쌓인 캐시와는 다릅니다.

| 기준 | 내용 파일 수 | 내용 바이트 수 |
| --- | --- | --- |
| 유효한 인덱스 항목 어디에서도 참조하지 않음 | 1 | 614295 |
| `npm cache verify`가 실제로 삭제 | 6 | 25469972 |

[cacache의 verify 구현](https://github.com/npm/cacache/blob/v20.0.4/lib/verify.js)은 내용을 정리하고 무결성을 확인한 뒤 인덱스를 다시 만듭니다. 같은 키에서는 마지막 항목만 남기지만, 이전 항목에도 다른 요청이 쓰는 전체 메타데이터와 축약 메타데이터가 있을 수 있습니다. 단순히 같은 응답의 구버전과 새 버전은 아닙니다.

복사본에서 verify가 삭제한 내용 중 11199796바이트는 다른 요청 형태의 유효한 항목이 여전히 참조하고 있었습니다. 정리 전에 오프라인으로 읽던 일부 패키지 정보가 이후 오프라인 `npm view`에서 `ENOTCACHED`를 반환했습니다. 온라인에서는 다시 받을 수 있어도 캐시가 하던 일이 달라진 것입니다.

Mole에서는 유효한 인덱스 항목이 하나라도 참조하는 파일은 남기기로 했습니다. 이 표본에서 약 0.6 MB만 찾았더라도 verify의 수치에 맞추려고 쓸 수 있는 내용까지 지우지는 않습니다.

## 참조 없는 파일은 묶어서 표시하고 전체 캐시는 직접 선택

새 구현은 기본 경로인 `~/.npm/_cacache`만 조사합니다. 참조가 없고 하루가 지난 내용을 정리 화면의 개발 도구 그룹에 한 줄로 표시하며 기본 선택합니다. npm 캐시 전체를 삭제하려면 계속 직접 확인해야 하며, 겹친 선택의 용량은 한 번만 계산합니다.

`npm install`, `npm ci`처럼 캐시에 쓰는 명령이 실행 중이면 해당 파일을 정리 목록에 표시하지 않습니다. 인덱스를 읽을 수 없어도 표시하지 않으며, 삭제 전에 참조를 다시 확인합니다. 인덱스 파일과 임시 디렉터리는 바꾸지 않고, Mole에서 백그라운드로 npm 정리 명령을 실행하지도 않습니다.

인덱스가 참조하는 내용을 남긴다고 모든 프로젝트의 오프라인 빌드가 보장되지는 않습니다. 잠금 파일이 해시로 패키지를 직접 찾을 수도 있고, 비공개 레지스트리와 오래된 버전을 다시 받을 수 있다는 보장도 없습니다. 소스, 잠금 파일, 다시 만들 수 없는 산출물은 별도로 보관해야 합니다. 사용자 지정 npm 캐시 경로도 이번 변경의 대상이 아닙니다.

## Go, Cargo, pnpm은 각각 판단한다

Go는 이미 빌드 캐시를 자동 정리합니다. [구현](https://go.dev/src/cmd/go/internal/cache/cache.go)은 최근 5일간 쓴 항목을 보존하고 1시간의 여유를 더해 121시간을 기준으로 삼습니다. 기존 Mole에서는 빌드 캐시 디렉터리 전체를 기본 정리 대상으로 삼았지만, 이번에 같은 시간 기준으로 좁혔습니다. 최근에 쓴 항목은 남겨 다음 빌드에서 다시 컴파일할 일을 줄입니다.

Cargo에는 [자동 캐시 정리](https://doc.rust-lang.org/cargo/reference/config.html#cache)가 있으며 이번 표본에는 기한이 지난 내용이 없었습니다. 이전에 압축을 푼 레지스트리 소스를 삭제하자 약 29시간 뒤 약 157 MB를 다시 내려받고 약 1.06 GB를 풀었습니다. Mole에서는 이 저장소에 별도의 자동 정리를 추가하지 않으며, 직접 확인해서 선택하는 기존 정리 항목은 그대로 유지합니다.

pnpm의 공유 저장소는 또 다릅니다. 조사한 APFS 표본에서는 하드 링크 수로 미사용 여부를 증명할 수 없었고, 그 기준을 옮기면 저장소 전체가 선택됐습니다. 이번에는 pnpm 자동 정리 기능을 추가하지 않았습니다. 하드 링크 수를 정리 기준으로 쓰려면 해당 파일 시스템에서 실제 사용 여부를 나타내는지 먼저 확인해야 합니다.

## 전역 도구와 오래된 Xcode 프로젝트의 빌드 산출물

전역 설치된 `pake-cli` 안에 약 1.48 GiB의 `src-tauri/target`이 있었습니다. Tauri를 빌드하며 남은 Rust 산출물이지 npm 다운로드 캐시가 아닙니다. 도구가 쓴 유효한 `CACHEDIR.TAG`를 가진 이런 빌드 디렉터리도 검토 대상으로 표시합니다. 도구 본체와 `node_modules` 의존성은 남기며, Rust 빌드가 실행 중이면 처리하지 않습니다.

Xcode에서는 기록된 프로젝트 경로가 없어진 DerivedData 24개, 조사 당시 약 9 GiB를 찾았습니다. 시동 디스크에서 프로젝트가 사라졌음을 확인하고, Xcode가 해당 캐시를 적어도 2주간 쓰지 않았을 때만 디렉터리 전체를 정리 목록에 표시합니다. 외장 디스크가 연결되지 않았거나 읽기 권한이 없는 상태는 프로젝트 삭제의 증거가 아닙니다. 이 용량은 당시 조사 결과로, 모든 Mac의 회수량을 약속하지 않으며 필요하면 다시 빌드하는 시간도 듭니다.

## 직접 정리하기 전에 대상 캐시부터 확인

다음 읽기 전용 명령으로 사용자 지정 설정을 포함한 실제 npm 캐시 경로를 확인할 수 있습니다.

```bash
npm config get cache
```

설치와 빌드가 캐시에 쓰지 않는지 확인한 뒤 `npm cache verify` 실행 여부를 결정합니다. 이 명령은 조회만 하는 것이 아니라 캐시를 실제로 변경합니다. 프로젝트의 `node_modules`와 전역 명령은 별도의 영역이라 이 명령으로 정리되지 않습니다. 전체 순서는 [개발 도구 캐시 정리](https://mole.fit/ko/blog/how-to-clear-dev-caches-mac)에 담았습니다.

---

Canonical HTML page: https://mole.fit/ko/blog/mole-developer-cache-gc
Blog index for agents: https://mole.fit/ko/blog/llms.txt
Site index for agents: https://mole.fit/llms.txt
