# codebridge DB 분리

> **작성일**: 2026-03-07
> **상태**: 로컬/개발 서버 적용 완료, **운영 서버 코드 revert 상태 — DB 선행 작업 필요**
> **최종 수정**: 2026-03-11 — 크로스 DB FK 제약조건 52개 제거 (개발+운영 적용 완료)

---

## 1. 개요

### 1.1 목적

SAM 프로젝트의 DB를 **서비스용**과 **내부 관리용**으로 분리한다.

- **samdb**: React 서비스가 사용하는 테이블 (수주, 견적, 생산, 거래처 등)
- **codebridge**: MNG(관리자 패널)에서만 사용하는 코드브릿지엑스 내부 관리 테이블

### 1.2 핵심 원칙

- codebridge DB에 테이블을 복사한 후, samdb에서 해당 테이블을 **삭제**하여 실질적 분리
- MNG 모델에 `$connection = 'codebridge'`를 설정하여 읽기 대상 DB만 변경
- React/API 서비스에는 **영향 없음**
- 개발 서버: samdb에서 59개 테이블 삭제 완료 (백업: `/home/pro/backup/sam_backup_20260309.sql.gz`)

### 1.3 분리 기준

| 분류 | 대상 DB | 기준 |
|------|---------|------|
| React 서비스 테이블 | samdb (유지) | React 프론트엔드 또는 API에서 사용 |
| MNG 전용 테이블 | codebridge (이동) | MNG에서만 사용, React/API 미참조 |
| 공통 테이블 | samdb (유지) | 양쪽 모두 사용 (users, tenants 등) |
| **API 사용 테이블** | **samdb (유지 필수)** | **API에 모델/서비스/컨트롤러 존재 — 이동 시 데이터 불일치 발생** |

> **경고: API에서 모델/서비스/컨트롤러로 참조하는 테이블을 codebridge로 이동하면, API는 samdb에 쓰고 MNG는 codebridge에서 읽게 되어 데이터 불일치가 발생한다. 절대 이동 금지.**

---

## 2. codebridge 테이블 목록 (59개)

