본문으로 건너뛰기

© 2026 Molayo

GH Trending릴리즈2026. 05. 14. 07:37

millionco/react-doctor

요약

react-doctor는 코드베이스를 스캔하여 React 코드를 분석하고, 0점에서 100점 사이의 '건강 점수(health score)'와 함께 상세한 진단 결과를 제공하는 도구입니다. 이 도구는 상태 및 이펙트, 성능, 아키텍처, 보안, 접근성, 데드 코드 등 다양한 측면에서 이슈를 식별합니다. 또한 코딩 에이전트에게 React 베스트 프랙티스를 학습시켜 잘못된 코드를 작성하지 않도록 예방하는 기능도 제공하며, Pull Request(PR) 이벤트에 통합되어 발견된 사항을 PR 코멘트로 게시할 수 있습니다.

핵심 포인트

  • 코드베이스 전체를 스캔하여 0-100점의 건강 점수와 상세 진단 결과를 얻을 수 있습니다.
  • 상태/이펙트, 성능, 아키텍처, 보안, 접근성 등 다차원적인 관점에서 React 코드를 검사합니다.
  • 코딩 에이전트에 react-doctor를 설치하여 잘못된 코드 작성 자체를 예방할 수 있습니다.
  • GitHub Actions의 Pull Request 이벤트에 통합되어 발견 사항을 PR 코멘트로 자동 게시 및 업데이트가 가능합니다.
  • `.ignore.rules`, `.ignore.files`, `.ignore.overrides` 등 세분화된 설정으로 특정 규칙을 제외하거나 재정의할 수 있습니다.

당신의 에이전트가 잘못된 React 코드를 작성한다면, 이것이 이를 잡아냅니다.

단 한 번의 명령으로 코드베이스를 스캔하고 실행 가능한 진단 결과와 함께 **0에서 100 사이의 건강 점수 (health score)**를 출력합니다.

Next.js, Vite, 그리고 React Native와 함께 작동합니다.

프로젝트 루트에서 다음을 실행하세요:

npx -y react-doctor@latest .

점수(75점 이상: Great, 50~74점: Needs work, 50점 미만: Critical)와 함께 상태 및 이펙트 (state & effects), 성능 (performance), 아키텍처 (architecture), 보안 (security), 접근성 (accessibility), 그리고 데드 코드 (dead code) 전반에 걸친 이슈 목록을 받게 됩니다. 규칙은 사용 중인 프레임워크와 React 버전에 따라 자동으로 전환됩니다.

Main.mp4

코딩 에이전트에게 React 베스트 프랙티스 (best practices)를 가르쳐서, 애초에 잘못된 코드를 작성하지 않도록 만드세요.

npx -y react-doctor@latest install

감지된 어떤 에이전트에 대해 설치할지 선택하라는 프롬프트가 나타납니다. 프롬프트를 건너뛰려면 --yes를 전달하세요.

Claude Code, Cursor, Codex, OpenCode 및 50개 이상의 다른 에이전트와 함께 작동합니다.

이 저장소에는 컴포지트 액션 (composite action)이 포함되어 있습니다. .github/workflows/react-doctor.yml에 다음을 넣으세요:

name: React Doctor
on:
pull_request:
...

pull_request 이벤트에 github-token이 설정되면, 발견된 사항들이 PR 코멘트로 게시(및 업데이트)됩니다. 이 액션은 또한 후속 단계에서 사용할 수 있는 score 출력값 (0–100)을 제공합니다.

입력값 (Inputs): directory, verbose, project, diff, github-token, fail-on (error / warning / none), offline, node-version. 전체 설명은 action.yml을 참조하세요.

마켓플레이스 액션 (marketplace action)을 추가하고 싶지 않다면? 기본 npx 형태도 작동합니다:

- run: npx -y react-doctor@latest --fail-on warning

프로젝트 루트에 react-doctor.config.json을 생성하세요:

