feat: [module] Phase 3 — 물리적 분리 (경계 마커, 검증 스크립트, 라우트 가드, 문서)
- MODULE.md 경계 마커 4개 (production, quality, construction, vehicle-management) - verify-module-separation.sh: Common→Tenant 금지 임포트 검증 스크립트 - 영업 생산지시 3개 페이지에 useModules 가드 추가 - MODULE_SEPARATION_OK 주석 마커 (공유 래퍼 허용) - tsconfig @modules/* path alias 추가 - CLAUDE.md 모듈 분리 아키텍처 섹션 추가 - 모듈 분리 가이드 문서 (claudedocs/architecture/)
This commit is contained in:
97
scripts/verify-module-separation.sh
Executable file
97
scripts/verify-module-separation.sh
Executable file
@@ -0,0 +1,97 @@
|
||||
#!/bin/bash
|
||||
# ===================================================================
|
||||
# Module Separation Verification Script
|
||||
#
|
||||
# 공통 ERP → 테넌트 모듈 간 금지된 정적 import를 검사합니다.
|
||||
# Phase 0에서 해소한 의존성이 다시 발생하지 않도록 CI에서 실행 가능.
|
||||
#
|
||||
# 사용법: bash scripts/verify-module-separation.sh
|
||||
# 종료코드: 0 = 통과, 1 = 위반 발견
|
||||
# ===================================================================
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
echo "================================================="
|
||||
echo " Module Separation Verification"
|
||||
echo "================================================="
|
||||
echo ""
|
||||
|
||||
# 테넌트 전용 경로 패턴 (from 'xxx' 또는 from "xxx" 형태로 검색)
|
||||
TENANT_PATHS=(
|
||||
"@/components/production/"
|
||||
"@/components/quality/"
|
||||
"@/components/business/construction/"
|
||||
"@/components/vehicle-management/"
|
||||
)
|
||||
|
||||
# 공통 ERP 소스 디렉토리 (테넌트 페이지 제외)
|
||||
COMMON_DIRS=(
|
||||
"src/components/approval"
|
||||
"src/components/accounting"
|
||||
"src/components/auth"
|
||||
"src/components/atoms"
|
||||
"src/components/board"
|
||||
"src/components/business/CEODashboard"
|
||||
"src/components/business/DashboardSwitcher.tsx"
|
||||
"src/components/clients"
|
||||
"src/components/common"
|
||||
"src/components/customer-center"
|
||||
"src/components/document-system"
|
||||
"src/components/hr"
|
||||
"src/components/items"
|
||||
"src/components/layout"
|
||||
"src/components/material"
|
||||
"src/components/molecules"
|
||||
"src/components/organisms"
|
||||
"src/components/orders"
|
||||
"src/components/outbound"
|
||||
"src/components/pricing"
|
||||
"src/components/providers"
|
||||
"src/components/reports"
|
||||
"src/components/settings"
|
||||
"src/components/stocks"
|
||||
"src/components/templates"
|
||||
"src/components/ui"
|
||||
"src/lib"
|
||||
"src/hooks"
|
||||
"src/stores"
|
||||
"src/contexts"
|
||||
)
|
||||
|
||||
VIOLATIONS=0
|
||||
|
||||
for dir in "${COMMON_DIRS[@]}"; do
|
||||
# 디렉토리/파일이 없으면 스킵
|
||||
[ -e "$dir" ] || continue
|
||||
|
||||
for tenant_path in "${TENANT_PATHS[@]}"; do
|
||||
# 정적 import 검색 (dynamic import는 허용)
|
||||
found=$(grep -rn "from ['\"]${tenant_path}" "$dir" \
|
||||
--include="*.ts" --include="*.tsx" 2>/dev/null \
|
||||
| grep -v "dynamic(" \
|
||||
| grep -v "// MODULE_SEPARATION_OK" \
|
||||
|| true)
|
||||
|
||||
if [ -n "$found" ]; then
|
||||
echo "VIOLATION: $dir → $tenant_path"
|
||||
echo "$found"
|
||||
echo ""
|
||||
VIOLATIONS=$((VIOLATIONS + 1))
|
||||
fi
|
||||
done
|
||||
done
|
||||
|
||||
echo "================================================="
|
||||
if [ $VIOLATIONS -eq 0 ]; then
|
||||
echo " PASSED: No forbidden imports found."
|
||||
exit 0
|
||||
else
|
||||
echo " FAILED: Found $VIOLATIONS forbidden import(s)."
|
||||
echo ""
|
||||
echo " 해결 방법:"
|
||||
echo " - dynamic import (next/dynamic)로 교체"
|
||||
echo " - @/lib/api/ 또는 @/interfaces/로 타입 이동"
|
||||
echo " - @/components/document-system/으로 공유 모달 이동"
|
||||
echo " - 불가피한 경우 // MODULE_SEPARATION_OK 주석 추가"
|
||||
exit 1
|
||||
fi
|
||||
Reference in New Issue
Block a user