# 마이그레이션 1003: source_menu_objid 추가 ## 📋 개요 메뉴 복사 기능 개선을 위해 `menu_info` 테이블에 `source_menu_objid` 컬럼을 추가합니다. ## 🎯 목적 ### 이전 방식의 문제점 - 메뉴 이름으로만 기존 복사본 판단 - 같은 이름의 다른 메뉴도 삭제될 위험 - 수동으로 만든 메뉴와 복사된 메뉴 구분 불가 ### 개선 후 - 원본 메뉴 ID로 정확히 추적 - 같은 원본에서 복사된 메뉴만 덮어쓰기 - 수동 메뉴와 복사 메뉴 명확히 구분 ## 🗄️ 스키마 변경 ### 추가되는 컬럼 ```sql ALTER TABLE menu_info ADD COLUMN source_menu_objid BIGINT; ``` ### 인덱스 ```sql -- 단일 인덱스 CREATE INDEX idx_menu_info_source_menu_objid ON menu_info(source_menu_objid); -- 복합 인덱스 (회사별 검색 최적화) CREATE INDEX idx_menu_info_source_company ON menu_info(source_menu_objid, company_code); ``` ## 📊 데이터 구조 ### 복사된 메뉴의 source_menu_objid 값 | 메뉴 레벨 | source_menu_objid | 설명 | |-----------|-------------------|------| | 최상위 메뉴 | 원본 메뉴의 objid | 예: 1762407678882 | | 하위 메뉴 | NULL | 최상위 메뉴만 추적 | | 수동 생성 메뉴 | NULL | 복사가 아님 | ### 예시 #### 원본 (COMPANY_7) ``` - 사용자 (objid: 1762407678882) └─ 영업관리 (objid: 1762421877772) └─ 거래처관리 (objid: 1762421920304) ``` #### 복사본 (COMPANY_11) ``` - 사용자 (objid: 1763688215729, source_menu_objid: 1762407678882) ← 추적 └─ 영업관리 (objid: 1763688215739, source_menu_objid: NULL) └─ 거래처관리 (objid: 1763688215743, source_menu_objid: NULL) ``` ## 🚀 실행 방법 ### 로컬 PostgreSQL ```bash psql -U postgres -d ilshin -f db/migrations/1003_add_source_menu_objid_to_menu_info.sql ``` ### Docker 환경 ```bash # 백엔드 컨테이너를 통해 실행 docker exec -i pms-backend-mac bash -c "PGPASSWORD=your_password psql -U postgres -d ilshin" < db/migrations/1003_add_source_menu_objid_to_menu_info.sql ``` ### DBeaver / pgAdmin 1. `db/migrations/1003_add_source_menu_objid_to_menu_info.sql` 파일 열기 2. 전체 스크립트 실행 ## ✅ 확인 방법 ### 1. 컬럼 추가 확인 ```sql SELECT column_name, data_type, is_nullable FROM information_schema.columns WHERE table_name = 'menu_info' AND column_name = 'source_menu_objid'; ``` **예상 결과**: ``` column_name | data_type | is_nullable -------------------|-----------|------------- source_menu_objid | bigint | YES ``` ### 2. 인덱스 생성 확인 ```sql SELECT indexname, indexdef FROM pg_indexes WHERE tablename = 'menu_info' AND indexname LIKE '%source%'; ``` **예상 결과**: ``` indexname | indexdef ---------------------------------|---------------------------------- idx_menu_info_source_menu_objid | CREATE INDEX ... idx_menu_info_source_company | CREATE INDEX ... ``` ### 3. 기존 데이터 확인 ```sql -- 모든 메뉴의 source_menu_objid는 NULL이어야 함 (기존 데이터) SELECT COUNT(*) as total, COUNT(source_menu_objid) as with_source FROM menu_info; ``` **예상 결과**: ``` total | with_source ------|------------- 114 | 0 ``` ## 🔄 롤백 (필요 시) ```sql -- 인덱스 삭제 DROP INDEX IF EXISTS idx_menu_info_source_menu_objid; DROP INDEX IF EXISTS idx_menu_info_source_company; -- 컬럼 삭제 ALTER TABLE menu_info DROP COLUMN IF EXISTS source_menu_objid; ``` ## 📝 주의사항 1. **기존 메뉴는 영향 없음**: 컬럼이 NULL 허용이므로 기존 데이터는 그대로 유지됩니다. 2. **복사 기능만 영향**: 메뉴 복사 시에만 `source_menu_objid`가 설정됩니다. 3. **백엔드 재시작 필요**: 마이그레이션 후 백엔드를 재시작해야 새 로직이 적용됩니다. ## 🧪 테스트 시나리오 ### 1. 첫 복사 (source_menu_objid 설정) ``` 원본: 사용자 (objid: 1762407678882, COMPANY_7) 복사: 사용자 (objid: 1763688215729, COMPANY_11) source_menu_objid: 1762407678882 ✅ ``` ### 2. 재복사 (정확한 덮어쓰기) ``` 복사 전 조회: SELECT objid FROM menu_info WHERE source_menu_objid = 1762407678882 AND company_code = 'COMPANY_11' → 1763688215729 발견 동작: 1. objid=1763688215729의 메뉴 트리 전체 삭제 2. 새로 복사 (source_menu_objid: 1762407678882) ``` ### 3. 다른 메뉴는 영향 없음 ``` 수동 메뉴: 관리자 (objid: 1234567890, COMPANY_11) source_menu_objid: NULL ✅ "사용자" 메뉴 재복사 시: → 관리자 메뉴는 그대로 유지 ✅ ``` ## 📚 관련 파일 - **마이그레이션**: `db/migrations/1003_add_source_menu_objid_to_menu_info.sql` - **백엔드 서비스**: `backend-node/src/services/menuCopyService.ts` - `deleteExistingCopy()`: source_menu_objid로 기존 복사본 찾기 - `copyMenus()`: 복사 시 source_menu_objid 저장