Knip: JavaScript 및 TypeScript 프로젝트를 위한 궁극적인 죽은 코드 탐지기
Source: Dev.to
위에 제공된 텍스트 외에 번역할 내용이 없습니다. 번역이 필요한 본문을 제공해 주시면 한국어로 번역해 드리겠습니다.
Source: …
문제: 죽은 코드가 여기저기 퍼져 있다
모든 성숙한 코드베이스에는 지저분한 비밀이 있다: 죽은 코드.
누군가 “혹시 몰라”라고 만든 유틸리티 함수.
폐기된 기능에서 남은 컴포넌트.
결코 진행되지 않은 스파이크용으로 설치한 npm 패키지.
ESLint는 파일 내에서 사용되지 않는 변수와 import를 잡아낼 수 있지만, 다음은 어떨까?
- 어디에서도 import되지 않은 파일?
- 아무도 사용하지 않는 export된 함수?
package.json에 남아 있지만 제거를 깜빡한 의존성?- 정의만 되고 전혀 참조되지 않은 타입과 인터페이스?
바로 여기서 Knip이 등장한다.
Knip이란?
Knip (네덜란드어로 “cut”)은 JavaScript/TypeScript 프로젝트에서 사용되지 않는 파일, 의존성 및 내보내기를 찾아주는 강력한 정적 분석 도구입니다. 코드베이스의 마리 콘도라고 생각하면 됩니다 — 코드가 즐거움을 주지 않거나(또는 사용되지 않으면) 반드시 제거해야 합니다.
Knip이 감지하는 항목
| Category | Description |
|---|---|
| 🗂️ 사용되지 않는 파일 | 어디에서도 임포트되지 않은 소스 파일 |
| 📦 사용되지 않는 의존성 | package.json에 있지만 사용되지 않는 패키지 |
| 📤 사용되지 않는 내보내기 | 내보내졌지만 한 번도 임포트되지 않은 함수, 클래스, 타입 |
| 🔧 사용되지 않는 개발 의존성 | 필요하지 않은 개발 패키지 |
| ❓ 목록에 없는 의존성 | 코드에서 사용되지만 package.json에 없는 패키지 |
| 🔗 해결되지 않은 임포트 | 존재하지 않는 모듈을 가리키는 임포트 |

