# ESLint Rules (eslint-plugin-dsmonitor) `packages/dsmonitor/eslint/`에 번들링된 커스텀 ESLint 플러그인. 프로젝트 **스타일링 정책**(`stylingPolicy.js`)을 주입받아 동작한다. ## Policy Decisions 프로젝트의 스타일링 정책 결정 사항 — 이 결정이 바뀌면 `stylingPolicy.js`와 이 문서를 같이 갱신한다. ### 결정 (2026-04-20 기준) - **정식**: SCSS (이 프로젝트는 `styles/css/scss/` 중심. DS 내부도 SCSS/reactstrap 혼합 기반) - **레거시**: - **Bootstrap 유틸리티 클래스** (`btn`, `d-flex`, `mt-3`, `col-*` 등) — 정리 대상 - **Tailwind 클래스** — 정리 대상 - **Tailwind에 대한 보충 메모**: - 현재 코드에 남아있는 Tailwind 잔재는 **비체계적**으로 쓰인 것들 (정식 도입 없이 일부 파일에서만 임의 사용). 이 잔재는 정식 Tailwind 도입 여부와 **별개**로 정리 대상. - **향후 Tailwind를 정식 도입할 가능성 있음**. 그 시점에는 이 정책 재평가: - `stylingPolicy.js`의 `allowed`에 `tailwind` 추가 - `forbidden.tailwind-classes` 제거 - `preferred`를 단일 값 → 배열로 확장하거나 `preferredFamilies` 도입 검토 - `docs/config-examples/tailwind-project.js` 참고해서 정책 재구성 - 재평가 트리거: 정식 Tailwind 도입 결정 / Tailwind config (`tailwind.config.js`) 추가 / DS 컴포넌트가 Tailwind 기반으로 재작성 시작 ## 룰 목록 (v0.2) ### `dsmonitor/no-forbidden-classes` #### 의도 프로젝트 정책에 의해 금지된 className 토큰(+ 선택적으로 금지 모듈 import)이 코드에 들어오는 것을 차단한다. 정책은 `stylingPolicy.forbidden` 배열로 주어지며, 한 룰이 **모든 금지 그룹을 통합 검사**한다. #### 동작 방식 - JSX `className` / `class` attribute의 모든 string literal을 토큰 단위로 분해 - 각 토큰을 `forbidden[*].classPatterns` 정규식에 매치 - 매치되면 해당 `forbidden[*].label`과 함께 보고 - 선택: `forbidden[*].importModules` 지정 시 import source도 차단 - 탐지 범위: - `className="d-flex mt-3"` — Literal - `` className={`menu-item btn ${active ? 'active' : ''}`} `` — TemplateLiteral - `className={clsx('form-control', { 'is-invalid': err })}` — CallExpression + ObjectExpression의 **문자열 key** - `className={cond ? 'btn' : 'ok'}` — ConditionalExpression #### 래칫 (심각도) `fromPolicy(policy, { baselinePath })` 가 자동으로: - `lint-baseline.json`에 등록된 파일 → **warn** (기존 부채) - 그 외 파일(신규 포함) → **error** - 베이스라인이 없으면 모든 파일 **error** (start-from-clean) #### 예시 — 현재 프로젝트 기준 (SCSS 정식) **❌ Before (error on new file / warn on baseline file)** ```jsx // apps/new-feature/index.jsx export default function Panel() { return (
); } ``` ESLint 출력: ``` 3:10 error 'd-flex' is forbidden (Bootstrap utility classes). dsmonitor/no-forbidden-classes 3:10 error 'mt-3' is forbidden (Bootstrap utility classes). dsmonitor/no-forbidden-classes 3:10 error 'justify-content-between' is forbidden (Bootstrap utility classes).dsmonitor/no-forbidden-classes 4:15 error 'btn' is forbidden (Bootstrap utility classes). dsmonitor/no-forbidden-classes 4:15 error 'btn-primary' is forbidden (Bootstrap utility classes). dsmonitor/no-forbidden-classes ``` **✅ After — SCSS + DS로 교체** ```jsx import Button from "@atoms/Button"; import Input from "@atoms/Input"; import styles from "./Panel.module.scss"; // 또는 프로젝트 SCSS 규칙 export default function Panel() { return (
); } ``` - Bootstrap utility 클래스 **제거** - `