Knip: JavaScript 및 TypeScript 프로젝트를 위한 궁극적인 죽은 코드 탐지기

발행: (2025년 12월 24일 오전 04:51 GMT+9)
10 min read
원문: Dev.to

Source: Dev.to

위에 제공된 텍스트 외에 번역할 내용이 없습니다. 번역이 필요한 본문을 제공해 주시면 한국어로 번역해 드리겠습니다.

Source:

문제: 죽은 코드가 여기저기 퍼져 있다

모든 성숙한 코드베이스에는 지저분한 비밀이 있다: 죽은 코드.
누군가 “혹시 몰라”라고 만든 유틸리티 함수.
폐기된 기능에서 남은 컴포넌트.
결코 진행되지 않은 스파이크용으로 설치한 npm 패키지.

ESLint는 파일 내에서 사용되지 않는 변수와 import를 잡아낼 수 있지만, 다음은 어떨까?

  • 어디에서도 import되지 않은 파일?
  • 아무도 사용하지 않는 export된 함수?
  • package.json에 남아 있지만 제거를 깜빡한 의존성?
  • 정의만 되고 전혀 참조되지 않은 타입과 인터페이스?

바로 여기서 Knip이 등장한다.

Knip이란?

Knip (네덜란드어로 “cut”)은 JavaScript/TypeScript 프로젝트에서 사용되지 않는 파일, 의존성 및 내보내기를 찾아주는 강력한 정적 분석 도구입니다. 코드베이스의 마리 콘도라고 생각하면 됩니다 — 코드가 즐거움을 주지 않거나(또는 사용되지 않으면) 반드시 제거해야 합니다.

Knip이 감지하는 항목

CategoryDescription
🗂️ 사용되지 않는 파일어디에서도 임포트되지 않은 소스 파일
📦 사용되지 않는 의존성package.json에 있지만 사용되지 않는 패키지
📤 사용되지 않는 내보내기내보내졌지만 한 번도 임포트되지 않은 함수, 클래스, 타입
🔧 사용되지 않는 개발 의존성필요하지 않은 개발 패키지
목록에 없는 의존성코드에서 사용되지만 package.json에 없는 패키지
🔗 해결되지 않은 임포트존재하지 않는 모듈을 가리키는 임포트

Knip report example

시작하기

설치

# 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
}

주요 설정 옵션

옵션설명
entryKnip이 추적을 시작하는 엔트리 포인트 파일
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에서 사용되지 않는 의존성 제거
  • ❌ 사용되지 않는 파일 삭제는 불가능 (위험함)

팁 및 모범 사례

  1. --include 로 시작하여 집중 – 결과가 너무 많아 압도될 경우, 먼저 특정 폴더나 카테고리로 분석을 제한하세요.
  2. 정기적으로 Knip을 실행하세요(예: CI에서) 죽은 코드를 누적되지 않게 방지합니다.
  3. Knip을 코드 리뷰 체크리스트와 함께 사용하세요: “새로운 사용되지 않은 import/파일 없음.”
  4. 수정 후 변경 사항을 커밋하고 팀에 정리 작업이 완료되었음을 알리세요.

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. 기타 도구

ToolUnused FilesUnused ExportsUnused DepsAuto‑fix
Knip
ESLintPartial
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

Back to Blog

관련 글

더 보기 »

Rust가 'pub'을 잘못 이해했다

!Rust의 표지 이미지가 ‘pub’를 잘못 표시했습니다 https://media2.dev.to/dynamic/image/width=1000,height=420,fit=cover,gravity=auto,format=auto/https%3A%2F%2Fdev-to-uploads.s...