Navigation

13. 도구 설정

React 전용 검사는 biome 도메인 설정으로 지정하고, 도구가 검사하지 못하는 항목은 리뷰에서 확인합니다.

13.1 biome의 react 도메인과 추가 검사를 설정합니다

자동 검사 범위와 리뷰에서 판단할 범위를 구분합니다.

biome 2.x의 linter.domains에서 react를 켭니다. package.json에 react@>=16이 있을 때 React 검사가 적용되며, 기본 설정은 TypeScript 규칙 7.1를 따릅니다.

도메인 검사와 추가 설정

검사컨벤션 적용 범위추가 설정, 리뷰
correctness/noNestedComponentDefinitions규칙 5.2 전체도메인 recommended에 없어 별도로 켭니다
correctness/useExhaustiveDependencies규칙 8.5의 누락된 의존성 검사useEffectEvent로 분리할지는 리뷰에서 판단합니다
correctness/useJsxKeyInIterable규칙 5.7의 key 유무<> 대신 Fragment를 썼는지는 리뷰에서 확인합니다
style/noRestrictedImports + overrides규칙 1.4의 레이어, 라우트 방향아래 경로 설정을 추가합니다. 소유자 경계는 별도로 판단합니다

접근성 검사

a11y/*내용
컨벤션 적용 범위규칙 11.1의 일부
켜는 곳도메인이 아닌 preset: "recommended"
리뷰실제 접근 가능한 이름

a11y 검사는 useButtonType, useAltText, useValidAnchor, useKeyWithClickEvents, useSemanticElements, noStaticElementInteractions, useFocusableInteractive를 포함합니다.

가져오기 경로 제한

noRestrictedImports 적용 위치차단할 경로
src/component/ui/**@/component/widget/**, @/page/**
src/component/widget/**@/page/**
각 src/page/<route>/**@/page/**를 막고 !@/page/<route>/**로 자기 라우트만 허용합니다

라우트가 늘면 해당 overrides도 추가합니다. overrides는 규칙 옵션을 통째로 바꾸므로 기본 설정의 경로 패턴을 각 항목에 함께 적습니다. 소유자 경계는 가져오는 파일의 위치에 따라 달라지므로 import 문자열만으로 판정하지 못하고 리뷰에서 확인합니다.

켜지 않는 규칙

켜지 않는 규칙이유
style/useFragmentSyntaxrecommended에 없으며, 켜면 Fragment를 요구하는 규칙 5.7와 충돌합니다
style/useReactFunctionComponents도메인 all에만 있고 기본 심각도가 info라 통과 여부를 판정하지 못합니다

도메인과 추가 검사를 켜고 레이어, 라우트 overrides를 설정합니다.

{
	"linter": {
		"enabled": true,
		"domains": {"react": "recommended"},
		"rules": {
			"preset": "recommended",
			"correctness": {"noNestedComponentDefinitions": "error"},
			"style": {
				"noRestrictedImports": {
					"level": "error",
					"options": {
						"patterns": [{"group": ["../**", "./**", "!./*.css"], "message": "Import with the absolute alias. Only a bare file import may use ./ for the same folder."}]
					}
				}
			}
		}
	},
	"overrides": [
		{
			"includes": ["src/component/ui/**"],
			"linter": {
				"rules": {
					"style": {
						"noRestrictedImports": {
							"level": "error",
							"options": {
								"patterns": [
									{
										"group": ["../**", "./**", "!./*.css"],
										"message": "Import with the absolute alias. Only a bare file import may use ./ for the same folder."
									},
									{
										"group": ["@/component/widget/**", "@/page/**"],
										"message": "ui must not import widget or page."
									}
								]
							}
						}
					}
				}
			}
		},
		{
			"includes": ["src/component/widget/**"],
			"linter": {
				"rules": {
					"style": {
						"noRestrictedImports": {
							"level": "error",
							"options": {
								"patterns": [
									{
										"group": ["../**", "./**", "!./*.css"],
										"message": "Import with the absolute alias. Only a bare file import may use ./ for the same folder."
									},
									{"group": ["@/page/**"], "message": "widget must not import page."}
								]
							}
						}
					}
				}
			}
		},
		{
			"includes": ["src/page/product-detail/**"],
			"linter": {
				"rules": {
					"style": {
						"noRestrictedImports": {
							"level": "error",
							"options": {
								"patterns": [
									{
										"group": ["../**", "./**", "!./*.css"],
										"message": "Import with the absolute alias. Only a bare file import may use ./ for the same folder."
									},
									{"group": ["@/page/**", "!@/page/product-detail/**"], "message": "Do not import the inside of another route."}
								]
							}
						}
					}
				}
			}
		}
	]
}