{
"ignore": {
"rules": ["react/no-danger", "jsx-a11y/no-autofocus"],
...

세 개의 중첩된 키, 세 단계의 세분화 수준 — 상황에 맞는 가장 좁은 범위를 선택하세요:

ignore.rules는 코드베이스 전체에서 규칙을 침묵시킵니다.
ignore.files는...

매칭된 파일의 모든 규칙을 침묵시킵니다 (주의해서 사용하세요 — 관련 없는 규칙들에 대한 커버리지가 손실됩니다). 매칭된 파일에서 나열된 규칙들만 침묵시키고, 다른 모든 규칙은 활성 상태로 유지합니다. 이는 단일 파일(또는 glob)이 한두 개의 규칙에 대해서는 정당하게 예외가 필요하지만, 그 외의 모든 사항에 대해서는 여전히 스캔되어야 할 때 원하는 방식입니다.

ignore.overrides를 사용할 수도 있습니다.

또한 package.json 내의 "reactDoctor" 키를 사용할 수 있습니다. CLI 플래그는 항상 설정 값을 우선합니다.

React Doctor는 .gitignore, .eslintignore, .oxlintignore, .prettierignore, 그리고 .gitattributes 내의 linguist-vendored / linguist-generated 주석을 준수합니다. 인라인 // eslint-disable*// oxlint-disable* 주석도 존중됩니다.

JSON 형태의 oxlint 또는 eslint 설정(.oxlintrc.json 또는 .eslintrc.json)이 있는 경우, 해당 규칙들은 자동으로 스캔에 병합되며 점수에 반영됩니다. 이를 제외하려면 adoptExistingConfig: false를 설정하세요.

스캔된 프로젝트에 다음 ESLint 플러그인들이 설치되어 있는 경우(또는 모노레포(monorepo)에서 호이스팅(hoisted)되어 있는 경우), React Doctor는 해당 규칙들을 동일한 스캔에 포함시킵니다. 두 플러그인 모두 **선택적 피어 의존성 (optional peer dependencies)**으로 나열되어 있으므로, 원하는 것만 설치하면 됩니다.

플러그인추가되는 내용네임스페이스 (Namespace)
eslint-plugin-react-hooks (v6 또는 v7)React Compiler 프론트엔드의 정확성 규칙 — 프로젝트에서 React Compiler가 감지되었을 때 실행됩니다.react-hooks-js/*
eslint-plugin-react-you-might-not-need-an-effect (v0.10+)React Doctor의 네이티브 State & Effects 규칙과 함께 실행되는 상호 보완적인 anti-pattern으로서의 effects 규칙 (no-derived-state, no-chain-state-updates, no-event-handler, no-pass-data-to-parent, …)effect/*
// react-doctor-disable-next-line react-doctor/no-cascading-set-state
useEffect(() => {
setA(value);
...

동일한 라인에서 두 개의 규칙이 실행되는 경우, 두 가지 동등한 옵션이 있습니다. 단일 주석에 규칙 ID들을 쉼표로 구분하여 작성하세요:

// react-doctor-disable-next-line react-doctor/rerender-state-only-in-handlers, react-doctor/no-derived-useState
const [localSearch, setLocalSearch] = useState(searchQuery);

또는 진단(diagnostic) 바로 위에 규칙당 하나의 주석을 쌓는(stack) 방법이 있습니다. 주석들 사이에 다른 react-doctor-disable-next-line 주석 외에 다른 내용이 대상 라인과 사이에 위치하지 않는 한, 쌓인 주석들은 유효하게 처리됩니다:

// react-doctor-disable-next-line react-doctor/rerender-state-only-in-handlers
// react-doctor-disable-next-line react-doctor/no-derived-useState
const [localSearch, setLocalSearch] = useState(searchQuery);

쌓인 주석 사이에 코드 라인이 삽입되면 체인이 끊어집니다. 이 경우 진단 바로 위에 있는 주석(및 그 위에 쌓인 연속적인 react-doctor-disable-next-line 주석들)만 유효하게 처리됩니다. 주석이 인접해 보임에도 규칙이 여전히 실행된다면, react-doctor --explain <file:line>을 실행하세요. 이 명령은 근처에서 억제(suppression) 설정을 찾았는지, 어떤 규칙을 포함하고 있는지, 그리고 왜 적용되지 않았는지를 보고합니다.

블록 주석(Block comments)은 JSX 내부에서도 작동합니다:

{/* react-doctor-disable-next-line react/no-danger */}
<div dangerouslySetInnerHTML={{ __html }} />

여러 줄로 구성된 JSX의 경우, 여는 태그 바로 위에 주석을 배치하면 전체 속성 목록(attribute list)이 적용됩니다 (ESLint 컨벤션과 동일).

동일한 규칙 세트가 oxlint 플러그인과 ESLint 플러그인으로 모두 제공되므로, 프로젝트에서 이미 사용 중인 린트 엔진(lint engine)에 맞춰 연결할 수 있습니다.

.oxlintrc.jsonoxlint 설정:

{
"jsPlugins": [{ "name": "react-doctor", "specifier": "react-doctor/oxlint-plugin" }],
"rules": {
...

ESLint flat config:

import reactDoctor from "react-doctor/eslint-plugin";
export default [
reactDoctor.configs.recommended,
...

전체 규칙 목록은 oxlint-config.ts에 있습니다.

Usage: react-doctor [directory] [options]
Options:
-v, --version display the version number
...

억제(suppression)가 작동하지 않을 때는 --explain <file:line> (또는 그 별칭인 --why <file:line>)을 사용하세요.

)은 스캐너가 해당 위치에서 무엇을 보고 있는지 보고하며, 근처의 react-doctor-disable-next-line이 왜 적용되지 않았는지에 대한 이유를 포함합니다. 진단 결과는 일반적인 실패 모드 — 다른 규칙을 위한 인접 주석(쉼표 형식 사용), 주석과 진단 사이의 코드 라인(체인이 끊김), 또는 근처에 억제(suppression)가 전혀 없음 — 를 구분합니다. 동일한 힌트가 --verbose 사용 시 모든 플래그가 지정된 위치에 인라인으로 나타나며, --json 출력에서는 diagnostic.suppressionHint로 나타나므로, 별도의 플래그 없이도 단 한 번의 스캔으로 억제 감사(suppression audit)를 겸할 수 있습니다.

--json은 모든 사람이 읽을 수 있는 출력을 억제하고 stdout에 파싱 가능한 객체를 생성합니다. 에러가 발생하더라도 ok: false가 포함된 JSON 객체를 생성하므로, stdout은 항상 유효한 문서입니다.

KeyTypeDefault
ignore.rulesstring[][]
ignore.filesstring[][]
ignore.overrides{ files, rules? }[][]
lintbooleantrue
deadCodebooleantrue
verbosebooleanfalse
diff`booleanstring`
failOn`"error""warning"
customRulesOnlybooleanfalse
sharebooleantrue
offlinebooleanfalse
textComponentsstring[][]
rawTextWrapperComponentsstring[][]
respectInlineDisablesbooleantrue
adoptExistingLintConfigbooleantrue
ignore.tagsstring[][]
entryFilesstring[]`[]$

textComponentsrn-no-raw-text를 위한 광범위한 탈출구(escape hatch)입니다. — React Native의 <Text>처럼 동작하는 컴포넌트들(커스텀 Typography, NativeTabs.Trigger.Label 등)을 목록에 추가하면, 해당 규칙은 자식 요소가 어떻게 생겼든 상관없이 이들을 텍스트 컨테이너로 취급합니다.

rawTextWrapperComponents는 텍스트 요소는 아니지만 내부의 <Text>를 통해 문자열 전용 자식 요소를 안전하게 전달하는 컴포넌트를 위한 더 좁은 범위의 옵션입니다 (예: heroui-nativeButton

, 자식 요소를 문자열로 변환하여 ButtonLabel을 통해 렌더링합니다). 나열된 래퍼(wrappers)들은 자식 요소가 완전히 문자열로 변환 가능할 때만 rn-no-raw-text를 억제합니다. 혼합된 자식 요소를 가진 래퍼(예: <Button>Save<Icon /></Button>)는 래퍼가 형제 JSX 요소와 함께 원시 텍스트(raw text)를 안전하게 전달할 수 없기 때문에 여전히 보고됩니다.

ignore.tags는 태그별로 규칙의 전체 카테고리를 억제합니다. 예를 들어, "tags": ["design"]은 모든 주관적인 디자인 규칙(그라데이션 텍스트, 순수 검정 배경, 사이드 탭 테두리, 기본 Tailwind 팔레트)을 비활성화합니다. 사용 가능한 태그: "design".

entryFiles는 직접 실행되지만 임포트(import)되지 않는 파일(테스트 러너 설정, eval 스크립트, CLI 엔트리 포인트)을 데드 코드 탐지기(dead-code detector)에 알려줍니다. 이 파일들은 추가적인 엔트리 포인트(entry points)로서 knip로 전달됩니다. 예시: "entryFiles": ["scripts/*.ts", "evalite.config.ts"]. 프로젝트에 이미 knip.json이 있는 경우, 해당 엔트리 포인트들이 자동으로 준수됩니다.

offline은 점수 API 호출을 건너뛰고 로컬에서 점수를 계산합니다. CI 환경(GitHub Actions, GitLab CI, CircleCI)에서는 자동으로 활성화됩니다. 항상 로컬에서 점수를 계산하려면 설정에서 true로 설정하세요.

헬스 점수(health score) 공식: 100 - (고유 에러 규칙 수 x 1.5) - (고유 경고 규칙 수 x 0.75).

주요 세부 사항:

  • 점수는 총 위반 횟수가 아니라 **트리거된 고유 규칙(unique rules triggered)**의 수를 계산합니다. 50개의 no-barrel-import 위반 중 49개를 수정하더라도 점수는 변하지 않으며, 50개 모두를 수정해야 해당 규칙에 대한 0.75점의 페널티가 제거됩니다. 에러 등급(Error-severity) 규칙은 각각 1.5점이 차감되며, 경고 등급(Warning-severity) 규칙은 각각 0.75점이 차감됩니다.
  • 출력 결과에 표시되는 카테고리별 분류는 표시용일 뿐이며 점수 가중치에는 영향을 미치지 않습니다.
  • 어떤 정확한 규칙이 점수에 기여했는지, 그리고 페널티가 어떻게 계산되었는지 확인하려면 --verbose를 실행하세요.

점수 라벨: 75점 이상은 Great, 50점에서 74점은 Needs work, 50점 미만은 Critical입니다.

새로운 규칙이 추가됨에 따라 릴리스가 진행될수록 점수가 낮아질 수 있습니다. 코드베이스에서 실행되는 새로운 규칙이 추가될 때마다 추가적인 페널티가 부여됩니다. 이는 예상된 결과입니다. 즉, 도구가 더 많은 문제를 잡아내고 있다는 의미이지, 코드가 나빠졌다는 뜻이 아닙니다. 업그레이드 시에도 안정적인 점수를 유지해야 한다면 CI에서 특정 react-doctor 버전을 고정(Pin)하여 사용하세요.

React Doctor는 전체 프로젝트 대신 변경된 파일만 스캔할 수 있습니다:

--diff [base]

기본 브랜치(main 또는 master)와 비교하여 변경된 파일을 스캔합니다. 또는 --diff develop과 같이 명시적인 브랜치를 전달할 수 있습니다. 설정 키로 `

(기본값)은 error-severity 진단(diagnostics)이 발견되면 0이 아닌 종료 코드(non-zero exit code)로 종료됩니다. CI 게이팅 (CI gating)을 조정하려면 --fail-on warning 또는 --fail-on none을 사용하세요.

프로그래밍 방식 API (Programmatic API):
스크립트 및 자동화에 직접 통합할 수 있도록 import { diagnose } from "react-doctor/api"를 제공합니다.

CI 환경에서는 프롬프트(prompts)가 자동으로 건너뛰어지며, 점수 산정(scoring)은 로컬(오프라인 모드)에서 실행됩니다.

import { diagnose, toJsonReport, summarizeDiagnostics } from "react-doctor/api";
const result = await diagnose("./path/to/your/react-project");
console.log(result.score); // { score: 82, label: "Great" } 또는 null
...

diagnose는 두 번째 인자로 { lint?: boolean, deadCode?: boolean }를 받습니다.

const report = toJsonReport(result, { version: "1.0.0" });
const counts = summarizeDiagnostics(result.diagnostics);

react-doctor/apiJsonReport, JsonReportSummary, JsonReportProjectEntry, JsonReportMode를 재내보내기(re-exports)하며, 더 낮은 수준의 빌더인 buildJsonReportbuildJsonReportError도 포함합니다. 전체 타입은 packages/react-doctor/src/api.ts를 참조하세요.

AI 자동 생성 콘텐츠

본 콘텐츠는 GitHub Trending All (daily)의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.

원문 바로가기
0

댓글

0