# SAM 프로젝트 개발 공통 정책 > **적용 대상:** 견적, 수주, 생산, 출하, 품질 등 모든 MES 기능 개발 > **최종 업데이트:** 2025-12-19 --- ## 📋 개요 이 문서는 SAM 시스템의 모든 기능 개발에 공통으로 적용되는 정책을 정의합니다. 각 기능별 개발 문서(MASTER_PLAN.md)는 이 문서를 참조합니다. --- ## 🚨 필수 준수 규칙 ### 1. 테이블 정책 ``` ❌ 절대 금지: - 새로운 테이블 임의 생성 (price_new, order_items_v2 등) - 기존 테이블 구조 임의 변경 - mng에서 마이그레이션 실행 ✅ 필수: - 기존 테이블 우선 활용 - 테이블 추가 필요 시 → 사용자 승인 필수 - DB 마이그레이션은 api 프로젝트에서만 실행 ``` ### 2. 기술 스택 | 프로젝트 | 기술 스택 | 주의사항 | |---------|----------|----------| | mng | Laravel 12 + Plain Blade + Tailwind + Livewire + Filament | ❌ Alpine.js 금지 | | api | Laravel 12 REST API + Swagger | Multi-tenant 필수 | | 5130 | PHP + jQuery + 레거시 JS | 분석 대상 (참조용) | | react | Next.js 15 | 프론트엔드 담당자 별도 | ### 3. 코드 컨벤션 (추측 금지 원칙) **🔴 핵심: 모든 코드 요소는 실제 확인 후 사용** ``` ❌ 절대 금지 - 추측/할루시네이션: - 컬럼명 추측 (tenant.name → 실제는 tenant.company_name) - 관계명 추측 (user.roles → 실제는 user.userRoles) - 경로 추측 (App\Models\User → 실제 경로 다를 수 있음) - 메서드명 추측 (getName() → 실제는 getCompanyName()) - 설정값 추측 (config('app.name') → 실제 키 다를 수 있음) - 라우트명 추측 (route('users.index') → 실제 라우트명 확인 필요) - 테이블명 추측 (users → 실제는 sam_users 일 수 있음) - Enum 값 추측 (Status::ACTIVE → 실제 Enum 확인 필요) ``` ``` ✅ 필수 - 실제 확인 후 사용: - 모델 파일 열어서 컬럼명/관계명 확인 - 마이그레이션 파일에서 테이블 구조 확인 - 기존 코드에서 사용 패턴 확인 - config 파일에서 실제 키 확인 - routes 파일에서 라우트명 확인 - 불확실하면 → 반드시 질문 ``` **확인 우선순위:** ``` 1. 모델 파일 (app/Models/*.php) 2. 마이그레이션 (database/migrations/*.php) 3. 기존 컨트롤러/서비스 사용 패턴 4. 라우트 파일 (routes/*.php) 5. 설정 파일 (config/*.php) ``` ### 4. 정책 충돌 해결 ``` 문서 간 정책 충돌 발견 시: 1. 최신 날짜 문서 우선 2. 날짜 동일 → 상위 문서(CLAUDE.md) 우선 3. 모호한 경우 → 반드시 사용자에게 질문 4. 해결된 정책 → PROGRESS.md에 기록 ``` --- ## 🗄️ DB 테이블 정책 ### 테이블 매핑 원칙 ``` ┌─────────────────────────────────────────────────────────────────┐ │ 5130 (레거시) │ │ ├── 모든 테이블 존재 (이미 개발 완료) │ │ └── 분석 대상 (구조/데이터 참조용) │ └─────────────────────────────────────────────────────────────────┘ ↓ 매핑 ┌─────────────────────────────────────────────────────────────────┐ │ SAM (api/mng) │ │ ├── 있는 테이블: 매핑하여 활용 │ │ ├── 이름 다른 테이블: 매핑 테이블 문서화 후 활용 │ │ └── 없는 테이블: 신규 생성 (SAM 설계 정책 적용) │ └─────────────────────────────────────────────────────────────────┘ ``` ### SAM 테이블 설계 정책 (Hybrid EAV) ``` ┌─────────────────────────────────────────────────────────────────┐ │ 컬럼 분류 기준 │ ├─────────────────────────────────────────────────────────────────┤ │ 🔴 필수 컬럼 (일반 컬럼으로 생성) │ │ - 조인에 사용되는 필드 (FK: tenant_id, product_id 등) │ │ - 인덱싱이 필요한 필드 (검색/정렬: status, created_at 등) │ │ - 고빈도 쿼리 필드 (WHERE 조건 자주 사용) │ │ - 유니크 제약 필드 (code, slug 등) │ ├─────────────────────────────────────────────────────────────────┤ │ 🟢 가변 컬럼 (options JSON으로 통합) │ │ - 비즈니스 로직용 데이터 │ │ - 설정/옵션 값 │ │ - 확장 가능성 있는 필드 │ │ - 조인/검색에 사용되지 않는 필드 │ └─────────────────────────────────────────────────────────────────┘ ``` ### 컬럼 타입 정책 ``` ┌─────────────────────────────────────────────────────────────────┐ │ ⚠️ Enum 지양 정책 │ ├─────────────────────────────────────────────────────────────────┤ │ 요구사항은 언제든 변경될 수 있음 → 유연한 타입 사용 │ │ │ │ ❌ 지양: │ │ - DB enum 타입 (ALTER TABLE 필요, 마이그레이션 복잡) │ │ - PHP Enum 하드코딩 (변경 시 코드 수정 필요) │ │ │ │ ✅ 권장: │ │ - string/varchar 타입 + common_codes 테이블 관리 │ │ - is_* 필드: boolean 허용 (true/false 명확한 경우만) │ │ - status 필드: string + common_codes 연동 │ │ - type 필드: string + common_codes 연동 │ │ │ │ 💡 예외 (Enum 허용): │ │ - 절대 변경되지 않는 값 (예: 성별 M/F) │ │ - is_* boolean 필드 (2가지 상태만 존재 확실할 때) │ └─────────────────────────────────────────────────────────────────┘ ``` **예시:** ```php // ❌ 지양: DB Enum $table->enum('status', ['pending', 'approved', 'rejected']); // ❌ 지양: 나중에 상태 추가되면 코드 수정 필요 enum OrderStatus: string { case PENDING = 'pending'; case APPROVED = 'approved'; } // ✅ 권장: string + 코드 테이블 $table->string('status', 20)->default('pending'); // 상태값은 common_codes 테이블에서 관리 // ✅ 허용: is_* boolean (명확한 2가지 상태) $table->boolean('is_active')->default(true); $table->boolean('is_deleted')->default(false); ``` ### 테이블 생성 예시 ```php // ✅ SAM 테이블 설계 정책 적용 예시 Schema::create('example_table', function (Blueprint $table) { $table->id(); // 🔴 필수 컬럼 (조인/인덱싱) $table->foreignId('tenant_id')->constrained()->cascadeOnDelete(); $table->foreignId('related_id')->constrained()->cascadeOnDelete(); $table->string('code')->unique(); $table->string('status')->index(); $table->decimal('amount', 15, 2)->index(); // 🟢 가변 컬럼 (JSON) $table->json('options')->nullable(); // options 예시: { // "custom_field_1": "value", // "settings": {...}, // "metadata": {...} // } $table->timestamps(); $table->softDeletes(); }); ``` ### 테이블 매핑 문서 템플릿 ```markdown ## 테이블 매핑: [기능명] ### 매핑 현황 | 5130 테이블 | SAM 테이블 | 상태 | 비고 | |------------|-----------|------|------| | legacy_table | sam_table | 🆕 신규 생성 | SAM 정책 적용 | | legacy_items | sam_items | ✅ 존재 | 동일 | ### 컬럼 매핑 상세 | 5130 컬럼 | SAM 컬럼 | 타입 | 분류 | 비고 | |----------|---------|------|------|------| | id | id | bigint | 필수 | PK | | company_id | tenant_id | bigint | 필수 | FK, 조인 | | code | code | string | 필수 | 유니크 | | memo | options->notes | json | 가변 | JSON 내부 | ``` ### 테이블 작업 프로세스 ``` Step 1: 5130 테이블 분석 └── 컬럼 목록, 관계, 인덱스 파악 ↓ Step 2: SAM 테이블 확인 ├── 존재 여부 확인 (api/database/migrations/) ├── 이름 다른 경우 매핑 관계 문서화 └── 없는 경우 신규 생성 대상으로 표시 ↓ Step 3: 컬럼 분류 ├── 🔴 필수 컬럼 식별 (조인/인덱싱/검색) └── 🟢 가변 컬럼 → options JSON 통합 ↓ Step 4: 매핑 문서 작성 └── docs/projects/[기능명]/phase-X/table-mapping.md ↓ Step 5: 사용자 승인 ├── 신규 테이블 생성 승인 ├── 컬럼 분류(필수/가변) 승인 └── 매핑 관계 승인 ↓ Step 6: 마이그레이션 생성 (api 프로젝트에서만!) └── api/database/migrations/ ``` ### 기존 테이블 처리 정책 ``` ┌─────────────────────────────────────────────────────────────────┐ │ 기존 SAM 테이블 (options JSON 미적용) │ ├─────────────────────────────────────────────────────────────────┤ │ ⏳ 추후 변환 작업 예정 │ │ │ │ 현재 작업 시: │ │ ├── 기존 테이블 구조 그대로 사용 │ │ ├── 기존 컬럼 활용 (임의 변경 금지) │ │ └── 신규 테이블만 SAM 정책(options JSON) 적용 │ │ │ │ 변환 작업 시 (추후): │ │ ├── 가변 컬럼 → options JSON 마이그레이션 │ │ └── 별도 마이그레이션 계획 수립 │ └─────────────────────────────────────────────────────────────────┘ ``` ### Model options 처리 패턴 ```php // app/Models/ExampleModel.php class ExampleModel extends Model { use BelongsToTenant, SoftDeletes; protected $casts = [ 'options' => 'array', // JSON 자동 변환 ]; // options 헬퍼 메서드 public function getOption(string $key, mixed $default = null): mixed { return data_get($this->options, $key, $default); } public function setOption(string $key, mixed $value): void { $options = $this->options ?? []; data_set($options, $key, $value); $this->options = $options; } } ``` ### DB 작업 체크리스트 ```markdown 신규 테이블 생성 시: - [ ] 5130 원본 테이블 구조 분석 완료 - [ ] SAM 기존 테이블 존재 여부 확인 - [ ] 컬럼 분류 (필수 🔴 / 가변 🟢) 완료 - [ ] 테이블 매핑 문서 작성 - [ ] 사용자 승인 획득 - [ ] api 프로젝트에서 마이그레이션 생성 - [ ] 모델 생성 및 options 캐스팅 설정 기존 테이블 활용 시: - [ ] 현재 테이블 구조 확인 - [ ] 필요 컬럼 존재 여부 확인 - [ ] 없는 컬럼 → 추가 마이그레이션 (승인 필요) - [ ] 이름 다른 컬럼 → 매핑 문서화 ``` --- ## 🔄 Phase 진행 방식 ### Phase 시작 시 ```markdown 1. PROGRESS.md 확인 → 현재 상태 파악 2. 해당 Phase README.md 확인 → 체크리스트 로드 3. 관련 문서 링크 확인 → 참조 문서 읽기 4. MCP Sequential Thinking으로 작업 계획 수립 5. 사용자 승인 후 진행 ``` ### Phase 진행 중 ```markdown 1. SuperClaude 페르소나 적용 - 분석: root-cause-analyst - 설계: backend-architect - 구현: backend-architect, quality-engineer 2. 단계별 문서 업데이트 (승인 불필요) 3. 코드 변경 시 code-workflow 스킬 적용 4. 체크리스트 진행 상황 실시간 반영 ``` ### Phase 완료 시 ```markdown 1. 해당 Phase 문서 최종 정리 2. PROGRESS.md 업데이트 3. Git 태그 생성: [기능명]/phase-X-complete 4. 커밋 (정책에 따라 한글 메시지) 5. 다음 Phase 준비 사항 명시 ``` --- ## ⚠️ 세션 및 커밋 정책 ### 롤백 포인트 설정 ```markdown 각 Phase 완료 시 Git 태그 생성: - [기능명]/phase-1-complete - [기능명]/phase-2-complete - ... ``` ### 세션 중단 대응 ```markdown 세션 중단 시 복구 절차: 1. PROGRESS.md 확인 → 마지막 완료 상태 2. 해당 Phase README.md → 체크리스트 상태 3. 미완료 항목부터 이어서 진행 4. 이전 문서 내용 참조하여 컨텍스트 복구 ``` ### 커밋 정책 ```markdown - 한글 커밋 메시지 - 단계별/스텝별 커밋 - 푸시는 사용자 수동 진행 - 커밋 후 푸시 여부 묻지 않음 ``` --- ## 🔗 참조 문서 목록 ### SAM 전체 문서 ``` docs/system/ # 시스템 현황 docs/reference/ # 레퍼런스 docs/guides/ # 가이드 (이 문서 포함) ``` ### 개별 프로젝트 문서 ``` api/docs/ # API 프로젝트 문서 mng/docs/ # mng 프로젝트 문서 ``` ### 테이블 참조 ``` api/database/migrations/ # 마이그레이션 파일 api/app/Models/ # 모델 정의 ``` --- ## 📝 변경 이력 | 날짜 | 변경 내용 | 작성자 | |------|----------|--------| | 2025-12-19 | 초기 공통 정책 문서 작성 (견적에서 분리) | Claude | --- > **Note:** 각 기능별 개발 문서(MASTER_PLAN.md)는 이 문서를 참조합니다. > 기능별 특화 내용만 각 MASTER_PLAN.md에 작성하세요.