시작하기
설치
# npm
npm install -D knip
# yarn
yarn add -D knip
# pnpm
pnpm add -D knip
기본 사용법
npx knip
그게 전부입니다! Knip은 프로젝트를 분석하고 찾아낸 모든 사용되지 않은 코드를 출력합니다.
설정
대부분의 프로젝트에서는 Knip을 별도 설정 없이 바로 사용할 수 있습니다. 복잡한 설정(모노레포, 커스텀 엔트리 포인트 등)이 필요한 경우 설정 파일을 만들면 됩니다.
프로젝트 루트에 knip.json을 생성하세요:
{
"$schema": "https://unpkg.com/knip@5/schema.json",
"entry": ["src/index.ts", "src/App.tsx"],
"project": ["src/**/*.{ts,tsx}"],
"ignore": [
"**/__tests__/**",
"**/__mocks__/**",
"**/node_modules/**"
],
"ignoreDependencies": [
"prettier",
"husky"
],
"ignoreExportsUsedInFile": true
}
주요 설정 옵션
| 옵션 | 설명 |
|---|---|
entry | Knip이 추적을 시작하는 엔트리 포인트 파일 |
project | 분석할 파일 |
ignore | 건너뛸 파일/패턴 |
ignoreDependencies | 건너뛸 의존성 (설정 전용 패키지에 유용) |
ignoreExportsUsedInFile | 같은 파일 내에서만 사용된 내보내기를 보고하지 않음 |
React Native 예시
{
"$schema": "https://unpkg.com/knip@5/schema.json",
"entry": ["src/App.tsx", "index.js"],
"project": ["src/**/*.{ts,tsx}"],
"ignore": [
"**/__tests__/**",
"**/__mocks__/**",
"android/**",
"ios/**"
],
"ignoreDependencies": [
"@react-native/metro-config",
"@react-native/typescript-config",
"@react-native/babel-preset",
"patch-package",
"husky",
"reactotron-react-native"
],
"ignoreExportsUsedInFile": true
}
실제 결과
Running Knip on a production React Native app produced:
Unused files (73)
src/components/map/index.tsx
src/components/views/NotificationMenuButton.tsx
src/models/requests/auth/authRequests.ts
src/utils/helpers/contactHelper.ts
... and 69 more
Unused dependencies (1)
@react-native-firebase/perf
Unused devDependencies (4)
@babel/preset-env
@testing-library/jest-native
@types/react-native-get-random-values
eslint-plugin-react-you-might-not-need-an-effect
Unlisted dependencies (2)
credit-card-type src/features/paymentMethods/addNewCard/index.tsx
Unused exports (74)
translations src/config/localization/languages.ts
defaultAddressForm src/features/addressBook/addressTypes.ts
... and more
73개의 사용되지 않은 파일! 이는 수천 줄에 달하는 죽은 코드일 가능성이 있으며, 다음과 같은 문제를 일으킵니다:
- 번들 크기 증가
- 새로운 개발자에게 혼란을 줌
- 유지 보수 부담 증가
- 검색 결과에 나타나 시간을 낭비하게 함
워크플로에 통합하기
NPM 스크립트
package.json에 다음을 추가하세요:
{
"scripts": {
"knip:check": "knip",
"knip:fix": "knip --fix"
}
}
CI/CD 통합
# .github/workflows/code-quality.yml
name: Code Quality
on: [push, pull_request]
jobs:
knip:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
- run: npm ci
- run: npx knip
Pre‑commit 훅 (Husky 사용)
# .husky/pre-commit
npx knip --no-exit-code
--fix 로 자동 수정
npx knip --fix
⚠️ Warning: 이 작업은 파일을 수정합니다! 항상 변경 사항을 검토하고 버전 관리를 준비하세요.
--fix 로 할 수 있는 일:
- ✅ 사용되지 않는 export 제거
- ✅
package.json에서 사용되지 않는 의존성 제거 - ❌ 사용되지 않는 파일 삭제는 불가능 (위험함)
팁 및 모범 사례
--include로 시작하여 집중 – 결과가 너무 많아 압도될 경우, 먼저 특정 폴더나 카테고리로 분석을 제한하세요.- 정기적으로 Knip을 실행하세요(예: CI에서) 죽은 코드를 누적되지 않게 방지합니다.
- Knip을 코드 리뷰 체크리스트와 함께 사용하세요: “새로운 사용되지 않은 import/파일 없음.”
- 수정 후 변경 사항을 커밋하고 팀에 정리 작업이 완료되었음을 알리세요.
Knip을 도입하면 코드베이스를 가볍게 유지하고, 개발자 경험을 향상시키며, 더 작고 빠른 번들을 배포할 수 있습니다. 청소를 즐기세요!
Source: …
Knip 사용 팁
1. 특정 체크 포함하기
# 사용되지 않은 파일만 확인
npx knip --include files
# 의존성만 확인
npx knip --include dependencies
# 여러 카테고리 확인
npx knip --include files,exports
2. 출력 리포터 선택하기
# JSON 출력 (툴링에 유용)
npx knip --reporter json
# 마크다운 (문서화용)
npx knip --reporter markdown
3. 알려진 오탐 무시하기
일부 코드는 동적으로 사용되거나 Knip이 감지할 수 없는 관례를 통해 사용됩니다:
{
"ignore": [
"src/generated/**",
"**/*.stories.tsx"
],
"ignoreDependencies": [
"tsconfig-paths"
]
}
4. 배럴 익스포트 처리하기
배럴 파일(index.ts에서 모든 것을 재수출) 을 사용하는 경우 Knip이 오탐을 보고할 수 있습니다. 다음 옵션을 활성화하세요:
{
"ignoreExportsUsedInFile": true
}
5. 프레임워크‑별 플러그인
Knip은 다양한 프레임워크에 대한 내장 지원을 제공합니다:
{
"next": {
"entry": ["pages/**/*.tsx", "app/**/*.tsx"]
},
"jest": {
"config": ["jest.config.js"]
},
"storybook": {
"entry": [".storybook/main.ts"]
}
}
Knip vs. 기타 도구
| Tool | Unused Files | Unused Exports | Unused Deps | Auto‑fix |
|---|---|---|---|---|
| Knip | ✅ | ✅ | ✅ | ✅ |
| ESLint | ❌ | ❌ | ❌ | Partial |
| ts‑prune | ❌ | ✅ | ❌ | ❌ |
| depcheck | ❌ | ❌ | ✅ | ❌ |
| unimported | ✅ | ❌ | ✅ | ❌ |
Knip은 여러 도구를 대체하는 올인원 솔루션입니다.
일반적인 문제 및 해결책
“거짓 양성이 너무 많이 발생해요!”
- 코드가 동적으로 import되는지 확인하세요.
- 설정의
ignore에 패턴을 추가하세요. - 설정 전용 패키지에는
ignoreDependencies를 사용하세요. ignoreExportsUsedInFile을 활성화하세요.
“대규모 모노레포에서 Knip이 느려요”
{
"ignore": [
"**/dist/**",
"**/build/**",
"**/coverage/**"
]
}
“엔트리 포인트를 찾지 못하고 있어요”
명시적으로 정의하세요:
{
"entry": [
"src/index.ts",
"src/cli.ts",
"scripts/*.ts"
]
}
결론
죽은 코드는 시간이 지날수록 누적되는 기술 부채입니다. 사용되지 않는 파일 하나마다 다음과 같은 비용이 발생합니다:
- 사용자에게 전달되는 바이트
- 개발자에게 가해지는 인지적 부담
- 잠재적인 보안 취약점
- 낭비되는 CI/CD 시간
Knip은 코드베이스에서 실제로 사용되는 부분을 가시화해 줍니다. 한 번 실행해 보세요—발견에 놀라실 수도 있습니다. 정기적으로 실행하여 코드베이스를 가볍고 유지보수하기 쉽게 유지하세요.
# Try it now
npx knip
Resources
Knip이 코드베이스 정리에 도움이 되었나요? 댓글에 결과를 공유해주세요! 얼마나 많은 죽은 코드를 찾았는지 듣고 싶어요. 🔪
Tags: javascript, typescript, webdev, productivity