> 2026-03-09 점검: API 프로젝트 전체 코드 조사를 통해 API에서 사용하는 22개 테이블을 제외함. 제외된 테이블은 [3절](#3-api-사용-테이블--samdb-유지-필수-22개) 참조.
> Equipment 하위 테이블 4개 추가 (FK 의존성으로 equipments와 동일 DB 필수).

### Admin (9)

| 테이블 | 설명 |
|--------|------|
| `admin_api_flows` | API 플로우 정의 |
| `admin_api_flow_runs` | API 플로우 실행 이력 |
| `admin_pm_daily_logs` | PM 일일 로그 |
| `admin_pm_daily_log_entries` | PM 일일 로그 항목 |
| `admin_pm_issues` | PM 이슈 |
| `admin_pm_projects` | PM 프로젝트 |
| `admin_pm_tasks` | PM 태스크 |
| `admin_roadmap_milestones` | 로드맵 마일스톤 |
| `admin_roadmap_plans` | 로드맵 계획 |

### DevTools (5)

| 테이블 | 설명 | 비고 |
|--------|------|------|
| `admin_api_bookmarks` | API 북마크 | 기존명 `api_bookmarks` |
| `admin_api_deprecations` | API 지원종료 관리 | 기존명 `api_deprecations` |
| `admin_api_environments` | API 환경 설정 | 기존명 `api_environments` |
| `admin_api_histories` | API 호출 이력 | 기존명 `api_histories` |
| `admin_api_templates` | API 템플릿 | 기존명 `api_templates` |

### Sales (17)

| 테이블 | 설명 |
|--------|------|
| `sales_partners` | 영업 파트너 |
| `sales_managers` | 영업 담당자 |
| `sales_manager_documents` | 영업 담당자 문서 |
| `sales_commissions` | 영업 수당 |
| `sales_commission_details` | 영업 수당 상세 |
| `sales_consultations` | 영업 상담 |
| `sales_contract_products` | 계약 제품 |
| `sales_products` | 영업 제품 |
| `sales_product_categories` | 영업 제품 카테고리 |
| `sales_prospects` | 영업 전망 |
| `sales_prospect_consultations` | 전망 상담 |
| `sales_prospect_products` | 전망 제품 |
| `sales_prospect_scenarios` | 전망 시나리오 |
| `sales_records` | 영업 실적 |
| `sales_scenario_checklists` | 시나리오 체크리스트 |
| `sales_tenant_managements` | 테넌트 영업 관리 |
| `tenant_prospects` | 테넌트 전망 |

### Finance (9)

| 테이블 | 설명 |
|--------|------|
| `condolence_expenses` | 경조사비 |
| `consulting_fees` | 컨설팅비 |
| `corporate_cards` | 법인카드 |
| `corporate_card_prepayments` | 법인카드 선결제 |
| `customer_settlements` | 고객 정산 |
| `daily_fund_memos` | 일일 자금 메모 |
| `daily_fund_transactions` | 일일 자금 거래 |
| `incomes` | 수입 |
| `vat_records` | 부가세 기록 |

### ESign (2)

| 테이블 | 설명 |
|--------|------|
| `esign_field_templates` | 전자서명 필드 템플릿 |
| `esign_field_template_items` | 전자서명 필드 항목 |

> esign_contracts, esign_audit_logs, esign_sign_fields, esign_signers는 API에서 전자계약 기능으로 사용 중 → samdb 유지

### Equipment (6)

| 테이블 | 설명 |
|--------|------|
| `equipments` | 설비 |
| `equipment_processes` | 설비 공정 |
| `equipment_inspections` | 설비 점검 (FK → equipments) |
| `equipment_inspection_details` | 설비 점검 상세 (FK → equipment_inspections) |
| `equipment_inspection_templates` | 설비 점검 템플릿 (FK → equipments) |
| `equipment_repairs` | 설비 수리 (FK → equipments) |

> Equipment 하위 4개 테이블은 `equipments`에 FK 의존하므로 반드시 동일 DB에 있어야 한다.

### HR (1)

| 테이블 | 설명 |
|--------|------|
| `business_income_payments` | 사업소득 지급 |

> income_tax_brackets는 API IncomeTaxBracketSeeder에서 초기 데이터 관리 → samdb 유지

### System (1)

| 테이블 | 설명 |
|--------|------|
| `ai_configs` | AI 설정 |

> ai_pricing_configs, ai_token_usages는 API 모델에서 직접 사용 → samdb 유지

### 기타 (9)

| 테이블 | 설명 | 비고 |
|--------|------|------|
| `biz_cert` | 사업자등록증 | 문서 기존명 `biz_certs` → 실제 테이블명 (단수) |
| `cm_songs` | R&D 곡 관리 | |
| `construction_site_photos` | 시공 현장 사진 | |
| `construction_site_photo_rows` | 시공 사진 행 | |
| `admin_meeting_logs` | 회의 로그 | 문서 기존명 `meeting_logs` → 실제 테이블명 |
| `meeting_minutes` | 회의록 | |
| `meeting_minute_segments` | 회의록 세그먼트 | |
| `interview_knowledges` | 면접 지식 | |
| `sales_records` | 매출 기록 | |

---

## 3. API 사용 테이블 — samdb 유지 필수 (22개)

> **경고: 아래 테이블은 API 프로젝트에서 모델/서비스/컨트롤러/시더로 직접 참조한다. 절대 codebridge로 이동 금지.**
>
> **2026-03-09 점검**: sam/api 프로젝트 전체 코드 (모델, 컨트롤러, 서비스, 라우트, 시더) 조사 완료.

### Barobill (12) — 전체 samdb 유지

| 테이블 | API 사용처 | 사유 |
|--------|-----------|------|
| `barobill_billing_records` | BarobillBillingService | 과금 기록 CRUD |
| `barobill_members` | BarobillUsageService | 회원사 사용량 집계 |
| `barobill_monthly_summaries` | BarobillBillingService | 월별 집계 갱신 |
| `barobill_pricing_policies` | BarobillUsageService | 과금 계산 |
| `bank_sync_statuses` | BankSyncStatus 모델 | 동기화 상태 추적 |
| `bank_transactions` | BankTransactionController | 은행 거래 조회/분개 |
| `bank_transaction_overrides` | BankTransactionOverride 모델 | 거래 재정의 |
| `bank_transaction_splits` | BankTransactionController | 은행 거래 분개 |
| `card_transaction_amount_logs` | CardTransactionAmountLog 모델 | 금액 수정 이력 + FK → card_transactions |
| `card_transaction_hides` | CardTransactionHide 모델 | 거래 숨김 + FK → card_transactions |
| `hometax_invoices` | BarobillUsageService | 세금계산서 사용량 집계 |
| `hometax_invoice_journals` | HometaxInvoiceJournal 모델 | 세금계산서 분개 + FK → hometax_invoices |

> **핵심**: API의 BarobillController, BarobillSettingController, BarobillService, EntertainmentService가 바로빌 테이블을 직접 참조. `barobill_card_transactions` (samdb 유지)와 FK로 연결된 자식 테이블도 분리 불가.

### ESign (4) — API 전자계약 기능

| 테이블 | API 사용처 | 사유 |
|--------|-----------|------|
| `esign_contracts` | EsignContractController, EsignService | 전자계약 CRUD |
| `esign_audit_logs` | EsignService | 감사 추적 기록 |
| `esign_sign_fields` | EsignService | 서명 위치 데이터 |
| `esign_signers` | EsignService | 서명자 정보/인증 |

### Audit (2) — API 전사 감사 시스템

| 테이블 | API 사용처 | 사유 |
|--------|-----------|------|
| `audit_logs` | AuditLog 모델, AuditLogService, AuditRollbackService | 전사 DML 감사 |
| `trigger_audit_logs` | TriggerAuditLog 모델, TriggerAuditLogController, RegenerateAuditTriggers 명령 | DB 트리거 감사 + 파티셔닝 관리 |

### DevTools (1)

| 테이블 | API 사용처 | 사유 |
|--------|-----------|------|
| `api_request_logs` | ApiRequestLog 모델, SystemStatService | API 통계 집계 |

### System (2)

| 테이블 | API 사용처 | 사유 |
|--------|-----------|------|
| `ai_pricing_configs` | AiPricingConfig 모델 | AI 서비스 비용 계산 (캐시 기반) |
| `ai_token_usages` | AiTokenUsage 모델 | 멀티테넌트 AI 토큰 사용량 추적 |

### HR (1)

| 테이블 | API 사용처 | 사유 |
|--------|-----------|------|
| `income_tax_brackets` | IncomeTaxBracketSeeder | 소득세 구간 초기 데이터 관리 |

---

## 4. 적용 현황

### 4.1 환경별 상태

| 환경 | codebridge DB | 테이블 복사 | samdb 삭제 | .env 설정 | MNG 코드 | 상태 |
|------|:---:|:---:|:---:|:---:|:---:|------|
| **로컬 Docker** | O | 100개 | **58개 삭제** | O | O (develop) | ✅ 정상 작동, samdb 265개 |
| **개발 서버** | O | 101개 | **63개 삭제** | O | O (develop) | ✅ 정상 작동, samdb 265개 |
| **운영 서버** | **X** | **X** | **X** | **X** | **revert됨** | ⚠️ DB 선행 작업 후 코드 재배포 필요 |

> **2026-03-09 작업 내역**:
> - API 사용 테이블 22개: codebridge 이동 대상에서 제외 → samdb 유지
> - `finance_*` 17개 + `barobill_companies` 1개: codebridge에 없는 유령 테이블 → samdb에서만 삭제
> - Equipment 하위 4개 테이블: FK 의존성으로 codebridge 이동 대상에 추가 (55→59개)
> - **개발 서버 samdb에서 63개 테이블 DROP 완료** (59개 + DevTools 실제 테이블명 4개 추가분)
> - **로컬 samdb에서 58개 테이블 DROP 완료** → 로컬/개발 265개로 동기화
> - 로컬에 `quality_documents` 등 4개 테이블 구조 동기화 (개발서버에서 복사)
> - 백업: `/home/pro/backup/sam_backup_20260309.sql.gz` (6.3MB)
>
> **테이블명 불일치 발견 (수정 완료)**:
> - `api_bookmarks` → 실제: `admin_api_bookmarks`
> - `meeting_logs` → 실제: `admin_meeting_logs`
> - `biz_certs` → 실제: `biz_cert` (단수형)
> - DevTools 4개: `api_deprecations` → `admin_api_deprecations`, `api_environments` → `admin_api_environments`, `api_histories` → `admin_api_histories`, `api_templates` → `admin_api_templates`
>
> **운영 서버 revert 사유 (2026-03-09)**:
> - MNG main에 codebridge 코드 2건 cherry-pick → Jenkins 배포됨 (빌드 #456, #457)
> - 운영 서버에 codebridge DB가 없는 상태에서 코드 배포 → **59개 모델 사용 페이지 오류 발생 위험**
> - kent가 main에서 revert 2건 push → 운영 서버 정상 복구
> - **교훈: 운영 서버는 반드시 DB 선행 작업(1~2단계) 완료 후 코드 배포(3단계)**

### 4.2 크로스 DB FK 제약조건 제거 (2026-03-11)

> **문제**: codebridge 테이블의 FK 제약조건이 sam DB의 `users`, `tenants` 등을 참조하여 INSERT 실패 발생.
> **증상**: `esign_field_templates` INSERT 시 `SQLSTATE[23000]` FK violation (created_by → users(id))
> **원인**: sam → codebridge로 테이블 이동 시, FK 제약조건은 이동되지 않고 sam의 테이블을 계속 참조.
> **해결**: 마이그레이션으로 codebridge DB의 깨진 FK 52개 일괄 제거.

| 참조 테이블 (sam에만 존재) | FK 수 | 영향 테이블 예시 |
|---|---|---|
| `users` | 27개 | esign_*, admin_*, business_income_payments, sales_* |
| `tenants` | 16개 | account_codes, esign_*, barobill_*, hometax_invoices |
| `departments` | 1개 | admin_pm_issues |
| `processes` | 1개 | equipment_process |
| `prospects` | 1개 | demo_links |
| `clients` | 1개 | expense_accounts |
| `barobill_card_transactions` | 1개 | barobill_card_transaction_amount_logs |
| **합계** | **48개** | |

> **참고**: FK 제거는 데이터 조회(JOIN/SELECT)에 영향 없음. FK는 INSERT/UPDATE 시 참조 무결성 검증만 수행하며, 실제 데이터 조회는 코드 레벨(Eloquent 관계)에서 처리한다.

**마이그레이션 파일**: `api/database/migrations/2026_03_11_100000_drop_broken_foreign_keys_from_codebridge.php`

```php
// 안전한 FK 삭제: 존재 여부 확인 후 제거
private function dropForeignKeySafe(string $connection, string $table, string $foreignKey): void
{
    $exists = DB::connection($connection)->select("
        SELECT 1 FROM information_schema.TABLE_CONSTRAINTS
        WHERE TABLE_SCHEMA = DATABASE()
          AND TABLE_NAME = ? AND CONSTRAINT_NAME = ?
          AND CONSTRAINT_TYPE = 'FOREIGN KEY'
    ", [$table, $foreignKey]);

    if (! empty($exists)) {
        DB::connection($connection)->statement(
            "ALTER TABLE `{$table}` DROP FOREIGN KEY `{$foreignKey}`"
        );
    }
}
```

| 환경 | 적용 상태 |
|------|----------|
| 개발 서버 | ✅ 2026-03-11 마이그레이션 실행 완료 (7초) |
| 운영 서버 | ✅ 2026-03-11 cherry-pick → main push 완료 |

### 4.3 코드 변경 사항

**config/database.php** — `codebridge` connection 추가:

```php
'codebridge' => [
    'driver' => 'mysql',
    'host' => env('CODEBRIDGE_DB_HOST', env('DB_HOST', '127.0.0.1')),
    'port' => env('CODEBRIDGE_DB_PORT', env('DB_PORT', '3306')),
    'database' => env('CODEBRIDGE_DB_DATABASE', 'codebridge'),
    'username' => env('CODEBRIDGE_DB_USERNAME', env('DB_USERNAME')),
    'password' => env('CODEBRIDGE_DB_PASSWORD', env('DB_PASSWORD')),
    // ... (mysql 기본 설정과 동일)
],
```

**.env** — 추가 설정:

```
CODEBRIDGE_DB_DATABASE=codebridge
```

**MNG 모델** — `$connection` 속성 추가 (codebridge 59개만):

```php
class SalesPartner extends Model
{
    protected $connection = 'codebridge';  // 추가
    protected $table = 'sales_partners';
    // ...
}
```

> **주의**: API 사용 테이블 22개에 해당하는 MNG 모델은 `$connection = 'codebridge'`를 설정하지 않는다. 기본 samdb connection을 사용해야 API와 동일한 데이터를 참조한다.

### 4.4 samdb 테이블 삭제 절차 (개발 서버 완료)

> Sales 테이블 그룹은 FK 상호 참조가 있어 `FOREIGN_KEY_CHECKS = 0`으로 일괄 삭제.

```sql
-- FK 체크 비활성화 (Sales, Equipment 등 FK 체인 테이블)
SET FOREIGN_KEY_CHECKS = 0;

-- 59개 테이블 DROP (codebridge에 복제 완료 확인 후)
DROP TABLE IF EXISTS admin_api_flows, admin_api_flow_runs, ...;

SET FOREIGN_KEY_CHECKS = 1;
```

> **롤백**: 백업에서 특정 테이블만 복원 가능
> ```bash
> gunzip < /home/pro/backup/sam_backup_20260309.sql.gz | mysql -u codebridge -p sam
> ```

---

## 5. 운영 서버 적용 절차 (미완료)

> **전제**: 운영 서버 SSH 접근 + DB root 권한 필요
> **현재 상태**: 운영 서버 main 코드는 revert 상태 (codebridge 코드 없음). DB 작업 완료 후 코드 재배포 필요.
> **⚠️ 교훈**: 2026-03-09에 DB 없이 코드만 배포하여 장애 위험 발생 → **반드시 DB 선행 후 코드 배포**

### 순서 (반드시 1 → 2 → 3 → 4 → 5 → 6 순서로)

**1단계: 운영 sam DB 백업**

```bash
# 운영 서버 접속 후
mysqldump -u codebridge -p'[운영PW]' sam --single-transaction > ~/backup/sam_backup_$(date +%Y%m%d).sql
gzip ~/backup/sam_backup_$(date +%Y%m%d).sql
```

**2단계: codebridge DB 생성 + 59개 테이블 복사**

```bash
# DB 생성
mysql -u root -p -e "CREATE DATABASE IF NOT EXISTS codebridge CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"

# DB 계정 권한 부여
mysql -u root -p -e "GRANT ALL PRIVILEGES ON codebridge.* TO 'codebridge'@'localhost'; FLUSH PRIVILEGES;"

# sam에서 59개 테이블 구조+데이터 복사
mysqldump -u codebridge -p sam \
  admin_api_flows admin_api_flow_runs \
  admin_pm_daily_logs admin_pm_daily_log_entries admin_pm_issues admin_pm_projects admin_pm_tasks \
  admin_roadmap_milestones admin_roadmap_plans \
  admin_api_bookmarks admin_api_deprecations admin_api_environments admin_api_histories admin_api_templates \
  sales_partners sales_managers sales_manager_documents sales_commissions sales_commission_details \
  sales_consultations sales_contract_products sales_products sales_product_categories \
  sales_prospects sales_prospect_consultations sales_prospect_products sales_prospect_scenarios \
  sales_records sales_scenario_checklists sales_tenant_managements tenant_prospects \
  condolence_expenses consulting_fees corporate_cards corporate_card_prepayments \
  customer_settlements daily_fund_memos daily_fund_transactions incomes vat_records \
  esign_field_templates esign_field_template_items \
  equipments equipment_process equipment_inspections equipment_inspection_details \
  equipment_inspection_templates equipment_repairs \
  business_income_payments ai_configs \
  biz_cert cm_songs construction_site_photos construction_site_photo_rows \
  admin_meeting_logs meeting_minutes meeting_minute_segments \
  interview_knowledge \
  | mysql -u codebridge -p codebridge
```

**3단계: .env 설정**

```bash
echo 'CODEBRIDGE_DB_DATABASE=codebridge' >> /home/webservice/mng/.env
cd /home/webservice/mng && php artisan config:clear
```

**4단계: API 마이그레이션 실행 (크로스 DB FK 제거)**

> codebridge 테이블이 sam의 users, tenants 등을 참조하는 깨진 FK 52개를 제거한다.
> 이 마이그레이션은 이미 API main 브랜치에 포함되어 있다.

```bash
cd /home/webservice/api
git pull origin main
php artisan migrate --force
```

**5단계: MNG 코드 재배포 (main cherry-pick)**

> develop에 codebridge 코드가 있으므로, revert 커밋 이후 develop의 최신 커밋을 cherry-pick.
> 또는 develop의 해당 커밋을 다시 cherry-pick하여 main에 push.

```bash
# 로컬에서 실행
cd /home/aweso/sam/mng
git checkout main && git pull origin main
git cherry-pick <develop의 codebridge 커밋 해시>
git push origin main
git checkout develop
```

**6단계: 동작 확인 + samdb 테이블 삭제 (선택)**

MNG 관리자 페이지에서 영업관리, 설비, 재무 등 주요 메뉴 동작 확인 후, 문제없으면 sam DB에서 59개 테이블 삭제.

```sql
SET FOREIGN_KEY_CHECKS = 0;
DROP TABLE IF EXISTS
  admin_api_flows, admin_api_flow_runs,
  admin_pm_daily_logs, admin_pm_daily_log_entries, admin_pm_issues, admin_pm_projects, admin_pm_tasks,
  admin_roadmap_milestones, admin_roadmap_plans,
  admin_api_bookmarks, admin_api_deprecations, admin_api_environments, admin_api_histories, admin_api_templates,
  sales_partners, sales_managers, sales_manager_documents, sales_commissions, sales_commission_details,
  sales_consultations, sales_contract_products, sales_products, sales_product_categories,
  sales_prospects, sales_prospect_consultations, sales_prospect_products, sales_prospect_scenarios,
  sales_records, sales_scenario_checklists, sales_tenant_managements, tenant_prospects,
  condolence_expenses, consulting_fees, corporate_cards, corporate_card_prepayments,
  customer_settlements, daily_fund_memos, daily_fund_transactions, incomes, vat_records,
  esign_field_templates, esign_field_template_items,
  equipments, equipment_process, equipment_inspections, equipment_inspection_details,
  equipment_inspection_templates, equipment_repairs,
  business_income_payments, ai_configs,
  biz_cert, cm_songs, construction_site_photos, construction_site_photo_rows,
  admin_meeting_logs, meeting_minutes, meeting_minute_segments,
  interview_knowledge;
SET FOREIGN_KEY_CHECKS = 1;
```

> **⚠️ 핵심 주의사항**:
> - 반드시 **1→2→3→4→5→6** 순서 (DB 먼저, 코드 나중)
> - 4단계(FK 제거) 전에 3단계(.env)까지 완료되어야 함
> - 5단계(MNG 코드 배포) 전에 4단계(API 마이그레이션)까지 완료되어야 함
> - 6단계(samdb 삭제)는 5단계 동작 확인 후 선택적 수행

---

## 6. 아키텍처 다이어그램

```
                    React (사용자)
                         |
                    API 서버 (Laravel)
                         |
                    ┌─────┴─────┐
                    |           |
                  samdb      sam_stat
                (서비스 DB)  (통계 DB)
                    |
                    |  (공통 + API 사용 테이블: users, tenants, barobill_*, esign_*, audit_* 등)
                    |
                MNG (관리자)
                    |
              ┌─────┴─────┐
              |           |
            samdb     codebridge
          (공통 참조)  (MNG 전용 59개)
```

- **React → API → samdb**: 서비스 트래픽 (수주, 견적, 생산, 바로빌, 전자서명 등)
- **MNG → samdb**: 공통 테이블 (users, tenants, menus) + API 사용 테이블 22개 참조
- **MNG → codebridge**: MNG 전용 데이터 (영업관리, 재무, 설비, PM 도구 등)

---

## 관련 문서

- [database/README.md](README.md) — DB 스키마 전체 현황
- [codebridge-db-separation-plan.md](/home/aweso/sam/docs/plans/codebridge-db-separation-plan.md) — 분리 작업 계획서 (plans/)

---

**최종 업데이트**: 2026-03-11 (크로스 DB FK 52개 제거, 적용 절차 6단계로 개정)
