docs:견적관리 분석 문서 및 INDEX 업데이트
- INDEX.md 업데이트 - 견적관리 URL 마이그레이션 계획 수정 - API 분석 리포트, tenant-id 준수 계획 추가 - 견적관리 기능 문서 추가 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2
INDEX.md
2
INDEX.md
@@ -19,6 +19,7 @@
|
||||
| **품목관리** | `rules/item-policy.md` | 품목 정책 (유형, 예약어, API 규칙) |
|
||||
| **게시판** | `specs/board-system-spec.md` | 게시판 시스템 설계 |
|
||||
| **단가관리** | `rules/pricing-policy.md` | 원가/판매가 계산, 리비전 관리 |
|
||||
| **견적관리** | `features/quotes/README.md` | 견적 시스템, BOM 계산, 10단계 로직 |
|
||||
| **MES 개발** | `projects/mes/README.md` | MES 프로젝트 개요 |
|
||||
|
||||
---
|
||||
@@ -124,6 +125,7 @@ docs/
|
||||
| [boards/README.md](features/boards/README.md) | 게시판 시스템 구현 |
|
||||
| [boards/mng-implementation.md](features/boards/mng-implementation.md) | MNG 게시판 구현 상세 |
|
||||
| [hr/hr-api-analysis.md](features/hr/hr-api-analysis.md) | HR API 분석 (근태/직원/부서) |
|
||||
| [quotes/README.md](features/quotes/README.md) | 견적 시스템 분석 (BOM 계산, 10단계 로직) |
|
||||
|
||||
### projects/ - 프로젝트별 문서
|
||||
|
||||
|
||||
455
features/quotes/README.md
Normal file
455
features/quotes/README.md
Normal file
@@ -0,0 +1,455 @@
|
||||
# 견적 시스템 분석 문서
|
||||
|
||||
> **목적**: 견적 시스템의 비즈니스 로직과 데이터 흐름을 이해하고 검증하기 위한 문서
|
||||
|
||||
## 목차
|
||||
|
||||
1. [개요](#1-개요)
|
||||
2. [데이터베이스 구조](#2-데이터베이스-구조)
|
||||
3. [견적 생성 흐름](#3-견적-생성-흐름)
|
||||
4. [BOM 계산 로직 (10단계)](#4-bom-계산-로직-10단계)
|
||||
5. [경동기업 전용 로직](#5-경동기업-전용-로직)
|
||||
6. [상태 관리](#6-상태-관리)
|
||||
7. [금액 계산 방식](#7-금액-계산-방식)
|
||||
8. [관련 파일 목록](#8-관련-파일-목록)
|
||||
|
||||
---
|
||||
|
||||
## 1. 개요
|
||||
|
||||
### 1.1 견적 유형
|
||||
|
||||
| 유형 | 코드 | 설명 |
|
||||
|------|------|------|
|
||||
| 제조 견적 | `manufacturing` | 스크린/철재 제품 제조 견적 |
|
||||
| 시공 견적 | `construction` | 현장설명회 기반 시공 견적 |
|
||||
|
||||
### 1.2 제품 카테고리
|
||||
|
||||
| 카테고리 | 코드 | 설명 |
|
||||
|----------|------|------|
|
||||
| 스크린 | `SCREEN` | 방화 스크린 제품 |
|
||||
| 철재 | `STEEL` | 철재 제품 |
|
||||
|
||||
### 1.3 핵심 서비스 클래스
|
||||
|
||||
```
|
||||
QuoteService ← 견적 CRUD, 상태 관리, 수주 전환
|
||||
├── QuoteNumberService ← 견적번호 생성 (KD-SC-YYMMDD-NN)
|
||||
├── QuoteCalculationService ← 자동산출 실행, BOM 계산 호출
|
||||
└── FormulaEvaluatorService ← 수식 평가, 10단계 BOM 계산
|
||||
└── KyungdongFormulaHandler ← 경동기업(tenant_id=287) 전용 계산
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 2. 데이터베이스 구조
|
||||
|
||||
### 2.1 테이블 관계도
|
||||
|
||||
```
|
||||
┌─────────────────┐
|
||||
│ quotes │ ← 견적 마스터
|
||||
├─────────────────┤
|
||||
│ id │
|
||||
│ tenant_id │──→ tenants
|
||||
│ quote_number │
|
||||
│ quote_type │ ← manufacturing | construction
|
||||
│ status │ ← pending→draft→finalized→converted
|
||||
│ client_id │──→ clients
|
||||
│ item_id │──→ items (완제품)
|
||||
│ site_briefing_id│──→ site_briefings (시공 견적용)
|
||||
│ order_id │──→ orders (수주 전환 후)
|
||||
│ calculation_inputs (JSON) │ ← 자동산출 입력값 + BOM 결과
|
||||
│ options (JSON) │ ← 세부산출, 비용항목, 할인 정보
|
||||
└────────┬────────┘
|
||||
│ 1:N
|
||||
▼
|
||||
┌─────────────────┐
|
||||
│ quote_items │ ← 견적 품목 상세
|
||||
├─────────────────┤
|
||||
│ id │
|
||||
│ quote_id │──→ quotes
|
||||
│ tenant_id │
|
||||
│ item_id │──→ items
|
||||
│ item_code │
|
||||
│ item_name │
|
||||
│ calculated_quantity │
|
||||
│ unit_price │
|
||||
│ total_price │
|
||||
│ formula │ ← 수량 계산 수식
|
||||
│ formula_category│ ← 카테고리 (material/labor/install)
|
||||
└─────────────────┘
|
||||
|
||||
┌─────────────────┐
|
||||
│ quote_revisions │ ← 수정 이력
|
||||
├─────────────────┤
|
||||
│ quote_id │──→ quotes
|
||||
│ revision_number │
|
||||
│ previous_data (JSON) │ ← 수정 전 스냅샷
|
||||
└─────────────────┘
|
||||
```
|
||||
|
||||
### 2.2 quotes 테이블 주요 필드
|
||||
|
||||
| 필드명 | 타입 | 설명 |
|
||||
|--------|------|------|
|
||||
| `quote_number` | VARCHAR(50) | 견적번호 (예: KD-SC-251204-01) |
|
||||
| `quote_type` | ENUM | `manufacturing` / `construction` |
|
||||
| `status` | ENUM | 상태 (pending→draft→finalized→converted) |
|
||||
| `product_category` | ENUM | `SCREEN` / `STEEL` |
|
||||
| `open_size_width` | INT | 개구부 폭 (mm) |
|
||||
| `open_size_height` | INT | 개구부 높이 (mm) |
|
||||
| `quantity` | INT | 수량 |
|
||||
| `material_cost` | DECIMAL | 재료비 합계 |
|
||||
| `labor_cost` | DECIMAL | 노무비 |
|
||||
| `install_cost` | DECIMAL | 설치비 |
|
||||
| `subtotal` | DECIMAL | 소계 |
|
||||
| `discount_rate` | DECIMAL | 할인율 (%) |
|
||||
| `total_amount` | DECIMAL | 최종 금액 |
|
||||
| `calculation_inputs` | JSON | 자동산출 입력값 및 BOM 결과 저장 |
|
||||
| `options` | JSON | 세부산출항목, 비용항목, 할인정보 |
|
||||
| `is_final` | BOOLEAN | 최종확정 여부 |
|
||||
|
||||
### 2.3 calculation_inputs JSON 구조
|
||||
|
||||
```json
|
||||
{
|
||||
"items": [
|
||||
{
|
||||
"floor": "B1",
|
||||
"code": "A-01",
|
||||
"openWidth": 3000,
|
||||
"openHeight": 2500,
|
||||
"quantity": 2,
|
||||
"productCategory": "SCREEN",
|
||||
"productName": "KD-SCREEN-001",
|
||||
"guideRailType": "wall",
|
||||
"motorPower": "single"
|
||||
}
|
||||
],
|
||||
"bomResults": [
|
||||
{
|
||||
"index": 0,
|
||||
"finished_goods_code": "KD-SCREEN-001",
|
||||
"items": [
|
||||
{
|
||||
"item_code": "GUIDE-001",
|
||||
"item_name": "가이드레일",
|
||||
"quantity": 2.5,
|
||||
"unit_price": 50000,
|
||||
"total_price": 125000,
|
||||
"is_manual": false
|
||||
}
|
||||
],
|
||||
"grand_total": 1250000
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. 견적 생성 흐름
|
||||
|
||||
### 3.1 제조 견적 생성 흐름
|
||||
|
||||
```
|
||||
[프론트엔드 - React]
|
||||
│
|
||||
▼
|
||||
1. 기본정보 입력 (거래처, 현장, 제품카테고리)
|
||||
│
|
||||
▼
|
||||
2. 위치별 규격 입력 (층/부호, 개구부 크기, 수량)
|
||||
│
|
||||
▼
|
||||
3. "견적 산출" 버튼 클릭
|
||||
│
|
||||
▼
|
||||
[API 호출: POST /api/v1/quotes/bom/calculate-bulk]
|
||||
│
|
||||
▼
|
||||
4. QuoteCalculationService.calculateBomBulk()
|
||||
│
|
||||
├─→ 경동기업(287)? → KyungdongFormulaHandler
|
||||
│
|
||||
└─→ 기타 테넌트 → 표준 BOM 계산
|
||||
│
|
||||
▼
|
||||
5. 10단계 계산 결과 반환
|
||||
│
|
||||
▼
|
||||
6. 프론트엔드에서 결과 표시 (세부산출내역)
|
||||
│
|
||||
▼
|
||||
7. "저장" 또는 "최종확정" 버튼
|
||||
│
|
||||
▼
|
||||
[API 호출: POST /api/v1/quotes 또는 PUT /api/v1/quotes/{id}]
|
||||
│
|
||||
▼
|
||||
8. QuoteService.store() / update()
|
||||
- quotes 테이블에 마스터 정보 저장
|
||||
- quote_items 테이블에 품목 상세 저장
|
||||
- calculation_inputs에 입력값 + BOM 결과 저장
|
||||
```
|
||||
|
||||
### 3.2 시공 견적 생성 흐름 (현장설명회 연계)
|
||||
|
||||
```
|
||||
[현장설명회]
|
||||
│
|
||||
▼
|
||||
1. 현장설명회 참석완료 상태 변경
|
||||
│
|
||||
▼
|
||||
2. QuoteService.upsertFromSiteBriefing()
|
||||
│
|
||||
▼
|
||||
3. 견적 자동 생성 (status: pending)
|
||||
- 거래처, 현장 정보 복사
|
||||
- 금액 정보는 비어있음
|
||||
│
|
||||
▼
|
||||
4. 담당자가 견적 편집 화면에서 상세 입력
|
||||
│
|
||||
▼
|
||||
5. 저장 시 status: pending → draft 변경
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. BOM 계산 로직 (10단계)
|
||||
|
||||
### 4.1 계산 단계 개요
|
||||
|
||||
| 단계 | 명칭 | 설명 |
|
||||
|------|------|------|
|
||||
| 1 | 입력값수집 | W0, H0, QTY, 옵션값 수집 |
|
||||
| 2 | 완제품선택 | 완제품 코드로 items 테이블 조회 |
|
||||
| 3 | 변수계산 | W1, H1, AREA, WEIGHT 등 파생 변수 계산 |
|
||||
| 4 | BOM전개 | 완제품의 BOM 트리 전개 |
|
||||
| 5 | 단가출처 | 품목별 단가 조회 (prices 테이블) |
|
||||
| 6 | 수량계산 | 수량 수식 평가 (변수 치환) |
|
||||
| 7 | 금액계산 | 수량 × 단가 = 금액 |
|
||||
| 8 | 카테고리그룹화 | item_category 기준 그룹화 |
|
||||
| 9 | 소계계산 | 카테고리별 소계 |
|
||||
| 10 | 최종합계 | 전체 합계 계산 |
|
||||
|
||||
### 4.2 변수 계산 (Step 3) 상세
|
||||
|
||||
```
|
||||
기본 변수:
|
||||
- W0: 개구부 폭 (mm) - 사용자 입력
|
||||
- H0: 개구부 높이 (mm) - 사용자 입력
|
||||
- QTY: 수량 - 사용자 입력
|
||||
|
||||
파생 변수 (스크린):
|
||||
- W1 = W0 + 140 (제작 폭, 마진 140mm)
|
||||
- H1 = H0 + 350 (제작 높이, 마진 350mm)
|
||||
- M = (W1 × H1) / 1,000,000 (면적, ㎡)
|
||||
- K = M × 2 + (W0 / 1000) × 14.17 (중량, kg)
|
||||
|
||||
파생 변수 (철재):
|
||||
- W1 = W0 + 110 (마진 110mm)
|
||||
- H1 = H0 + 350
|
||||
- M = (W1 × H1) / 1,000,000
|
||||
- K = M × 25 (철재 중량)
|
||||
```
|
||||
|
||||
### 4.3 수량 수식 예시
|
||||
|
||||
BOM의 quantity_formula 필드에 저장된 수식:
|
||||
|
||||
```
|
||||
고정값: "1"
|
||||
변수참조: "QTY"
|
||||
계산식: "W1 / 1000" → 가이드레일 길이
|
||||
"CEIL(H1 / 2000)" → 분할 개수
|
||||
"M * 1.1" → 면적 기반 수량 (여유 10%)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. 경동기업 전용 로직
|
||||
|
||||
### 5.1 적용 조건
|
||||
|
||||
```php
|
||||
// tenant_id = 287 일 때만 적용
|
||||
private const KYUNGDONG_TENANT_ID = 287;
|
||||
|
||||
if ($tenantId === self::KYUNGDONG_TENANT_ID) {
|
||||
return $this->calculateKyungdongBom(...);
|
||||
}
|
||||
```
|
||||
|
||||
### 5.2 KyungdongFormulaHandler 주요 기능
|
||||
|
||||
| 기능 | 설명 |
|
||||
|------|------|
|
||||
| 모터 용량 계산 | 제품타입 × 인치 × 중량 3차원 조건표 |
|
||||
| 브라켓 크기 결정 | 중량 기준 브라켓 인치 결정 |
|
||||
| 절곡품 계산 | 10종 절곡품 (케이스, 가이드레일, 하단바 등) |
|
||||
| 부자재 계산 | 3종 부자재 (볼트, 너트, 패킹 등) |
|
||||
|
||||
### 5.3 경동기업 변수 계산
|
||||
|
||||
```
|
||||
기본 변수:
|
||||
- W0, H0, QTY: 사용자 입력
|
||||
- bracket_inch: 브라켓 인치 (5", 6", 7")
|
||||
- product_type: 제품 타입 (screen/steel)
|
||||
|
||||
파생 변수:
|
||||
- W1 = W0 + 140
|
||||
- H1 = H0 + 350
|
||||
- AREA = (W0 × (H0 + 550)) / 1,000,000
|
||||
- WEIGHT = AREA × 2 + (W0 / 1000) × 14.17 (스크린)
|
||||
= AREA × 25 (철재)
|
||||
- MOTOR_CAPACITY: 모터 용량 (조건표 조회)
|
||||
- BRACKET_SIZE: 브라켓 크기 (조건표 조회)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. 상태 관리
|
||||
|
||||
### 6.1 견적 상태 흐름
|
||||
|
||||
```
|
||||
pending ─────→ draft ─────→ finalized ─────→ converted
|
||||
(견적대기) (작성중) (최종확정) (수주전환)
|
||||
│ │ │
|
||||
│ ▼ │
|
||||
│ sent ────────────→│
|
||||
│ (발송됨) │
|
||||
│ │ │
|
||||
│ ▼ │
|
||||
│ approved │
|
||||
│ (승인됨) │
|
||||
│ │ │
|
||||
└──────────────┴──────────────┘
|
||||
│
|
||||
▼
|
||||
rejected
|
||||
(거절됨)
|
||||
```
|
||||
|
||||
### 6.2 상태별 가능 작업
|
||||
|
||||
| 상태 | 수정 | 삭제 | 확정 | 수주전환 |
|
||||
|------|------|------|------|----------|
|
||||
| pending | ✓ | ✓ | - | - |
|
||||
| draft | ✓ | ✓ | ✓ | - |
|
||||
| sent | ✓ | ✓ | ✓ | - |
|
||||
| approved | ✓ | ✓ | ✓ | - |
|
||||
| finalized | - | - | - | ✓ |
|
||||
| converted | - | - | - | - |
|
||||
| rejected | ✓ | ✓ | - | - |
|
||||
|
||||
---
|
||||
|
||||
## 7. 금액 계산 방식
|
||||
|
||||
### 7.1 카테고리 기반 단가 계산
|
||||
|
||||
CategoryGroup 모델을 사용하여 품목 카테고리별 단가 계산 방식 결정:
|
||||
|
||||
| 카테고리 그룹 | 계산 방식 | 수식 |
|
||||
|--------------|----------|------|
|
||||
| area_based | 면적 기반 | 단가 × M (면적) |
|
||||
| weight_based | 중량 기반 | 단가 × K (중량) |
|
||||
| quantity_based | 수량 기반 | 단가 × 수량 |
|
||||
|
||||
### 7.2 총 금액 계산
|
||||
|
||||
```
|
||||
material_cost = SUM(재료비 카테고리 품목의 total_price)
|
||||
labor_cost = SUM(노무비 카테고리 품목의 total_price)
|
||||
install_cost = SUM(설치비 카테고리 품목의 total_price)
|
||||
|
||||
subtotal = material_cost + labor_cost + install_cost
|
||||
discount_amount = subtotal × (discount_rate / 100)
|
||||
total_amount = subtotal - discount_amount
|
||||
```
|
||||
|
||||
### 7.3 단가 조회 우선순위
|
||||
|
||||
1. **prices 테이블** (Price::getSalesPriceByItemCode)
|
||||
2. **items.attributes.salesPrice** (JSON 필드)
|
||||
3. **기본값 0**
|
||||
|
||||
---
|
||||
|
||||
## 8. 관련 파일 목록
|
||||
|
||||
### 8.1 백엔드 (API)
|
||||
|
||||
```
|
||||
app/Services/Quote/
|
||||
├── QuoteService.php ← 견적 CRUD, 상태 관리
|
||||
├── QuoteCalculationService.php ← BOM 계산 진입점
|
||||
├── QuoteNumberService.php ← 견적번호 생성
|
||||
├── QuoteDocumentService.php ← 견적서/거래명세서 PDF
|
||||
├── FormulaEvaluatorService.php ← 수식 평가, 10단계 계산
|
||||
└── Handlers/
|
||||
└── KyungdongFormulaHandler.php ← 경동기업 전용
|
||||
|
||||
app/Models/Quote/
|
||||
├── Quote.php ← 견적 마스터 모델
|
||||
├── QuoteItem.php ← 견적 품목 모델
|
||||
├── QuoteRevision.php ← 수정 이력 모델
|
||||
├── QuoteFormula.php ← 수식 정의 모델
|
||||
├── QuoteFormulaCategory.php
|
||||
├── QuoteFormulaRange.php
|
||||
├── QuoteFormulaMapping.php
|
||||
└── QuoteFormulaItem.php
|
||||
|
||||
database/migrations/
|
||||
├── 2025_12_04_164542_create_quotes_table.php
|
||||
└── 2025_12_04_133410_create_quote_formula_tables.php
|
||||
```
|
||||
|
||||
### 8.2 프론트엔드 (React)
|
||||
|
||||
```
|
||||
react/src/components/quotes/
|
||||
├── types.ts ← 타입 정의 (LocationItem, BomCalculationResult)
|
||||
├── actions.ts ← API 액션 (calculateBomBulk)
|
||||
├── QuoteFooterBar.tsx ← 하단 버튼바 (견적서보기, 저장, 최종확정)
|
||||
├── FormulaViewModal.tsx ← 수식 보기 모달 (개발용)
|
||||
└── ...
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 9. 검증 체크리스트
|
||||
|
||||
### 9.1 데이터 정합성 검증
|
||||
|
||||
- [ ] quotes.total_amount = subtotal - discount_amount
|
||||
- [ ] quotes.subtotal = material_cost + labor_cost + install_cost
|
||||
- [ ] quote_items의 합계 = quotes의 비용 합계
|
||||
- [ ] calculation_inputs.bomResults의 grand_total = 품목 합계
|
||||
|
||||
### 9.2 상태 전이 검증
|
||||
|
||||
- [ ] pending → draft: 첫 수정 시 자동 전환
|
||||
- [ ] draft → finalized: 확정 버튼 클릭 + total_amount > 0
|
||||
- [ ] finalized → converted: 수주 전환 시 + order_id 설정
|
||||
|
||||
### 9.3 BOM 계산 검증
|
||||
|
||||
- [ ] W1 = W0 + 마진값 (SCREEN: 140, STEEL: 110)
|
||||
- [ ] H1 = H0 + 350
|
||||
- [ ] 면적(M) = (W1 × H1) / 1,000,000
|
||||
- [ ] 중량(K) 계산식 제품타입별 확인
|
||||
- [ ] 수량 수식의 변수 치환 정확성
|
||||
- [ ] 단가 조회 우선순위 준수
|
||||
|
||||
---
|
||||
|
||||
*문서 작성일: 2026-01-29*
|
||||
*작성자: Claude Code*
|
||||
434
plans/api-analysis-report.md
Normal file
434
plans/api-analysis-report.md
Normal file
@@ -0,0 +1,434 @@
|
||||
# SAM API 전체 분석 보고서
|
||||
|
||||
> **작성일**: 2026-01-29
|
||||
> **목적**: api/, mng/, react/ 프로젝트 간 API 중복/통합/미사용 분석 및 관계 정리
|
||||
> **기준 문서**: api/routes/api/v1/*.php, mng/routes/api.php, mng/routes/web.php, react/src/lib/api/*
|
||||
> **상태**: ✅ 분석 완료
|
||||
|
||||
---
|
||||
|
||||
## 📍 분석 결과 요약
|
||||
|
||||
| 항목 | 수치 |
|
||||
|------|------|
|
||||
| **api/ 엔드포인트** | ~710+ |
|
||||
| **mng/ 엔드포인트** | ~300+ |
|
||||
| **React 실제 사용** | ~80+ (api/ 전체의 ~15%) |
|
||||
| **중복 도메인** | 10개 |
|
||||
| **즉시 정리 가능** | 3건 |
|
||||
| **통합 가능 그룹** | 6개 |
|
||||
|
||||
---
|
||||
|
||||
## 1. 개요
|
||||
|
||||
### 1.1 배경
|
||||
|
||||
SAM 프로젝트는 api/(REST API), mng/(관리자 패널), react/(프론트엔드) 3개 프로젝트로 구성되어 있으며, 각 프로젝트가 독립적으로 발전하면서 동일 도메인에 대한 API가 중복 생성되었다. 본 분석은 전체 API를 파악하고 정리 방안을 제시한다.
|
||||
|
||||
### 1.2 분석 범위
|
||||
|
||||
| 프로젝트 | 역할 | 분석 대상 |
|
||||
|---------|------|----------|
|
||||
| **api/** | REST API 서버 | routes/api/v1/*.php (14개 라우트 파일), 컨트롤러 138개 |
|
||||
| **mng/** | 관리자 패널 | routes/api.php, routes/web.php, 컨트롤러 90+개 |
|
||||
| **react/** | 프론트엔드 | src/lib/api/*, src/hooks/*, src/app/api/* |
|
||||
|
||||
---
|
||||
|
||||
## 2. 프로젝트별 API 구조
|
||||
|
||||
### 2.1 API 프로젝트 (api/)
|
||||
|
||||
**라우트 파일**: `api/routes/api/v1/`
|
||||
|
||||
| 도메인 | 라우트 파일 | 엔드포인트 수 | 소비자 |
|
||||
|--------|-----------|:----------:|--------|
|
||||
| 인증 | `auth.php` | 8 | React, MNG |
|
||||
| 사용자 | `users.php` | 25 | React |
|
||||
| 테넌트 | `tenants.php` | 18 | React |
|
||||
| 관리자 | `admin.php` | 22 | React, MNG |
|
||||
| 공통 | `common.php` | 95+ | React, MNG |
|
||||
| HR | `hr.php` | 85+ | React |
|
||||
| 재무 | `finance.php` | 130+ | React |
|
||||
| 영업 | `sales.php` | 85+ | React |
|
||||
| 재고 | `inventory.php` | 65+ | React |
|
||||
| 생산 | `production.php` | 35+ | React |
|
||||
| 설계 | `design.php` | 55+ | React |
|
||||
| 파일 | `files.php` | 15 | React |
|
||||
| 게시판 | `boards.php` | 70+ | React |
|
||||
| 문서 | `documents.php` | 5+ | React |
|
||||
|
||||
### 2.2 MNG 프로젝트 (mng/)
|
||||
|
||||
**API 소비 방식**: 자체 모델로 DB 직접 접근 (api/ REST API를 거치지 않음)
|
||||
|
||||
| 도메인 | 엔드포인트 수 | 비고 |
|
||||
|--------|:----------:|------|
|
||||
| 사용자/역할/권한 | 30+ | api/와 중복 |
|
||||
| 메뉴/글로벌메뉴 | 25+ | api/와 중복 |
|
||||
| 게시판/필드 | 20+ | api/와 중복 |
|
||||
| 카테고리/글로벌 | 15+ | api/와 중복 |
|
||||
| 바로빌 (전체) | 60+ | MNG 전용 (외부 서비스) |
|
||||
| 프로젝트 관리 | 25+ | MNG 전용 |
|
||||
| 견적 공식 | 30+ | MNG 전용 |
|
||||
| 품목 필드 | 25+ | MNG 전용 |
|
||||
| 문서/템플릿 | 12+ | api/와 중복 |
|
||||
| 계좌/자금일정 | 18+ | api/와 중복 |
|
||||
| 기타 (회의록, 신용, 영업, Lab) | 40+ | MNG 전용 |
|
||||
|
||||
### 2.3 React 프론트엔드 (react/)
|
||||
|
||||
**API 호출 방식**: Next.js Proxy (`/api/proxy/*`) → Backend (`/api/v1/*`)
|
||||
|
||||
| 카테고리 | 주요 엔드포인트 | 사용 빈도 |
|
||||
|---------|---------------|:--------:|
|
||||
| 인증 | login, logout, refresh, signup | 높음 |
|
||||
| 품목 CRUD | items, items/{id}, items/bom | 높음 |
|
||||
| 품목기준관리 | item-master/* (pages, sections, fields) | 높음 |
|
||||
| 견적 계산 | quotes/calculate, quotes/calculate/bom | 높음 |
|
||||
| 공통코드 | settings/common/{group} | 높음 |
|
||||
| 대시보드 | card-transactions/dashboard, loans/dashboard | 중간 |
|
||||
| 알림 | today-issues/unread, unread/count | 중간 |
|
||||
| 거래처 | clients, client-groups | 중간 |
|
||||
| 재고 | stocks, work-results | 중간 |
|
||||
| 일괄작업 | bulk-update-account-code | 낮음 |
|
||||
| 내보내기 | attendances/export, salaries/export | 낮음 |
|
||||
|
||||
---
|
||||
|
||||
## 3. 중복 API 분석
|
||||
|
||||
### 3.1 중복 컨트롤러 목록 (api/ vs mng/)
|
||||
|
||||
| # | 도메인 | api/ 컨트롤러 | mng/ 컨트롤러 | 중복 수준 |
|
||||
|---|--------|-------------|-------------|:--------:|
|
||||
| 1 | 사용자 관리 | `Api\V1\Admin\AdminController` | `Api\Admin\UserController` | 🔴 높음 |
|
||||
| 2 | 역할 관리 | `Api\V1\RoleController` | `Api\Admin\RoleController` | 🔴 높음 |
|
||||
| 3 | 메뉴 관리 | `Api\V1\MenuController` | `Api\Admin\MenuController` | 🔴 높음 |
|
||||
| 4 | 카테고리 | `Api\V1\CategoryController` | `Api\Admin\CategoryApiController` | 🔴 높음 |
|
||||
| 5 | 계좌 관리 | `Api\V1\BankAccountController` | `Api\Admin\BankAccountController` | 🔴 높음 |
|
||||
| 6 | 권한 관리 | `Api\V1\PermissionController` | `Api\Admin\PermissionController` | 🟡 중간 |
|
||||
| 7 | 부서 관리 | `Api\V1\DepartmentController` | `Api\Admin\DepartmentController` | 🟡 중간 |
|
||||
| 8 | 게시판 | `Api\V1\BoardController` | `Api\Admin\BoardController` | 🟡 중간 |
|
||||
| 9 | 문서 | `Api\V1\Documents\DocumentController` | `Api\Admin\DocumentApiController` | 🟡 중간 |
|
||||
| 10 | 테넌트 | `Api\V1\TenantController` | `Api\Admin\TenantController` | 🟡 중간 |
|
||||
|
||||
### 3.2 상세 비교
|
||||
|
||||
#### (1) 사용자 관리 🔴
|
||||
|
||||
| 기능 | api/ | mng/ | 차이 |
|
||||
|------|:----:|:----:|------|
|
||||
| 기본 CRUD | ✅ | ✅ | 동일 |
|
||||
| 복구 (restore) | ✅ | ✅ | 동일 |
|
||||
| 비밀번호 초기화 | ✅ | ✅ | 동일 |
|
||||
| 활성화/비활성화 | ✅ (PATCH /status) | ❌ | api/만 |
|
||||
| 역할 부여/해제 | ✅ (POST/DELETE /roles) | ❌ | api/만 |
|
||||
| 영구삭제 | ❌ | ✅ (DELETE /force) | mng/만 (슈퍼관리자) |
|
||||
| 개발용 로그인토큰 | ❌ | ✅ (POST /login-token) | mng/만 |
|
||||
| 모달 데이터 | ❌ | ✅ (GET /modal) | mng/만 |
|
||||
|
||||
#### (2) 역할 관리 🔴
|
||||
|
||||
| 기능 | api/ | mng/ | 차이 |
|
||||
|------|:----:|:----:|------|
|
||||
| 기본 CRUD | ✅ | ✅ | 동일 |
|
||||
| 통계 (stats) | ✅ | ❌ | api/만 |
|
||||
| 활성 목록 (active) | ✅ | ❌ | api/만 |
|
||||
|
||||
#### (3) 메뉴 관리 🔴
|
||||
|
||||
| 기능 | api/ | mng/ | 차이 |
|
||||
|------|:----:|:----:|------|
|
||||
| 기본 CRUD | ✅ | ✅ | 동일 |
|
||||
| 순서변경 (reorder) | ✅ | ✅ | 동일 |
|
||||
| 복구 (restore) | ✅ | ✅ | 동일 |
|
||||
| 활성화 토글 | ✅ (toggle) | ✅ (toggle-active) | 동일 기능 |
|
||||
| 동기화 | ✅ (sync, sync-new, sync-updates) | ❌ | api/만 |
|
||||
| 트리 구조 | ❌ | ✅ (tree) | mng/만 |
|
||||
| 글로벌 복사 | ❌ | ✅ (copy-from-global) | mng/만 |
|
||||
| 일괄 작업 | ❌ | ✅ (bulk-delete/restore/force) | mng/만 |
|
||||
| 숨김 토글 | ❌ | ✅ (toggle-hidden) | mng/만 |
|
||||
| 영구삭제 | ❌ | ✅ (force) | mng/만 (슈퍼관리자) |
|
||||
|
||||
#### (4) 카테고리 🔴
|
||||
|
||||
| 기능 | api/ | mng/ | 차이 |
|
||||
|------|:----:|:----:|------|
|
||||
| 기본 CRUD | ✅ | ✅ | 동일 |
|
||||
| 트리/순서변경/이동 | ✅ | ✅ | 동일 |
|
||||
| 활성화 토글 | ✅ | ✅ | 동일 |
|
||||
| 필드 관리 | ✅ (fields CRUD, bulk-upsert) | ❌ | api/만 |
|
||||
| 템플릿 관리 | ✅ (templates, apply, preview, diff) | ❌ | api/만 |
|
||||
| 로그 조회 | ✅ (logs) | ❌ | api/만 |
|
||||
| 글로벌 관리 | ❌ | ✅ (global-categories) | mng/만 |
|
||||
|
||||
#### (5) 계좌 관리 🔴
|
||||
|
||||
| 기능 | api/ | mng/ | 차이 |
|
||||
|------|:----:|:----:|------|
|
||||
| 기본 CRUD | ✅ | ✅ | 동일 |
|
||||
| 활성화 토글 | ✅ | ✅ | 동일 |
|
||||
| 활성 목록 (active) | ✅ | ❌ | api/만 |
|
||||
| 대표계좌 설정 | ✅ (set-primary) | ❌ | api/만 |
|
||||
| 전체 조회 (all) | ❌ | ✅ | mng/만 |
|
||||
| 요약 (summary) | ❌ | ✅ | mng/만 |
|
||||
| 거래내역 | ❌ | ✅ (transactions) | mng/만 |
|
||||
| 일괄 작업 | ❌ | ✅ (bulk-*) | mng/만 |
|
||||
| 영구삭제/복구 | ❌ | ✅ (force/restore) | mng/만 |
|
||||
|
||||
#### (6) 권한 관리 🟡
|
||||
|
||||
| 기능 | api/ | mng/ | 차이 |
|
||||
|------|:----:|:----:|------|
|
||||
| 권한 매트릭스 조회 | ✅ (dept/role/user menu-matrix) | ❌ | api/만 (특화) |
|
||||
| 기본 CRUD | ❌ | ✅ | mng/만 |
|
||||
|
||||
> **분석**: api/는 매트릭스 조회 전용, mng/는 CRUD 전용으로 기능 분리된 상태. 완전 중복은 아님.
|
||||
|
||||
---
|
||||
|
||||
## 4. 통합 가능 API
|
||||
|
||||
### 4.1 통합 대상 그룹
|
||||
|
||||
| # | 대상 | 현재 상태 | 통합 방안 | 우선순위 |
|
||||
|---|------|----------|----------|:--------:|
|
||||
| 1 | **인증 API** | signup + register 중복 | register 제거 (signup 유지) | 🔴 |
|
||||
| 2 | **사용자 관리** | api/ + mng/ 각각 CRUD | mng/ → api/ 호출로 전환 | 🔴 |
|
||||
| 3 | **역할 관리** | api/ + mng/ 각각 CRUD | api/에 통합, mng/는 호출만 | 🟡 |
|
||||
| 4 | **메뉴 관리** | api/ 동기화 + mng/ 관리 분리 | 관리: mng/, 조회+동기화: api/ | 🟡 |
|
||||
| 5 | **대시보드 데이터** | 개별 엔드포인트 분산 | 통합 대시보드 API 제공 | 🟢 |
|
||||
| 6 | **일괄 업데이트** | withdrawals/deposits/sales 각각 | 공통 bulk-update 패턴 | 🟢 |
|
||||
|
||||
### 4.2 인증 API 중복 상세
|
||||
|
||||
```
|
||||
현재:
|
||||
POST /v1/login → 로그인
|
||||
POST /v1/logout → 로그아웃
|
||||
POST /v1/signup → 회원가입 (1)
|
||||
POST /v1/register → 회원가입 (2) ← 중복!
|
||||
POST /v1/token-login → 토큰 로그인 (MNG→DEV)
|
||||
POST /v1/refresh → 토큰 갱신
|
||||
POST /v1/internal/exchange-token → 내부 서버 토큰 교환
|
||||
GET /v1/debug-apikey → 디버그용 ← 프로덕션 제거 필요
|
||||
|
||||
권장:
|
||||
- register 제거 (signup 유지)
|
||||
- debug-apikey 프로덕션 비활성화
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. 미사용 API
|
||||
|
||||
### 5.1 React에서 호출하지 않는 api/ 도메인
|
||||
|
||||
| 도메인 | 엔드포인트 수 | 미사용 이유 |
|
||||
|--------|:----------:|-----------|
|
||||
| HR 전체 (employees, attendance, leave, approval) | ~80+ | MNG에서 직접 관리 또는 React 미구현 |
|
||||
| 생산 대부분 (processes, work-orders, inspections) | ~35+ | work-results만 사용 |
|
||||
| 설계 전체 (models, versions, bom-templates) | ~55+ | 견적 계산 시 간접 사용만 |
|
||||
| 재무 대부분 (cards, payroll, bad-debts 등) | ~100+ | CEO 대시보드 일부만 사용 |
|
||||
| 사용자 초대 (invitations) | ~5 | React 미구현 |
|
||||
| 알림 설정 (notification-settings) | ~5 | React 미구현 |
|
||||
| 프로필 관리 (profiles) | ~5 | React 미구현 |
|
||||
| 팝업 관리 (popups) | ~5 | React 미구현 |
|
||||
| AI 리포트 (reports/ai) | ~4 | React 미구현 |
|
||||
| 구독/결제 (subscriptions, payments) | ~20+ | React 미구현 |
|
||||
| 현장/시공 (sites, construction) | ~30+ | React 미구현 |
|
||||
| 검사 관리 (inspections) | ~8 | React 미구현 |
|
||||
|
||||
> **참고**: "미사용"은 React 프론트엔드 기준. MNG에서 Blade UI로 직접 사용하거나 향후 구현 예정인 경우 포함.
|
||||
|
||||
### 5.2 완전 미사용 가능성 높은 API
|
||||
|
||||
| 엔드포인트 | 이유 | 조치 권장 |
|
||||
|-----------|------|----------|
|
||||
| `GET /v1/debug-apikey` | 디버그 전용 | 프로덕션 비활성화 |
|
||||
| `POST /v1/register` | signup과 중복 | 제거 |
|
||||
| `GET /v1/welfare/*` | React/MNG 모두 미호출 확인 필요 | 사용 여부 확인 |
|
||||
| `GET /v1/entertainment/*` | React/MNG 모두 미호출 확인 필요 | 사용 여부 확인 |
|
||||
| `GET /v1/calendar/schedules` | React 미호출 | 사용 여부 확인 |
|
||||
| `GET /v1/comprehensive-analysis` | React 미호출 | 사용 여부 확인 |
|
||||
|
||||
### 5.3 MNG 전용 기능 (정상)
|
||||
|
||||
| 기능 | 설명 | 상태 |
|
||||
|------|------|:----:|
|
||||
| 바로빌 (Barobill) | 전자세금계산서, 카드, 홈택스 연동 | ✅ 정상 |
|
||||
| 프로젝트 관리 | 프로젝트, 태스크, 이슈 | ✅ 정상 |
|
||||
| 데일리 로그 | 일일 스크럼 | ✅ 정상 |
|
||||
| 견적 공식 | 견적 계산 공식 관리 | ✅ 정상 |
|
||||
| 회의록 | 녹음, AI 요약 (Google Cloud) | ✅ 정상 |
|
||||
| 신용 평가 | Coocon API 연동 | ✅ 정상 |
|
||||
| 영업 관리 | 매니저, 전망, 기록 | ✅ 정상 |
|
||||
| DevTools | API 탐색기, 흐름 테스터 | ✅ 정상 |
|
||||
| Lab/R&D | AI, 전략 실험 | ✅ 정상 |
|
||||
|
||||
---
|
||||
|
||||
## 6. 프로젝트 간 API 관계도
|
||||
|
||||
### 6.1 시스템 구조
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ 사용자 (브라우저) │
|
||||
│ │
|
||||
│ ┌──────────────┐ ┌──────────────────┐ │
|
||||
│ │ React App │ │ MNG Admin │ │
|
||||
│ │ (dev.sam.kr) │ │ (mng.sam.kr) │ │
|
||||
│ └──────┬───────┘ └──────┬───────────┘ │
|
||||
│ │ │ │
|
||||
│ Next.js Proxy 자체 모델 직접 사용 │
|
||||
│ (/api/proxy/*) + 일부 api/ 호출 │
|
||||
│ │ │ │
|
||||
│ ▼ │ │
|
||||
│ ┌──────────────┐ │ │
|
||||
│ │ API 서버 │◄─────────────────┘ │
|
||||
│ │ (api.sam.kr) │ token-login, │
|
||||
│ │ │ DevTools API 탐색 │
|
||||
│ └──────┬───────┘ │
|
||||
│ │ │
|
||||
│ ▼ │
|
||||
│ ┌──────────────┐ │
|
||||
│ │ Database │◄──── MNG도 동일 DB 직접 접근 │
|
||||
│ │ (MySQL) │ │
|
||||
│ └──────────────┘ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
|
||||
외부 API:
|
||||
┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐
|
||||
│ Google │ │ Coocon │ │ FCM │ │ NTS │
|
||||
│ Cloud │ │ (신용) │ │ (푸시) │ │ (홈택스) │
|
||||
└────┬─────┘ └────┬─────┘ └────┬─────┘ └────┬─────┘
|
||||
└────────────┴────────────┴─────────────┘
|
||||
│
|
||||
MNG에서 호출
|
||||
```
|
||||
|
||||
### 6.2 데이터 흐름
|
||||
|
||||
| 흐름 | 방식 | 설명 |
|
||||
|------|------|------|
|
||||
| React → API | HTTP (Proxy) | 모든 비즈니스 로직 API 호출 |
|
||||
| MNG → DB | 직접 모델 | 관리 기능은 DB 직접 접근 |
|
||||
| MNG → API | HTTP | token-login, DevTools, 일부 동기화 |
|
||||
| MNG → 외부 | HTTP | Barobill, Google Cloud, Coocon, NTS |
|
||||
| API → DB | 직접 모델 | 모든 비즈니스 로직 |
|
||||
|
||||
### 6.3 중복 발생 원인
|
||||
|
||||
```
|
||||
문제: MNG가 api/를 호출하지 않고 DB 직접 접근
|
||||
→ 동일 도메인에 대해 api/, mng/ 각각 독립 컨트롤러 보유
|
||||
→ 비즈니스 로직 분산, 유지보수 부담 증가
|
||||
|
||||
현재:
|
||||
React → api/ (REST API) → DB
|
||||
MNG → DB 직접 ← 여기가 문제
|
||||
|
||||
이상적:
|
||||
React → api/ (REST API) → DB
|
||||
MNG → api/ (REST API) → DB (관리자 전용 엔드포인트 추가)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 7. 개선 권장사항
|
||||
|
||||
### 7.1 즉시 정리 (Quick Wins) 🔴
|
||||
|
||||
| # | 작업 | 영향 | 노력 |
|
||||
|---|------|------|:----:|
|
||||
| 1 | `POST /v1/register` 제거 (signup 유지) | 코드 정리 | 소 |
|
||||
| 2 | `GET /v1/debug-apikey` 프로덕션 비활성화 | 보안 강화 | 소 |
|
||||
| 3 | 미사용 Swagger 문서 정리 | 문서 정확성 | 소 |
|
||||
|
||||
### 7.2 중복 해소 (Medium Term) 🟡
|
||||
|
||||
| # | 작업 | 현재 | 목표 |
|
||||
|---|------|------|------|
|
||||
| 1 | 사용자 관리 통합 | api/ + mng/ 각각 | api/ 마스터, mng/ 관리자 기능만 추가 |
|
||||
| 2 | 역할 관리 통합 | api/ + mng/ 각각 | api/ 단일 소스 |
|
||||
| 3 | 카테고리 통합 | api/ + mng/ 각각 | api/ 마스터, mng/ 글로벌 관리만 유지 |
|
||||
| 4 | 계좌 관리 통합 | api/ + mng/ 각각 | 하나로 통합 |
|
||||
| 5 | 메뉴 관리 정리 | api/ 동기화 + mng/ 관리 | 역할 분리 명확화 |
|
||||
|
||||
### 7.3 아키텍처 개선 (Long Term) 🟢
|
||||
|
||||
| # | 작업 | 설명 |
|
||||
|---|------|------|
|
||||
| 1 | MNG → API 호출 전환 | MNG가 DB 직접 접근 대신 api/ REST API 호출 |
|
||||
| 2 | API Gateway 도입 | 인증/권한/레이트리밋 중앙 관리 |
|
||||
| 3 | 미사용 API 비활성화 | deprecation 헤더 추가 후 단계적 제거 |
|
||||
| 4 | API v2 전환 | 중복 정리 포함한 v2 설계 |
|
||||
|
||||
---
|
||||
|
||||
## 8. 전체 엔드포인트 도메인별 수
|
||||
|
||||
### API 프로젝트
|
||||
|
||||
| 도메인 | 파일 | 수 |
|
||||
|--------|------|:--:|
|
||||
| 인증 | auth.php | 8 |
|
||||
| 사용자 | users.php | 25 |
|
||||
| 테넌트 | tenants.php | 18 |
|
||||
| 관리자 | admin.php | 22 |
|
||||
| 공통 | common.php | 95+ |
|
||||
| HR | hr.php | 85+ |
|
||||
| 재무 | finance.php | 130+ |
|
||||
| 영업 | sales.php | 85+ |
|
||||
| 재고 | inventory.php | 65+ |
|
||||
| 생산 | production.php | 35+ |
|
||||
| 설계 | design.php | 55+ |
|
||||
| 파일 | files.php | 15 |
|
||||
| 게시판 | boards.php | 70+ |
|
||||
| 문서 | documents.php | 5+ |
|
||||
| **합계** | | **~710+** |
|
||||
|
||||
### MNG 프로젝트
|
||||
|
||||
| 그룹 | 수 |
|
||||
|------|:--:|
|
||||
| 사용자/역할/권한 | 30+ |
|
||||
| 메뉴/글로벌메뉴 | 25+ |
|
||||
| 게시판/필드 | 20+ |
|
||||
| 카테고리/글로벌 | 15+ |
|
||||
| 바로빌 | 60+ |
|
||||
| 프로젝트 관리 | 25+ |
|
||||
| 견적 공식 | 30+ |
|
||||
| 품목 필드 | 25+ |
|
||||
| 문서/템플릿 | 12+ |
|
||||
| 계좌/자금일정 | 18+ |
|
||||
| 기타 | 40+ |
|
||||
| **합계** | **~300+** |
|
||||
|
||||
---
|
||||
|
||||
## 9. 참고 문서
|
||||
|
||||
- `docs/standards/api-rules.md` - API 규칙
|
||||
- `docs/architecture/system-overview.md` - 시스템 아키텍처
|
||||
- `docs/specs/database-schema.md` - DB 스키마
|
||||
- `api/routes/api/v1/*.php` - API 라우트 파일
|
||||
- `mng/routes/api.php` - MNG API 라우트
|
||||
- `react/src/lib/api/` - React API 클라이언트
|
||||
|
||||
---
|
||||
|
||||
## 10. 결론
|
||||
|
||||
1. **api/와 mng/의 10개 도메인에서 컨트롤러 중복** 발생 - 동일 DB를 각각 직접 접근하는 구조적 문제
|
||||
2. **React는 api/ 전체의 약 15%만 사용** - 나머지는 MNG 전용이거나 미구현 기능
|
||||
3. **인증 API에 signup/register 중복** 존재 - 즉시 정리 가능
|
||||
4. **장기적으로 MNG → API 호출 전환**이 이상적이나, 현재 아키텍처도 기능적으로 동작
|
||||
5. **Quick Wins(register 제거, debug-apikey 비활성화)부터 시작** 권장
|
||||
|
||||
---
|
||||
|
||||
*이 문서는 /sc:plan 스킬로 생성되었습니다.*
|
||||
@@ -1,4 +1,4 @@
|
||||
ㅅ# 견적관리 URL 구조 마이그레이션 계획
|
||||
# 견적관리 URL 구조 마이그레이션 계획
|
||||
|
||||
> **작성일**: 2026-01-26
|
||||
> **목적**: 견적관리 페이지 URL 구조를 Query 기반(?mode=new)에서 RESTful 경로 기반(/test-new, /test/[id])으로 마이그레이션
|
||||
|
||||
410
plans/tenant-id-compliance-plan.md
Normal file
410
plans/tenant-id-compliance-plan.md
Normal file
@@ -0,0 +1,410 @@
|
||||
# tenant_id 준수 분석 및 분리 방안
|
||||
|
||||
> **작성일**: 2026-01-29
|
||||
> **목적**: API 전체 모델에서 tenant_id 스코핑 미적용 현황을 분석하고, BelongsToTenant trait 적용 방안 수립
|
||||
> **기준 문서**: `docs/specs/database-schema.md`, `docs/architecture/system-overview.md`
|
||||
> **상태**: 🔄 분석 완료 → 실행 대기
|
||||
|
||||
---
|
||||
|
||||
## 📍 현재 진행 상태
|
||||
|
||||
| 항목 | 내용 |
|
||||
|------|------|
|
||||
| **마지막 완료 작업** | 전체 모델 분석 완료 |
|
||||
| **다음 작업** | 사용자 검토 후 Phase 1 실행 |
|
||||
| **진행률** | 0/4 Phase (0%) |
|
||||
| **마지막 업데이트** | 2026-01-29 |
|
||||
|
||||
---
|
||||
|
||||
## 1. 개요
|
||||
|
||||
### 1.1 배경
|
||||
|
||||
SAM API는 멀티테넌트 아키텍처를 사용하며, `BelongsToTenant` trait를 통해 자동 tenant_id 스코핑을 적용합니다. 그러나 일부 모델에서 trait가 누락되어 있어, 테넌트 간 데이터 격리가 보장되지 않을 수 있습니다.
|
||||
|
||||
**분석 결과 요약:**
|
||||
- 전체 모델: 167개
|
||||
- BelongsToTenant 적용: 103개 (61.7%)
|
||||
- 미적용: 63개 (37.7%)
|
||||
- 의도적 글로벌: 18개
|
||||
- 부모 종속 (FK 격리): 13개
|
||||
- **BelongsToTenant 추가 필요: 27개**
|
||||
- **검토 후 결정: 5개**
|
||||
|
||||
### 1.2 기준 원칙
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ 🎯 핵심 원칙 │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ 1. tenant_id 컬럼이 있는 모델은 BelongsToTenant 적용 필수 │
|
||||
│ 2. 부모-자식 관계에서 자식은 부모의 FK로 격리 가능하면 면제 │
|
||||
│ 3. 시스템 전역 데이터(User, Tenant, ApiKey 등)는 글로벌 유지 │
|
||||
│ 4. Boards 영역은 시스템/테넌트 혼용이므로 커스텀 스코프 유지 │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 1.3 변경 승인 정책
|
||||
|
||||
| 분류 | 예시 | 승인 |
|
||||
|------|------|------|
|
||||
| ✅ 즉시 가능 | BelongsToTenant trait 추가 (기존 동작 유지) | 불필요 |
|
||||
| ⚠️ 컨펌 필요 | Boards 영역 스코핑 방식 변경, 쿼리 로직 수정 | **필수** |
|
||||
| 🔴 금지 | 테이블 구조 변경, tenant_id 컬럼 추가/삭제 | 별도 협의 |
|
||||
|
||||
### 1.4 준수 규칙
|
||||
- `docs/specs/database-schema.md` - 테이블 구조
|
||||
- `docs/architecture/system-overview.md` - 시스템 아키텍처
|
||||
- `docs/standards/quality-checklist.md` - 품질 체크리스트
|
||||
|
||||
---
|
||||
|
||||
## 2. 분석 결과 상세
|
||||
|
||||
### 2.1 의도적 글로벌 (BelongsToTenant 불필요) - 18개
|
||||
|
||||
시스템 전역 데이터로, tenant_id 스코핑이 필요하지 않습니다.
|
||||
|
||||
| # | 모델 | 테이블 | tenant_id | 사유 |
|
||||
|---|------|--------|:---------:|------|
|
||||
| 1 | `ApiKey` | api_keys | ❌ | 시스템 API 키 |
|
||||
| 2 | `ApiRequestLog` | api_request_logs | ❌ | 시스템 감시 로그 |
|
||||
| 3 | `AuditLog` | audit_logs | ✅ | 전체 감사 로그 (자체 tenant_id 필터링) |
|
||||
| 4 | `FcmSendLog` | fcm_send_logs | ✅ | 푸시 발송 로그 (수동 필터링) |
|
||||
| 5 | `LoginToken` | login_tokens | ❌ | MNG→API 인증 토큰 |
|
||||
| 6 | `SiteAdmin` | site_admins | ❌ | 시스템 관리자 |
|
||||
| 7 | `Tenant` | tenants | ❌ | 테넌트 마스터 (자기 자신) |
|
||||
| 8 | `Plan` | plans | ❌ | 구독 플랜 정의 |
|
||||
| 9 | `Subscription` | subscriptions | ✅ | 구독 (tenant_id로 연결) |
|
||||
| 10 | `Payment` | payments | ✅ | 결제 (tenant_id로 연결) |
|
||||
| 11 | `User` | users | ❌ | 글로벌 사용자 계정 |
|
||||
| 12 | `UserTenant` | user_tenants | ✅ | 사용자-테넌트 매핑 (피벗) |
|
||||
| 13 | `UserRole` | user_roles | ✅ | 사용자-역할 매핑 (피벗) |
|
||||
| 14 | `GlobalMenu` | global_menus | ❌ | 시스템 전역 메뉴 |
|
||||
| 15 | `Tag` | tags | ❌ | 시스템 공용 태그 |
|
||||
| 16 | `SystemFieldDefinition` | system_field_definitions | ❌ | 시스템 필드 정의 |
|
||||
| 17 | `KdPriceTable` | kd_price_tables | ❌ | 경동 전용 단가표 (레거시) |
|
||||
| 18 | `TenantScope` | - | - | 스코프 정의 클래스 (모델 아님) |
|
||||
|
||||
### 2.2 부모 종속 (FK 격리 - BelongsToTenant 면제) - 13개
|
||||
|
||||
부모 모델에 BelongsToTenant가 적용되어 있고, FK를 통해 자동 격리되는 자식 모델입니다.
|
||||
|
||||
| # | 모델 | 테이블 | 부모 모델 | FK |
|
||||
|---|------|--------|----------|-----|
|
||||
| 1 | `PostCustomFieldValue` | post_custom_field_values | Post | post_id |
|
||||
| 2 | `DocumentData` | document_data | Document | document_id |
|
||||
| 3 | `DocumentApproval` | document_approvals | Document | document_id |
|
||||
| 4 | `DocumentAttachment` | document_attachments | Document | document_id |
|
||||
| 5 | `RoleMenuPermission` | role_menu_permissions | Role | role_id |
|
||||
| 6 | `UserMenuPermission` | user_menu_permissions | - | user_id + menu_id |
|
||||
| 7 | `NotificationSettingGroupItem` | notification_setting_group_items | NotificationSettingGroup | group_id |
|
||||
| 8 | `BillInstallment` | bill_installments | Bill | bill_id |
|
||||
| 9 | `ApprovalStep` | approval_steps | Approval | approval_id |
|
||||
| 10 | `OrderItemComponent` | order_item_components | OrderItem | order_item_id |
|
||||
| 11 | `MaterialInspectionItem` | inspection_items | MaterialInspection | inspection_id |
|
||||
| 12 | `QuoteFormulaItem` | quote_formula_items | QuoteFormula | formula_id |
|
||||
| 13 | `QuoteFormulaRange` | quote_formula_ranges | QuoteFormula | formula_id |
|
||||
|
||||
**주의:** 이 모델들은 직접 쿼리할 때 부모를 통한 접근이 필수입니다. 직접 `::all()` 등으로 접근하면 테넌트 격리가 안됩니다.
|
||||
|
||||
### 2.3 🔴 BelongsToTenant 추가 필요 - 27개
|
||||
|
||||
tenant_id 컬럼이 있지만 BelongsToTenant trait가 없는 모델입니다. 추가해야 합니다.
|
||||
|
||||
| # | 모델 | 테이블 | 영역 | 우선순위 |
|
||||
|---|------|--------|------|:--------:|
|
||||
| **Design 영역 (4개)** | | | | |
|
||||
| 1 | `DesignModel` | models | 설계 | 높음 |
|
||||
| 2 | `ModelVersion` | model_versions | 설계 | 높음 |
|
||||
| 3 | `BomTemplate` | bom_templates | 설계 | 높음 |
|
||||
| 4 | `BomTemplateItem` | bom_template_items | 설계 | 높음 |
|
||||
| **Orders 영역 (2개)** | | | | |
|
||||
| 5 | `OrderHistory` | order_histories | 수주 | 높음 |
|
||||
| 6 | `OrderVersion` | order_versions | 수주 | 높음 |
|
||||
| **Materials 영역 (3개)** | | | | |
|
||||
| 7 | `MaterialReceipt` | material_receipts | 자재 | 높음 |
|
||||
| 8 | `MaterialInspection` | inspections | 자재 | 높음 |
|
||||
| 9 | `MaterialInspectionItem` | inspection_items | 자재 | 중간 |
|
||||
| **Tenants 설정 영역 (7개)** | | | | |
|
||||
| 10 | `TenantOptionGroup` | tenant_option_groups | 설정 | 높음 |
|
||||
| 11 | `TenantOptionValue` | tenant_option_values | 설정 | 높음 |
|
||||
| 12 | `TenantFieldSetting` | tenant_field_settings | 설정 | 높음 |
|
||||
| 13 | `TenantUserProfile` | tenant_user_profiles | 설정 | 중간 |
|
||||
| 14 | `SettingFieldDef` | setting_field_defs | 설정 | 중간 |
|
||||
| 15 | `TenantStatField` | tenant_stat_fields | 설정 | 중간 |
|
||||
| 16 | `BarobillSetting` | barobill_settings | 설정 | 낮음 |
|
||||
| **BadDebts 영역 (2개)** | | | | |
|
||||
| 17 | `BadDebtDocument` | bad_debt_documents | 미수금 | 중간 |
|
||||
| 18 | `BadDebtMemo` | bad_debt_memos | 미수금 | 중간 |
|
||||
| **Permissions 영역 (2개)** | | | | |
|
||||
| 19 | `Permission` | permissions | 권한 | 높음 |
|
||||
| 20 | `PermissionOverride` | permission_overrides | 권한 | 높음 |
|
||||
| **기타 영역 (8개)** | | | | |
|
||||
| 21 | `MainRequest` | main_requests | 요청 | 높음 |
|
||||
| 22 | `MainRequestFlow` | main_request_flows | 요청 | 높음 |
|
||||
| 23 | `MainRequestEstimate` | main_request_estimates | 견적 | 높음 |
|
||||
| 24 | `Schedule` | schedules | 일정 | 중간 |
|
||||
| 25 | `ProcessItem` | process_items | 공정 | 중간 |
|
||||
| 26 | `ProcessClassificationRule` | process_classification_rules | 공정 | 중간 |
|
||||
| 27 | `ItemDetail` | item_details | 품목 | 중간 |
|
||||
|
||||
### 2.4 ⚠️ 검토 후 결정 필요 - 5개
|
||||
|
||||
커스텀 스코핑을 사용하거나, 특수한 비즈니스 로직이 있는 모델입니다.
|
||||
|
||||
| # | 모델 | 현재 방식 | 검토 사항 |
|
||||
|---|------|----------|----------|
|
||||
| 1 | `Board` | `scopeAccessible()` 커스텀 | tenant_id nullable; 시스템 게시판(tenant_id=null)과 테넌트 게시판 혼용 |
|
||||
| 2 | `Post` | 수동 where 조건 | Board의 tenant_id 정책을 따름 |
|
||||
| 3 | `BoardComment` | 수동 where 조건 | Post 종속 |
|
||||
| 4 | `BoardSetting` | 수동 where 조건 | Board 종속 |
|
||||
| 5 | `CompanyRequest` | `created_tenant_id` | tenant_id 대신 created_tenant_id 사용 |
|
||||
|
||||
**Board 영역 결론:** 시스템 게시판(tenant_id=null)을 지원해야 하므로, BelongsToTenant의 글로벌 스코프 대신 현재 커스텀 스코프(`scopeAccessible`) 유지가 적합합니다.
|
||||
|
||||
### 2.5 특수 케이스
|
||||
|
||||
| 모델 | 설명 |
|
||||
|------|------|
|
||||
| `Part` | tenant_id 있지만 BelongsToTenant 미적용. Product와 유사 역할이나 별도 테이블 |
|
||||
| `Lot` / `LotSale` | tenant_id 있지만 미적용. 품질관리 영역 |
|
||||
| `CalculationConfig` | tenant_id 있지만 미적용. 계산 설정 |
|
||||
| `QuoteFormulaMapping` | tenant_id 있지만 미적용. 견적 수식 매핑 |
|
||||
|
||||
---
|
||||
|
||||
## 3. 작업 절차
|
||||
|
||||
### 3.1 단계별 절차
|
||||
|
||||
```
|
||||
Phase 1: 고우선순위 모델 적용 (15개)
|
||||
├── Design 영역: DesignModel, ModelVersion, BomTemplate, BomTemplateItem
|
||||
├── Orders 영역: OrderHistory, OrderVersion
|
||||
├── Materials 영역: MaterialReceipt, MaterialInspection
|
||||
├── Permissions 영역: Permission, PermissionOverride
|
||||
├── MainRequest 영역: MainRequest, MainRequestFlow, MainRequestEstimate
|
||||
├── Tenants 설정: TenantOptionGroup, TenantOptionValue, TenantFieldSetting
|
||||
└── 검증: 기존 서비스 로직에 중복 where 조건 확인 및 정리
|
||||
|
||||
Phase 2: 중간 우선순위 모델 적용 (10개)
|
||||
├── Tenants 설정: TenantUserProfile, SettingFieldDef, TenantStatField
|
||||
├── BadDebts: BadDebtDocument, BadDebtMemo
|
||||
├── 기타: Schedule, ProcessItem, ProcessClassificationRule, ItemDetail
|
||||
├── Materials: MaterialInspectionItem
|
||||
└── 검증: 서비스 로직 정리
|
||||
|
||||
Phase 3: 특수 케이스 처리 (4개)
|
||||
├── Part, Lot, LotSale, CalculationConfig, QuoteFormulaMapping
|
||||
└── 각 모델별 비즈니스 로직 확인 후 적용
|
||||
|
||||
Phase 4: 서비스 레이어 정리
|
||||
├── BelongsToTenant 적용 후 불필요한 수동 where('tenant_id', ...) 제거
|
||||
├── 직접 쿼리하는 부모 종속 모델에 대한 접근 패턴 검토
|
||||
└── 전체 통합 테스트
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. 상세 작업 내용
|
||||
|
||||
### 4.1 Phase 1: 고우선순위 (15개)
|
||||
|
||||
각 모델에 `use BelongsToTenant;` 추가. 작업 패턴:
|
||||
|
||||
```php
|
||||
// Before
|
||||
namespace App\Models\Design;
|
||||
|
||||
use App\Traits\ModelTrait;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class DesignModel extends Model
|
||||
{
|
||||
use ModelTrait;
|
||||
// ...
|
||||
}
|
||||
|
||||
// After
|
||||
namespace App\Models\Design;
|
||||
|
||||
use App\Traits\BelongsToTenant;
|
||||
use App\Traits\ModelTrait;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class DesignModel extends Model
|
||||
{
|
||||
use BelongsToTenant, ModelTrait;
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
**Phase 1 대상 모델:**
|
||||
|
||||
| # | 파일 경로 | 상태 |
|
||||
|---|----------|:----:|
|
||||
| 1.1 | `app/Models/Design/DesignModel.php` | ⏳ |
|
||||
| 1.2 | `app/Models/Design/ModelVersion.php` | ⏳ |
|
||||
| 1.3 | `app/Models/Design/BomTemplate.php` | ⏳ |
|
||||
| 1.4 | `app/Models/Design/BomTemplateItem.php` | ⏳ |
|
||||
| 1.5 | `app/Models/Orders/OrderHistory.php` | ⏳ |
|
||||
| 1.6 | `app/Models/Orders/OrderVersion.php` | ⏳ |
|
||||
| 1.7 | `app/Models/Materials/MaterialReceipt.php` | ⏳ |
|
||||
| 1.8 | `app/Models/Materials/MaterialInspection.php` | ⏳ |
|
||||
| 1.9 | `app/Models/Permissions/Permission.php` | ⏳ |
|
||||
| 1.10 | `app/Models/Permissions/PermissionOverride.php` | ⏳ |
|
||||
| 1.11 | `app/Models/MainRequest.php` | ⏳ |
|
||||
| 1.12 | `app/Models/MainRequestFlow.php` | ⏳ |
|
||||
| 1.13 | `app/Models/Estimates/MainRequestEstimate.php` | ⏳ |
|
||||
| 1.14 | `app/Models/Tenants/TenantOptionGroup.php` | ⏳ |
|
||||
| 1.15 | `app/Models/Tenants/TenantOptionValue.php` | ⏳ |
|
||||
| 1.16 | `app/Models/Tenants/TenantFieldSetting.php` | ⏳ |
|
||||
|
||||
### 4.2 Phase 2: 중간 우선순위 (10개)
|
||||
|
||||
| # | 파일 경로 | 상태 |
|
||||
|---|----------|:----:|
|
||||
| 2.1 | `app/Models/Tenants/TenantUserProfile.php` | ⏳ |
|
||||
| 2.2 | `app/Models/Tenants/SettingFieldDef.php` | ⏳ |
|
||||
| 2.3 | `app/Models/Tenants/TenantStatField.php` | ⏳ |
|
||||
| 2.4 | `app/Models/BadDebts/BadDebtDocument.php` | ⏳ |
|
||||
| 2.5 | `app/Models/BadDebts/BadDebtMemo.php` | ⏳ |
|
||||
| 2.6 | `app/Models/Tenants/Schedule.php` | ⏳ |
|
||||
| 2.7 | `app/Models/ProcessItem.php` | ⏳ |
|
||||
| 2.8 | `app/Models/ProcessClassificationRule.php` | ⏳ |
|
||||
| 2.9 | `app/Models/Items/ItemDetail.php` | ⏳ |
|
||||
| 2.10 | `app/Models/Materials/MaterialInspectionItem.php` | ⏳ |
|
||||
|
||||
### 4.3 Phase 3: 특수 케이스 (5개)
|
||||
|
||||
| # | 파일 경로 | 검토 사항 | 상태 |
|
||||
|---|----------|----------|:----:|
|
||||
| 3.1 | `app/Models/Products/Part.php` | Product와 역할 중복 여부 | ⏳ |
|
||||
| 3.2 | `app/Models/Qualitys/Lot.php` | 품질관리 독립 쿼리 패턴 | ⏳ |
|
||||
| 3.3 | `app/Models/Qualitys/LotSale.php` | Lot 종속 여부 | ⏳ |
|
||||
| 3.4 | `app/Models/Calculation/CalculationConfig.php` | 테넌트별 설정 확인 | ⏳ |
|
||||
| 3.5 | `app/Models/Quote/QuoteFormulaMapping.php` | 공용 vs 테넌트별 | ⏳ |
|
||||
|
||||
### 4.4 Phase 4: 서비스 레이어 정리
|
||||
|
||||
BelongsToTenant 적용 후, 서비스에서 수동으로 `->where('tenant_id', $tenantId)` 하던 코드를 정리합니다.
|
||||
|
||||
**확인 대상 서비스:**
|
||||
- `app/Services/Design/` - DesignModelService, BomTemplateService 등
|
||||
- `app/Services/OrderService.php` - OrderHistory, OrderVersion 관련
|
||||
- `app/Services/Materials/` - MaterialReceiptService 등
|
||||
- `app/Services/MainRequestService.php`
|
||||
- 기타 관련 서비스
|
||||
|
||||
**정리 패턴:**
|
||||
```php
|
||||
// Before (수동 스코핑)
|
||||
$models = DesignModel::where('tenant_id', $this->tenantId())->get();
|
||||
|
||||
// After (BelongsToTenant 자동 스코핑)
|
||||
$models = DesignModel::all(); // 글로벌 스코프가 자동 적용
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. 컨펌 대기 목록
|
||||
|
||||
| # | 항목 | 변경 내용 | 영향 범위 | 상태 |
|
||||
|---|------|----------|----------|------|
|
||||
| 1 | Boards 영역 | 현재 커스텀 스코프 유지 vs BelongsToTenant 전환 | Board, Post, BoardComment, BoardSetting | ⚠️ 확인 필요 |
|
||||
| 2 | Permission 영역 | Spatie Permission 패키지와의 호환성 | Permission, PermissionOverride | ⚠️ 확인 필요 |
|
||||
| 3 | Schedule 모델 | tenant_id nullable - 글로벌 일정 지원 유지 여부 | Schedule | ⚠️ 확인 필요 |
|
||||
| 4 | CompanyRequest | created_tenant_id → tenant_id 통일 여부 | CompanyRequest | ⚠️ 확인 필요 |
|
||||
|
||||
---
|
||||
|
||||
## 6. 변경 이력
|
||||
|
||||
| 날짜 | 항목 | 변경 내용 | 파일 | 승인 |
|
||||
|------|------|----------|------|------|
|
||||
| 2026-01-29 | 분석 | 전체 모델 tenant_id 준수 분석 완료 | 167개 모델 분석 | - |
|
||||
| 2026-01-29 | 문서 | 계획 문서 초안 작성 | docs/plans/tenant-id-compliance-plan.md | - |
|
||||
|
||||
---
|
||||
|
||||
## 7. 참고 문서
|
||||
|
||||
- **DB 스키마**: `docs/specs/database-schema.md`
|
||||
- **시스템 아키텍처**: `docs/architecture/system-overview.md`
|
||||
- **API 규칙**: `docs/standards/api-rules.md`
|
||||
- **품질 체크리스트**: `docs/standards/quality-checklist.md`
|
||||
- **BelongsToTenant trait**: `api/app/Traits/BelongsToTenant.php`
|
||||
- **TenantScope**: `api/app/Models/Scopes/TenantScope.php`
|
||||
|
||||
---
|
||||
|
||||
## 8. 리스크 및 주의사항
|
||||
|
||||
### 8.1 BelongsToTenant 적용 시 부작용
|
||||
|
||||
| 리스크 | 설명 | 대응 |
|
||||
|--------|------|------|
|
||||
| **중복 스코핑** | 서비스에서 이미 `where('tenant_id', ...)` 하고 있으면 중복 | Phase 4에서 수동 where 제거 |
|
||||
| **withoutGlobalScope 필요** | 관리자 기능에서 전체 데이터 조회 시 | `withoutGlobalScopes()` 명시 |
|
||||
| **테스트 실패** | tenant_id 컨텍스트 없는 테스트 | 테스트에서 tenant context 설정 |
|
||||
| **마이그레이션 영향** | seeder/migration에서 직접 insert | tenant context 없이 실행 가능한지 확인 |
|
||||
|
||||
### 8.2 Permission 모델 특수 사항
|
||||
|
||||
Permission은 Spatie Permission 패키지를 확장하므로, BelongsToTenant 적용 시 패키지 내부 쿼리와 충돌 가능성이 있습니다. 적용 전 테스트가 필수입니다.
|
||||
|
||||
### 8.3 Schedule 모델 특수 사항
|
||||
|
||||
Schedule의 tenant_id는 nullable입니다. BelongsToTenant 적용 시 tenant_id=null인 글로벌 일정이 조회되지 않을 수 있습니다. TenantScope에서 nullable 처리가 필요할 수 있습니다.
|
||||
|
||||
---
|
||||
|
||||
## 9. 검증 결과
|
||||
|
||||
> 작업 완료 후 이 섹션에 검증 결과 추가
|
||||
|
||||
### 9.1 성공 기준
|
||||
|
||||
| 기준 | 측정 방법 | 달성 |
|
||||
|------|----------|:----:|
|
||||
| Phase 1 모델 전체 BelongsToTenant 적용 | 코드 확인 | ⏳ |
|
||||
| Phase 2 모델 전체 BelongsToTenant 적용 | 코드 확인 | ⏳ |
|
||||
| 서비스 레이어 중복 where 제거 | grep 검색 | ⏳ |
|
||||
| 기존 API 기능 정상 동작 | Swagger 테스트 | ⏳ |
|
||||
| Pint 포맷팅 통과 | `./vendor/bin/pint --test` | ⏳ |
|
||||
|
||||
---
|
||||
|
||||
## 10. 자기완결성 점검 결과
|
||||
|
||||
### 10.1 체크리스트 검증
|
||||
|
||||
| # | 검증 항목 | 상태 | 비고 |
|
||||
|---|----------|:----:|------|
|
||||
| 1 | 작업 목적이 명확한가? | ✅ | tenant_id 미적용 모델에 BelongsToTenant 추가 |
|
||||
| 2 | 성공 기준이 정의되어 있는가? | ✅ | 섹션 9.1 참조 |
|
||||
| 3 | 작업 범위가 구체적인가? | ✅ | 27개 모델 명시, 5개 검토 대상 분리 |
|
||||
| 4 | 의존성이 명시되어 있는가? | ✅ | Spatie Permission, Boards 커스텀 스코프 |
|
||||
| 5 | 참고 파일 경로가 정확한가? | ✅ | 전체 모델 파일 경로 명시 |
|
||||
| 6 | 단계별 절차가 실행 가능한가? | ✅ | Phase 1~4 구체적 작업 항목 |
|
||||
| 7 | 검증 방법이 명시되어 있는가? | ✅ | 성공 기준 및 테스트 방법 |
|
||||
| 8 | 모호한 표현이 없는가? | ✅ | 구체적 모델명, 파일 경로, 수치 사용 |
|
||||
|
||||
### 10.2 새 세션 시뮬레이션 테스트
|
||||
|
||||
| 질문 | 답변 가능 | 참조 섹션 |
|
||||
|------|:--------:|----------|
|
||||
| Q1. 이 작업의 목적은 무엇인가? | ✅ | 1.1 배경 |
|
||||
| Q2. 어디서부터 시작해야 하는가? | ✅ | 4.1 Phase 1 |
|
||||
| Q3. 어떤 파일을 수정해야 하는가? | ✅ | 2.3 수정 필요 목록 + 4.1~4.3 파일 경로 |
|
||||
| Q4. 작업 완료 확인 방법은? | ✅ | 9.1 성공 기준 |
|
||||
| Q5. 막혔을 때 참고 문서는? | ✅ | 7. 참고 문서 |
|
||||
|
||||
**결과**: 5/5 통과 → ✅ 자기완결성 확보
|
||||
|
||||
---
|
||||
|
||||
*이 문서는 /sc:plan 스킬로 생성되었습니다.*
|
||||
Reference in New Issue
Block a user