

안 쓰는 파일, 흔히 말하는 유령 파일들 때문에 생각보다 많이 고생했습니다.
파일은 계속 늘어나는데,
이게 지금도 쓰이고 있는 건지, 예전에 쓰다 남은 건지 도무지 알 수가 없었죠...
지워도 될 것 같으면서도, 혹시라도 어딘가에서 쓰고 있으면 어쩌나 계속 망설이게 됐다.
그래서 찾기로했습니다...“이런 걸 정리해 주는 라이브러리 하나쯤은 있지 않을까?”
그렇게 찾다 보니 눈에 들어온 게 바로 Knip이었습니다.
knip은 JS/TS 프로젝트 내에서 사용되지 않은 파일, 의존성, export, 타입을 자동으로 찾아주는 도구입니다.
🙃 제가 회사에서 레거시 프로젝트를 유지보수하게 되었습니다!! (열정 가득)
처음에는 아주 의욕적으로 시작했습니다!
리팩토링을 통해 충분히 개선할 수 있을 거라고 생각했고, 조금만 정리하면 되겠지~ 라는 생각으로 했습니다.

하지만 코드를 하나하나 살펴볼수록,
안 쓰는 파일들이 예상보다 훨씬 많이 쌓여 있다는 걸 알게 되었죠.
그래서 그때부터 파일이 실제로 사용되고 있는지,
과거에 쓰이다 남은 코드인지 판단하는것에 아주 많은 시간을 사용했습니다!
생각보다 아주 힘든 작업입니다ㅜㅠ

그 프로젝트는 여러 차례 릴리즈와 어싸인 인원이 바뀌면서 안 쓰는 파일/의존성/export가 계속 쌓인, 전형적인 레거시 프로젝트 였습니다.
이로 인해 발생하는 문제들...
그래서 이번에 knip을 레거시 코드에 직접 적용해 보았습니다.
Knip은 설치부터 실행까지 과정이 꽤 단순한 편입니다.
상황에 따라 아래 방식 중 하나를 선택해서 사용할 수 있습니다.
# 1) 설치 없이 일회성 실행
npx knip
# 2) 개발 의존성으로 설치 후 실행
npm i -D knip typescript @types/node
npx knip
# 3) 스크립트로 등록
# package.json
{
"scripts": {
"knip": "knip"
}
}
저는 처음에는 설치 없이 npx knip으로 가볍게 실행해 보면서
프로젝트 상태를 한 번 훑어보는 용도로 사용했습니다.
npx knip
npx knip --production
npx knip --strict
(--strict 옵션은 --production 모드를 포함)
처음 한 번 돌렸을 때 이런 결과를 받았다.
Unused files (144)
프로젝트 규모가 큰 만큼 테스트용 컴포넌트, 기획 변경으로 사라진 훅/유틸 등이 정말 많이 남아있더라구요....
| Category | 설명 | Key |
|---|---|---|
| Unused files | 어디에서도 import되지 않는 파일 | files |
| Unused dependencies | dependencies 중 코드에서 사용되지 않음 | dependencies |
| Unused devDependencies | devDependencies 중 사용되지 않음 | dependencies |
| Referenced optional peerDependencies | optional peer dependency가 코드에서 참조됨 (검토 필요) | dependencies |
| Unlisted dependencies | 코드에서 쓰이는데 package.json에 없는 dependency | unlisted |
| Unlisted binaries | 스크립트에서 쓰이는데 package.json의 bin에 없는 경우 | binaries |
| Unresolved imports | import 경로를 해석할 수 없음 | unresolved |
| Unused exports | export 했지만 어디에서도 사용되지 않음 | exports |
| Unused exported types | export된 타입이 사용되지 않음 | types |
| Exports in used namespace | 사용 중인 namespace에 export가 실제로 없음 | nsExports |
| Exported types in used namespace | namespace에 선언된 타입이 존재하지 않음 | nsTypes |
| Unused exported enum members | enum 멤버 일부가 미사용 | enumMembers |
| Unused exported class members | class 멤버 일부가 미사용 | classMembers |
| Duplicate exports | 동일한 이름의 export가 중복됨 | duplicates |
처음 도입할때 점점 강도를 높여가는 방식이 가장 괜찮다고 생각합니다.
처음부터 높은 강도로 돌리면,너무 많은 결과가 한번에 나오고,
옵션을 이해하기도 전에 “이걸 지금 지워도 되나?”라는 생각부터 들었다.
러닝커브 때문에 오히려 더 답답한 느낌이 들기도 했다.
그래서 저는 아래와 같은 순서로 진행했습니다.
# 0) 드라이런
npx knip
# 1) 프로덕션 코드만 (테스트/스토리/설정 제외)
npx knip --production
# 2) workspace/peerDeps 검증 강화 (프로덕션 모드 포함)
npx knip --strict
# 3) 자동 수정 (코드/의존성 정리)
npx knip --fix
# 4) 파일 삭제까지 허용
npx knip --fix --allow-remove-files
--fix 옵션만으로는 파일을 삭제하지 않습니다.
❌ 파일 제거를 위해서는 --allow-remove-files 옵션 추가