From a05ef0b0a84e90fcddf11b62d1498bada8d724da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9C=A0=EB=B3=91=EC=B2=A0?= Date: Fri, 20 Mar 2026 14:33:21 +0900 Subject: [PATCH] =?UTF-8?q?docs:=20=EC=98=A8=EB=B3=B4=EB=94=A9=20=EA=B0=80?= =?UTF-8?q?=EC=9D=B4=EB=93=9C=20+=20=EA=B6=8C=ED=95=9C=20=ED=99=94?= =?UTF-8?q?=EC=9D=B4=ED=8A=B8=EB=A6=AC=EC=8A=A4=ED=8A=B8=20=EB=AC=B8?= =?UTF-8?q?=EC=84=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 00-onboarding: 신규 합류자 가이드 (시스템 개요, 도메인 맵, 읽기 순서) - 12-permission-whitelist: PermissionGate 화이트리스트 접근 제어 - _index.md: 문서 목록 업데이트 - v2/01: 관련 문서 참조 추가 Co-Authored-By: Claude Opus 4.6 (1M context) --- frontend/_index.md | 11 +- frontend/v1/00-onboarding.md | 386 ++++++++++++++++++ frontend/v1/12-permission-whitelist.md | 134 ++++++ .../v2/01-dynamic-multi-tenant-page-system.md | 68 ++- 4 files changed, 592 insertions(+), 7 deletions(-) create mode 100644 frontend/v1/00-onboarding.md create mode 100644 frontend/v1/12-permission-whitelist.md diff --git a/frontend/_index.md b/frontend/_index.md index 468b4a2..52fe3bf 100644 --- a/frontend/_index.md +++ b/frontend/_index.md @@ -1,7 +1,7 @@ # SAM ERP Frontend Documentation > **프로젝트**: SAM ERP Next.js 프론트엔드 -> **최종 갱신**: 2026-03-10 +> **최종 갱신**: 2026-03-18 > **현재 문서 버전**: v1 (운영 중) / v2 (설계 중) --- @@ -26,6 +26,7 @@ frontend/ | # | 문서 | 버전 | 최종 수정 | 담당 | 대상 | 설명 | |---|------|------|----------|------|------|------| +| 00 | [onboarding](v1/00-onboarding.md) | 1.0.0 | 2026-03-20 | Frontend | 전체 | 신규 합류자 온보딩 (시스템 개요, 도메인 맵, 읽기 순서) | | 01 | [architecture](v1/01-architecture.md) | 1.0.0 | 2026-03-09 | Frontend | 전체 | 프로젝트 구조, 기술 스택, 디렉토리 설계 | | 02 | [api-pattern](v1/02-api-pattern.md) | 1.0.0 | 2026-03-09 | Frontend | FE/BE | API 통신 패턴 (프록시, Server Action, buildApiUrl) | | 03 | [component-design](v1/03-component-design.md) | 1.0.0 | 2026-03-09 | Frontend | FE/기획 | 컴포넌트 계층 (atoms → templates), 페이지 유형 | @@ -37,12 +38,13 @@ frontend/ | 09 | [conventions](v1/09-conventions.md) | 1.0.0 | 2026-03-09 | Frontend | FE | 네이밍, import, 파일 배치, Git 규칙 | | 10 | [document-api-integration](v1/10-document-api-integration.md) | 1.0.0 | 2026-02-05 | API Team | FE/BE | 문서 관리 API 연동 (검사 성적서 resolve/upsert) | | 11 | [browser-navigation-rules](v1/11-browser-navigation-rules.md) | 1.0.0 | 2026-03-10 | Frontend | AI/QA | 브라우저 네비게이션 규칙 (URL 추측 금지, 메뉴 클릭 필수) | +| 12 | [permission-whitelist](v1/12-permission-whitelist.md) | 1.0.0 | 2026-03-20 | Frontend | FE/BE | 권한 기반 페이지 접근 제어 (화이트리스트, 바이패스, 모듈 역할 분담) | ### v2 — 동적 멀티테넌트 시스템 (설계 중) | # | 문서 | 버전 | 최종 수정 | 담당 | 대상 | 설명 | |---|------|------|----------|------|------|------| -| 01 | [dynamic-multi-tenant-page-system](v2/01-dynamic-multi-tenant-page-system.md) | 1.1.0 | 2026-03-11 | FE/BE | 전체 | 동적 멀티테넌트 페이지 시스템 설계 (17개 규칙, JSON config, 동적 라우팅, 권한 통합) | +| 01 | [dynamic-multi-tenant-page-system](v2/01-dynamic-multi-tenant-page-system.md) | 1.3.0 | 2026-03-18 | FE/BE | 전체 | 동적 멀티테넌트 페이지 시스템 설계 (17개 규칙, JSON config, 동적 라우팅, 권한 통합, 테넌트 분류, 선결과제) | > **v2 상태**: 초안 — 백엔드 회의 후 협의 항목 확정 예정 @@ -62,6 +64,7 @@ frontend/ | 날짜 | 문서 | 변경 | 버전 | |------|------|------|------| | 2026-03-11 | 01 | 동적 멀티테넌트 페이지 시스템 설계 초안 작성 | 1.1.0 | +| 2026-03-18 | 01 | JSONB 저장 확정, 테넌트 분류(3종), 선결과제 4개, 의존성 위반 목록 추가 | 1.3.0 | ### v1 (2026-03-09 ~) @@ -70,6 +73,8 @@ frontend/ | 2026-03-09 | 01~09 | 초기 작성 | 1.0.0 | | 2026-02-05 | 10 | 문서 API 연동 가이드 작성 (api-specs에서 이관) | 1.0.0 | | 2026-03-10 | 11 | 브라우저 네비게이션 규칙 추가 (AI/E2E URL 추측 금지) | 1.0.0 | +| 2026-03-20 | 12 | 권한 기반 페이지 접근 제어 — PermissionGate 화이트리스트 전환, 바이패스 경로, 모듈 시스템 역할 분담 | 1.0.0 | +| 2026-03-20 | 00 | 신규 합류자 온보딩 가이드 — 시스템 개요, 테넌트 구조, 도메인 맵, 상태관리, 라우팅 패턴, 읽기 순서 | 1.0.0 | --- @@ -104,6 +109,7 @@ PATCH: 오탈자, 코드 예시 수정, 사소한 수정 | 할 일 | 읽을 문서 | |-------|----------| +| **프로젝트에 처음 합류** | **v1/00-onboarding (여기서 시작)** | | 프로젝트 전체 구조 이해 | v1/01-architecture | | API 호출 방법 알기 | v1/02-api-pattern | | 새 리스트 페이지 만들기 | v1/03-component-design → v1/04-common-components | @@ -114,4 +120,5 @@ PATCH: 오탈자, 코드 예시 수정, 사소한 수정 | 코딩 컨벤션 확인 | v1/09-conventions | | 문서 관리 API 연동 | v1/10-document-api-integration | | AI/E2E 페이지 이동 규칙 | v1/11-browser-navigation-rules | +| 권한 기반 접근 제어 이해 | v1/12-permission-whitelist | | **동적 멀티테넌트 설계** | **v2/01-dynamic-multi-tenant-page-system** | diff --git a/frontend/v1/00-onboarding.md b/frontend/v1/00-onboarding.md new file mode 100644 index 0000000..7f0c8ef --- /dev/null +++ b/frontend/v1/00-onboarding.md @@ -0,0 +1,386 @@ +# 00. 신규 합류자 온보딩 가이드 + +> **대상**: 프로젝트에 새로 합류하는 개발자 (시니어 포함) +> **버전**: 1.0.0 +> **최종 수정**: 2026-03-20 +> **읽는 시간**: 15분 + +--- + +## 1. SAM ERP 한눈에 보기 + +SAM은 **멀티테넌트 폐쇄형 ERP** 시스템입니다. +인증된 사용자만 접근 가능하며, 테넌트(고객사)별로 필요한 모듈만 활성화됩니다. + +``` +┌─────────────────────────────────────────────────────────┐ +│ SAM ERP Platform │ +│ │ +│ ┌─────────────────────────────────────────────────┐ │ +│ │ 공통 ERP (~165 페이지) │ │ +│ │ 회계 | 영업 | 인사 | 결재 | 게시판 | 설정 │ │ +│ │ 고객센터 | 기준정보 | 자재/재고 | 출고/배송 │ │ +│ └─────────────────────────────────────────────────┘ │ +│ │ +│ ┌──────────────────┐ ┌──────────────────────────┐ │ +│ │ 경동 MES (~27p) │ │ 주일 건설 (~48p) │ │ +│ │ 생산관리 │ │ 시공/프로젝트 │ │ +│ │ 품질관리 │ │ 입찰/계약 │ │ +│ └──────────────────┘ │ 기성관리 │ │ +│ └──────────────────────────┘ │ +│ ┌──────────────────┐ │ +│ │ 옵션 모듈 │ │ +│ │ 차량관리 │ │ +│ └──────────────────┘ │ +└─────────────────────────────────────────────────────────┘ +``` + +--- + +## 2. 테넌트 구조 + +현재 3개 테넌트가 운영됩니다. + +| 테넌트 | 업종 | 전용 모듈 | 특징 | +|--------|------|-----------|------| +| 경동 | 셔터 제조 (MES) | 생산, 품질 | 작업지시/실적, 설비관리, QMS | +| 주일 | 건설 시공 | 건설/프로젝트 | 현장관리, 입찰, 기성 | +| (신규) | 일반 | 공통만 | 공통 ERP 기능만 사용 | + +### 테넌트별 접근 제어 + +``` +로그인 → 백엔드가 해당 테넌트의 메뉴 목록 반환 + → PermissionGate가 화이트리스트로 접근 제어 + → 메뉴에 없는 페이지 = 접근 불가 (URL 직접 입력도 차단) + +경동 유저: 회계, 영업, 생산, 품질 등 접근 가능 / 건설 차단 +주일 유저: 회계, 영업, 건설 등 접근 가능 / 생산, 품질 차단 +``` + +상세: [v1/12-permission-whitelist.md](12-permission-whitelist.md) + +--- + +## 3. 기술 스택 + +| 영역 | 기술 | +|------|------| +| 프레임워크 | Next.js 15 (App Router) | +| 런타임 | React 19 | +| 언어 | TypeScript (strict) | +| UI | shadcn/ui (Radix UI) + Tailwind CSS 4 | +| 상태관리 | Zustand | +| 폼 | react-hook-form + Zod | +| 백엔드 | PHP Laravel 12 (별도 프로젝트) | +| 모바일 | Capacitor (하이브리드 앱) | + +### 핵심 제약 + +- **모든 페이지 Client Component**: `'use client'` 필수 (HttpOnly 쿠키 인증 때문) +- **Server Component 사용 금지**: SEO 불필요 + 쿠키 수정 불가 +- **API 호출은 반드시 프록시**: `/api/proxy/` 또는 Server Action 경유 + +--- + +## 4. 프로젝트 구조 + +``` +sam_project/ +├── sam-next/sam-react-prod/ ← 프론트엔드 (현재 프로젝트) +├── sam-api/sam-api/ ← 백엔드 (PHP Laravel) +├── sam-design/sam-design/ ← 디자인 시스템 +└── sam-docs/ ← 프로젝트 문서 +``` + +### 프론트엔드 디렉토리 + +``` +src/ +├── app/[locale]/(protected)/ # 라우트 (도메인별 폴더) +│ ├── accounting/ # 회계 +│ ├── sales/ # 영업 +│ ├── hr/ # 인사 +│ ├── approval/ # 결재 +│ ├── production/ # 생산 (경동 전용) +│ ├── quality/ # 품질 (경동 전용) +│ ├── construction/ # 건설 (주일 전용) +│ ├── dashboard/ # CEO 대시보드 +│ └── settings/ # 설정 +│ +├── components/ # 컴포넌트 (계층 구조) +│ ├── ui/ # atoms (shadcn/ui) +│ ├── molecules/ # molecules (FormField, DateRangeSelector 등) +│ ├── organisms/ # organisms (PageLayout, IntegratedListTemplateV2 등) +│ ├── templates/ # templates (UniversalListPage 등) +│ ├── {domain}/ # 도메인별 비즈니스 컴포넌트 +│ └── document-system/ # 모듈 경계 넘는 공유 컴포넌트 +│ +├── stores/ # Zustand 전역 상태 +├── hooks/ # 커스텀 훅 +├── lib/ # 유틸리티, API 래퍼 +├── modules/ # 모듈 시스템 (테넌트 분리) +└── contexts/ # React Context (Permission 등) +``` + +--- + +## 5. 전역 상태 (Zustand Stores) + +| 스토어 | 역할 | 지속성 | +|--------|------|--------| +| `authStore` | 로그인 유저, 테넌트, 역할 정보 | localStorage | +| `menuStore` | 사이드바 메뉴 목록, 활성 메뉴, 접힘 상태 | localStorage | +| `permissionStore` | 메뉴별 권한 매트릭스 (view/create/update/delete) | 메모리 | +| `masterDataStore` | 기준정보 캐시 (품목, 공정 등) | 메모리 | +| `themeStore` | 테마 설정 | localStorage | +| `useUIStore` | UI 상태 (사이드바 너비 등) | 메모리 | +| `useItemMasterStore` | 품목 마스터 폼 상태 | 메모리 | +| `favoritesStore` | 즐겨찾기 메뉴 | localStorage | +| `useCalendarScheduleStore` | 캘린더 일정 | 메모리 | +| `useTableColumnStore` | 테이블 컬럼 설정 (표시/숨김) | localStorage | + +--- + +## 6. 라우팅 패턴 + +### 페이지 모드 (mode 쿼리파라미터) + +``` +/sales/order-management → 목록 (기본) +/sales/order-management?mode=new → 등록 폼 +/sales/order-management/123 → 상세 (view) +/sales/order-management/123?mode=edit → 수정 폼 +``` + +- 별도 `/new`, `/edit` 경로 사용 금지 +- 목록과 등록을 같은 page.tsx에서 mode로 분기 + +### 페이지 유형 + +| 유형 | 컴포넌트 | 특징 | +|------|----------|------| +| 목록 | `UniversalListPage` | 검색, 페이지네이션, 컬럼 설정, 모바일 카드 | +| 상세/폼 | `Card` + `FormField` | sticky 하단 액션 바, 모드별 분기 | +| 대시보드 | 섹션 기반 | 모듈별 조건부 렌더링 | + +--- + +## 7. 도메인 맵 + +### 공통 ERP (모든 테넌트) + +``` +회계 (accounting/) +├── 매출/매입 관리 +├── 입출금 관리 +├── 세금계산서 +├── 거래처 원장 +├── 경조사비/접대비 +└── 일보/결산 + +영업 (sales/) +├── 견적/수주 관리 +├── 단가 관리 +├── 생산지시 (공유 API) +└── 거래처 관리 + +인사 (hr/) +├── 직원 관리 +├── 근태/출결 +├── 급여/휴가 +└── 인사 이력 + +결재 (approval/) +├── 기안/수신/참조 +└── 결재 양식 관리 + +기준정보 (master-data/) +├── 품목 마스터 +├── 공정 관리 +└── 단가 테이블 + +자재/재고 (material/, stocks/) +├── 입고 관리 +├── 재고 현황 +└── 재고 생산 + +출고/배송 (outbound/) +├── 출하 관리 +└── 차량 배차 +``` + +### 경동 전용 (셔터 제조 MES) + +``` +생산 (production/) +├── 작업지시 +├── 작업실적 +├── 작업자 화면 +└── 생산 대시보드 + +품질 (quality/) +├── 설비 관리/점검/수리 +├── 검사 관리 +├── QMS (문서관리) +└── 성적서/작업일지 +``` + +### 주일 전용 (건설 시공) + +``` +건설 (construction/) +├── 수주/현장 관리 +├── 프로젝트 관리 +│ ├── 계약/실행예산 +│ ├── 입찰 관리 +│ ├── 시공 관리 +│ └── 인력 현황 +└── 기성 관리 +``` + +--- + +## 8. 데이터 흐름 + +``` +[컴포넌트] → Server Action (또는 fetch /api/proxy/...) + │ + ↓ + [authenticatedFetch] + │ + ├── 정상 → 데이터 반환 + ├── 401 → 자동 토큰 갱신 → 재시도 + └── 실패 → 로그인 페이지 이동 + +Server Action 위치: src/components/{domain}/actions.ts +URL 빌더: buildApiUrl('/api/v1/path', { search, page }) +``` + +--- + +## 9. 모듈 분리 현황 + +코드 아키텍처 레벨에서 공통 ERP와 테넌트 전용 코드의 경계를 관리합니다. + +| 단계 | 상태 | 내용 | +|------|------|------| +| Phase 0 | 완료 | 공통 -> 테넌트 import 의존성 해소 | +| Phase 1 | 완료 | 모듈 레지스트리 + useModules() 훅 | +| Phase 2 | 완료 | CEO 대시보드 모듈화 (섹션/API 최적화) | +| Phase 3 | 완료 | 검증 스크립트 + 경계 문서 (MODULE.md) | +| 화이트리스트 | 완료 | PermissionGate 화이트리스트 전환 | + +### 모듈 경계 규칙 + +``` +허용: 테넌트 → 공통 import (production → ui/) +금지: 공통 → 테넌트 import (approval → production/) +금지: 테넌트 간 import (production → construction/) + +공유 필요 시: document-system/ 또는 lib/api/ 래퍼 경유 +``` + +검증: `scripts/verify-module-separation.sh` + +--- + +## 10. 향후 로드맵 + +``` +v1 (현재) ──── 모듈 분리 완료, 권한 화이트리스트 + │ +v2 (진행) ──── 백엔드에서 모듈/페이지 정보 JSON API 제공 + │ useModules() 내부를 API 호출로 교체 + │ +v3 (목표) ──── JSON 스키마 기반 동적 페이지 조립 + 테넌트 추가 = 어드민 설정만 → 코드 변경 0줄 +``` + +상세: [v2/01-dynamic-multi-tenant-page-system.md](../v2/01-dynamic-multi-tenant-page-system.md) + +--- + +## 11. 문서 읽기 순서 + +### 첫째 날: 전체 구조 파악 + +| 순서 | 문서 | 핵심 | +|------|------|------| +| 1 | 이 문서 (00-onboarding) | 시스템 전체 그림 | +| 2 | [01-architecture](01-architecture.md) | 기술 스택, 디렉토리 구조 | +| 3 | [07-auth-flow](07-auth-flow.md) | 인증/토큰 흐름 | +| 4 | [12-permission-whitelist](12-permission-whitelist.md) | 접근 제어 | + +### 둘째 날: 개발 패턴 익히기 + +| 순서 | 문서 | 핵심 | +|------|------|------| +| 5 | [02-api-pattern](02-api-pattern.md) | API 호출 방법 | +| 6 | [03-component-design](03-component-design.md) | 컴포넌트 계층 | +| 7 | [04-common-components](04-common-components.md) | UniversalListPage 등 사용법 | +| 8 | [05-form-pattern](05-form-pattern.md) | 폼 패턴 (Zod, FormField) | + +### 셋째 날: 세부 규칙 + +| 순서 | 문서 | 핵심 | +|------|------|------| +| 9 | [06-styling-guide](06-styling-guide.md) | Tailwind, 색상 | +| 10 | [08-dashboard-system](08-dashboard-system.md) | 대시보드 아키텍처 | +| 11 | [09-conventions](09-conventions.md) | 네이밍, Git 규칙 | + +--- + +## 12. Git 브랜치 전략 + +``` +main ────── 배포용 (검증된 것만, 기능별 squash merge) + │ +develop ─── 평소 작업 (자유롭게 커밋) + │ +feature/* ─ 큰 기능/실험적 작업 시 사용 +``` + +- develop에서 자유롭게 작업 +- main에는 기능별 squash merge (cherry-pick + 정리) +- main 직접 push 금지 + +--- + +## 13. 개발 환경 셋업 + +```bash +# 1. 의존성 설치 +npm install + +# 2. 환경변수 (.env.local) +# 팀원에게 받거나 sam-docs 참고 + +# 3. 개발 서버 +npm run dev + +# 4. 접속 +http://localhost:3000 +``` + +### 주요 명령어 + +| 명령어 | 용도 | +|--------|------| +| `npm run dev` | 개발 서버 | +| `npm run build` | 프로덕션 빌드 | +| `npx tsc --noEmit` | 타입 체크 | + +--- + +## 14. 자주 하는 실수 + +| 실수 | 올바른 방법 | +|------|-------------| +| Server Component 사용 | `'use client'` 필수 | +| localStorage 직접 접근 | `typeof window` 가드 필요 | +| API 직접 fetch | Server Action 또는 `/api/proxy/` 사용 | +| `/new`, `/edit` 라우트 생성 | `?mode=new`, `?mode=edit` 쿼리 사용 | +| `DatePicker` 2개 직접 조합 | `DateRangeSelector` 사용 | +| `Label + Input` 수동 조합 | `FormField` molecule 사용 | +| 공통에서 테넌트 코드 import | `document-system/` 래퍼 경유 | \ No newline at end of file diff --git a/frontend/v1/12-permission-whitelist.md b/frontend/v1/12-permission-whitelist.md new file mode 100644 index 0000000..50bf68b --- /dev/null +++ b/frontend/v1/12-permission-whitelist.md @@ -0,0 +1,134 @@ +# 12. 권한 기반 페이지 접근 제어 (화이트리스트) + +> **대상**: 프론트엔드/백엔드 개발자 +> **버전**: 1.0.0 +> **최종 수정**: 2026-03-20 + +--- + +## 1. 개요 + +PermissionGate가 **화이트리스트 방식**으로 동작합니다. +메뉴 권한에 등록되지 않은 페이지는 접근이 차단됩니다. + +``` +메뉴 권한에 있음 + view: true → 허용 +메뉴 권한에 있음 + view: false → 차단 (AccessDenied) +메뉴 권한에 없음 → 차단 (AccessDenied) +``` + +--- + +## 2. 왜 화이트리스트? + +| 방식 | 동작 | 문제 | +|------|------|------| +| 블랙리스트 (이전) | 권한에 없으면 허용 | 메뉴 미할당 페이지에 URL 직접 접근 가능 | +| **화이트리스트 (현재)** | 권한에 없으면 차단 | 메뉴 등록된 페이지만 접근 가능 | + +기존 정책과 일치: +``` +테넌트 생성 → 글로벌 메뉴 동기화 → 역할 생성 → 메뉴 권한 설정 → 접근 가능 +``` + +메뉴 권한이 설정되지 않은 페이지는 접근할 수 없는 것이 정상 동작입니다. + +--- + +## 3. 바이패스 경로 + +메뉴 권한 없이도 항상 접근 가능한 시스템 페이지: + +| 경로 | 이유 | +|------|------| +| `/settings/permissions` | 자기 잠금 방지 (권한 설정 페이지) | +| `/settings/account-info` | 내 계정 설정 | +| `/dashboard` | 대시보드 (모든 유저 필수, `startsWith`로 type2~5 포함) | +| `/company-info` | 회사 정보 | +| `/subscription` | 구독 관리 | +| `/dev`, `/test` | 개발 도구 (개발 환경에서만 활성화) | + +### 바이패스 추가/관리 + +파일: `src/contexts/PermissionContext.tsx` + +```typescript +const BYPASS_PATHS = [ + '/settings/permissions', + '/settings/account-info', + '/dashboard', + '/company-info', + '/subscription', + ...(process.env.NODE_ENV === 'development' ? ['/dev', '/test'] : []), +]; +``` + +- `startsWith` 매칭: `/dashboard` → `/dashboard_type2`, `/dashboard_type3` 등 모두 포함 +- 비즈니스 페이지는 바이패스에 추가하지 않음 (권한으로 제어) + +--- + +## 4. 접근 제어 흐름 + +``` +유저가 페이지 접근 + │ + ├─ 권한 로딩 중 → 빈 화면 (로딩) + │ + ├─ permissionMap 없음 (로딩 실패) → 통과 (안전장치) + │ + ├─ BYPASS_PATHS 매칭 → 통과 + │ + └─ findMatchingUrl (longest prefix match) + ├─ 매칭됨 + view: true → 허용 + ├─ 매칭됨 + view: false → AccessDenied + └─ 매칭 없음 → AccessDenied +``` + +### findMatchingUrl 동작 + +``` +접근: /accounting/deposits/123 +permissionMap: { "/accounting/deposits": { view: true, ... } } + +1. 정확히 매칭: /accounting/deposits/123 → 없음 +2. Prefix 매칭: /accounting/deposits → 있음! → view 확인 +``` + +상위 경로에 권한이 있으면 하위 경로도 접근 가능합니다. + +--- + +## 5. 프론트엔드 개발자 체크리스트 + +| 항목 | 설명 | +|------|------| +| 새 페이지 추가 시 | 백엔드 메뉴 등록 필수 (미등록 = 접근 불가) | +| 시스템 페이지 추가 시 | BYPASS_PATHS에 추가 검토 | +| 개발 중 접근 차단 시 | 해당 메뉴의 권한 설정 확인 | +| 테넌트별 접근 제어 | 메뉴 권한으로 제어 (프론트 코드 변경 불필요) | + +--- + +## 6. 백엔드 개발자 참고 + +| 항목 | 설명 | +|------|------| +| 새 메뉴 추가 시 | 글로벌 메뉴 등록 → 테넌트 동기화 → 역할별 권한 설정 | +| 테넌트별 페이지 차단 | 해당 테넌트에 메뉴 미할당 또는 view: false | +| industry 기반 프리셋 (향후) | 테넌트 생성 시 업종별 메뉴 프리셋 자동 적용 | + +--- + +## 7. 모듈 시스템과의 역할 분담 + +| 역할 | PermissionGate | 모듈 시스템 (useModules) | +|------|---|---| +| 페이지 접근 차단 | O | X (제거 검토) | +| 메뉴 표시/숨김 | O (백엔드 메뉴 응답) | X | +| 대시보드 섹션 ON/OFF | X | O | +| 대시보드 API 호출 최적화 | X | O | +| JSON 동적 페이지 초석 | X | O | + +- **PermissionGate**: 접근 제어 ("누가 어디에 들어갈 수 있는가") +- **모듈 시스템**: 화면 구성 ("들어간 페이지에 뭘 보여줄 것인가") \ No newline at end of file diff --git a/frontend/v2/01-dynamic-multi-tenant-page-system.md b/frontend/v2/01-dynamic-multi-tenant-page-system.md index 862c910..6751ab1 100644 --- a/frontend/v2/01-dynamic-multi-tenant-page-system.md +++ b/frontend/v2/01-dynamic-multi-tenant-page-system.md @@ -1,11 +1,16 @@ # 동적 멀티테넌트 페이지 시스템 설계 > 작성일: 2026-03-11 -> 상태: 초안 (백엔드 논의 필요) +> 최종 업데이트: 2026-03-20 +> 상태: 초안 (백엔드 논의 진행 중) > 관련 문서: > - `[VISION-2026-02-19] dynamic-rendering-platform-strategy.md` > - `[PLAN-2026-02-06] multi-tenancy-optimization-roadmap.md` > - `[DESIGN-2026-02-11] dynamic-field-type-extension.md` +> - `[ANALYSIS-2026-03-17] tenant-module-separation-dependency-audit.md` +> - `[PLAN-2026-03-17] tenant-module-separation-plan.md` — Phase 0~3 실행 계획 +> - `[IMPL-2026-03-20] permission-whitelist-gate.md` — PermissionGate 화이트리스트 전환 +> - `sam-docs/frontend/v1/12-permission-whitelist.md` — 권한 기반 접근 제어 가이드 --- @@ -761,9 +766,61 @@ DynamicItemForm의 ComputedField → computed 타입으로 범용화 ### 규칙 17: 점진적 마이그레이션 전략 +#### 17-1. 3단계 아키텍처 방향 (2026-03-17 확인) + +``` +1단계: 현재 → 모듈 분리 + - 공통 ERP / 테넌트별 모듈 물리적 분리 + - 선결과제 해소 (아래 17-2 참조) + +2단계: 모듈 분리 → JSON 동적 조립 + - 테넌트 모듈을 manifest/JSON 기반으로 전환 + - 동적 페이지 렌더러 도입 + +3단계: 최종 — 빈 페이지 셸 + 백엔드 JSON으로 페이지 자동 조립 + - 이 문서의 최종 목표 +``` + +#### 17-2. 선결과제 (모듈 분리 전 해결 필수) + +| # | 과제 | 내용 | 예상 | +|---|------|------|------| +| 1 | CEO 대시보드 테넌트 의존성 해소 | 생산/건설 섹션 직접 import → 동적 로딩 전환 | - | +| 2 | 공유 컴포넌트 추출 | 결재/영업(공통)이 생산(경동) 코드 직접 import | - | +| 3 | 라우트 가드 추가 | 테넌트 미보유 모듈 URL 직접 접근 차단 | - | +| 4 | dashboard-invalidation 동적화 | production/construction 도메인 키 하드코딩 제거 | - | + +> 선결과제 해소 예상: 3~4일, 이후 모듈 분리 본작업은 별도 산정 + +**핵심 의존성 위반 (공통 → 테넌트 방향, 수정 필요)**: +``` +ApprovalBox → production/InspectionReportModal +Sales/production-orders → production/ProductionOrders (actions+types+UI) +Sales → router.push("/production/work-orders") 하드코딩 +CEODashboard → DailyProductionSection, ConstructionSection 직접 import +dashboard-invalidation.ts → production/construction 도메인 키 +``` + +**안전한 부분**: +- 테넌트 간 교차 의존성 없음 (생산↔건설 = 0) +- 건설(주일) 모듈 완전 독립 → 바로 분리 가능 +- Zustand 스토어, API 프록시, 메뉴 시스템은 무관 + +#### 17-3. 테넌트별 페이지 현황 (2026-03-17 분석) + +| 테넌트 | 업종 | 전용 모듈 | 페이지 수 | +|--------|------|----------|:---:| +| 공통 ERP | 전 업종 | 회계, 인사, 결재, 게시판, 설정, 고객센터 등 | ~165 | +| 경동 | 셔터 제조 (MES) | 생산, 품질관리 | ~27 | +| 주일 | 건설 시공 | 건설/프로젝트, 입찰, 기성 | ~48 | +| (옵션) | - | 차량관리 | ~13 | + +#### 17-4. 마이그레이션 Phase + | Phase | 범위 | 예상 기간 | 상태 | |-------|------|----------|------| -| **Phase 0** | 인프라 구축 | 2-3주 | ⏳ 준비 | +| **선결과제** | 의존성 해소 (17-2) | 3-4일 | ⏳ 준비 | +| **Phase 0** | 인프라 구축 | 2-3주 | ⏳ | | | - catch-all 라우터 | | | | | - pageConfigStore | | | | | - DynamicListPage/FormPage 렌더러 | | | @@ -776,13 +833,13 @@ DynamicItemForm의 ComputedField → computed 타입으로 범용화 | | - 거래처관리, 설비관리 등 | | | | **Phase 3** | 복잡한 비즈니스 페이지 전환 | 6-8주 | ⏳ | | | - 견적, 수주, 생산 등 로직 있는 페이지 | | | -| | - 로직 블록 구축 병행 | | | | **Phase 4** | 기존 정적 → 동적 완전 전환 | 지속적 | ⏳ | | | - 남은 하드코딩 페이지 점진적 전환 | | | ``` 전환 판단 기준: +[선행] 선결과제 해소 (의존성 분리) → 선결과제 Phase [쉬움] 순수 CRUD (리스트+폼) → Phase 2에서 전환 [보통] CRUD + 단순 계산 → Phase 2~3 [어려움] 복잡한 비즈니스 로직 → Phase 3 @@ -886,9 +943,10 @@ DynamicItemForm의 ComputedField → computed 타입으로 범용화 | 동적 필드 타입 설계 | `claudedocs/architecture/[DESIGN-2026-02-11]` | 4-Level 구조, 14종 필드 | | 동적 필드 구현 현황 | `claudedocs/architecture/[IMPL-2026-02-11]` | Phase 1~3 프론트 구현 완료 | | 백엔드 API 스펙 | `claudedocs/item-master/[API-REQUEST-2026-02-12]` | 동적 필드 타입 백엔드 요청서 | +| 테넌트 모듈 의존성 분석 | `claudedocs/architecture/[ANALYSIS-2026-03-17]` | 3테넌트 분리, 선결과제 4개, 의존성 위반 목록 | --- -**문서 버전**: 1.2 -**마지막 업데이트**: 2026-03-11 +**문서 버전**: 1.3 +**마지막 업데이트**: 2026-03-18 **다음 단계**: 백엔드 회의 → 협의 필요 항목 확정 → v2.0 작성 → `sam-docs/frontend/v2/`에 최종본 등록