- master-data-sync-plan.md 신규: 31개 마스터 테이블, 양방향(local↔dev↔prod) - local-to-dev-data-sync-plan.md 업데이트: 35→62개 테이블 확장, FK 의존성 전수 분석 - kd_price_tables 삭제 반영 (미사용 레거시)
13 KiB
13 KiB
로컬 → 개발서버 데이터 동기화 계획
작성일: 2026-03-10 목적: 로컬 DB(tenant_id=287)의 MES 관련 데이터 + 파일을 개발서버로 반복 이관 상태: ⏳ 실행 대기
📍 진행 상태
| 항목 | 내용 |
|---|---|
| 마지막 완료 작업 | 문서 점검 및 단순화 완료 |
| 다음 작업 | 스크립트 작성 + 테스트 |
| 진행률 | 0/2 (0%) |
| 마지막 업데이트 | 2026-03-10 |
1. 개요
1.1 배경
로컬 Docker 환경에서 개발/테스트한 MES 데이터를 개발서버에 주기적으로 동기화한다. 셸 스크립트 1개로 DB + 파일을 한번에 처리한다.
1.2 환경 정보
| 항목 | 로컬 (Docker) | 개발서버 (sam-dev) |
|---|---|---|
| IP | localhost | 114.203.209.83 |
| SSH 사용자 | - | hskwon |
| DB명 | samdb | sam |
| DB 사용자 | samuser / sampass | codebridge |
| DB 포트 (외부) | 3306 | 3306 (localhost only) |
| MySQL 컨테이너 | sam-mysql-1 | - (bare metal) |
| API 경로 | /home/webservice/api/ (없음, Docker) | /home/webservice/api/ |
| 파일 경로 | api/storage/app/tenants/287/ | /home/webservice/api/storage/app/tenants/287/ |
| 테넌트 ID | 287 | 287 |
참고: 개발서버는 releases/shared 구조가 아닌 직접 디렉토리 구조. 출처:
docs/dev/deploys/ops-manual/01-server-overview.md
1.3 실행 방식
# Mac 터미널 (프로젝트 루트)에서 실행
./scripts/data-sync.sh
# 옵션
./scripts/data-sync.sh --db-only # DB만
./scripts/data-sync.sh --files-only # 파일만
./scripts/data-sync.sh --dry-run # 미리보기
- mysqldump: sam-mysql-1 Docker 컨테이너 내부에서 실행
- SSH/rsync: Mac 호스트에서 직접 실행 (로컬에 ssh, rsync 있음)
- 향후 확장: 필요시 mng 웹 UI 추가 가능 (현재는 스크립트로 충분)
2. 대상 테이블 (62개 + 참조 users)
2.1 데이터 현황 (tenant_id=287, 2026-03-17 기준)
| # | 카테고리 | 테이블 | tenant_id | 비고 |
|---|---|---|---|---|
| 기준 정보 | ||||
| 1 | 품목 | items | ✅ direct | |
| 2 | 카테고리 | categories | ✅ direct | |
| 3 | 부서 | departments | ✅ direct | work_orders.team_id 참조 |
| 4 | 거래처 | clients | ✅ direct | quotes/orders/shipments 참조 |
| 5 | 거래처그룹 | client_groups | ✅ direct | clients.client_group_id 참조 |
| 6 | 공통코드 | common_codes | ✅ direct | |
| 7 | 계정코드 | account_codes | ✅ direct | |
| 8 | 카테고리그룹 | category_groups | ✅ direct | |
| 품목 하위 | ||||
| 9 | 품목필드 | item_fields | ✅ direct | |
| 10 | 품목섹션 | item_sections | ✅ direct | |
| 11 | 품목페이지 | item_pages | ✅ direct | |
| 12 | BOM구성 | item_bom_items | ✅ direct | |
| 13 | 단가 | prices | ✅ direct | 견적 단가 조회 필수 |
| 14 | 엔티티관계 | entity_relationships | ✅ direct | |
| 공정관리 | ||||
| 15 | 공정 | processes | ✅ direct | |
| 16 | 공정단계 | process_steps | ❌ FK | process_id → processes |
| 17 | 분류규칙 | process_classification_rules | ❌ FK | process_id → processes |
| 견적 | ||||
| 18 | 견적 | quotes | ✅ direct | |
| 19 | 견적품목 | quote_items | ✅ direct | |
| 20 | 견적수정 | quote_revisions | ✅ direct | |
| 수주 | ||||
| 21 | 수주 | orders | ✅ direct | |
| 22 | 수주품목 | order_items | ✅ direct | |
| 23 | 수주노드 | order_nodes | ✅ direct | 자체참조 (parent_id) |
| 24 | 수주이력 | order_histories | ✅ direct | |
| 25 | 수주품목구성 | order_item_components | ✅ direct | |
| 생산/작업지시 | ||||
| 26 | 작업지시 | work_orders | ✅ direct | |
| 27 | 작업품목 | work_order_items | ❌ FK | work_order_id → work_orders |
| 28 | 단계진행 | work_order_step_progress | ✅ direct | |
| 29 | 담당자 | work_order_assignees | ✅ direct | |
| 30 | 원자재투입 | work_order_material_inputs | ✅ direct | |
| 31 | 이슈 | work_order_issues | ❌ FK | work_order_id → work_orders |
| 32 | 벤딩상세 | work_order_bending_details | ❌ FK | work_order_id → work_orders |
| 33 | 작업실적 | work_results | ✅ direct | |
| 34 | 작업설정 | work_settings | ✅ direct | |
| 출하 | ||||
| 35 | 출하 | shipments | ✅ direct | |
| 36 | 출하품목 | shipment_items | ❌ FK | shipment_id → shipments |
| 37 | 배차 | shipment_vehicle_dispatches | ✅ direct | |
| 재고 | ||||
| 38 | 재고현황 | stocks | ✅ direct | |
| 39 | LOT | stock_lots | ✅ direct | |
| 40 | 입고 | receivings | ✅ direct | |
| 41 | 거래이력 | stock_transactions | ✅ direct | |
| 품질 | ||||
| 42 | 검사 | inspections | ✅ direct | IQC/PQC/FQC |
| 43 | 품질관리서 | quality_documents | ✅ direct | |
| 44 | 품질-수주연결 | quality_document_orders | ❌ FK | quality_document_id |
| 45 | 품질-현장 | quality_document_locations | ❌ FK | quality_document_id |
| 46 | 성능리포트 | performance_reports | ❌ FK | quality_document_id |
| 47 | 심사체크리스트 | audit_checklists | ✅ direct | |
| 48 | 심사카테고리 | audit_checklist_categories | ✅ direct | |
| 49 | 심사항목 | audit_checklist_items | ✅ direct | |
| 50 | 심사표준문서 | audit_standard_documents | ✅ direct | |
| 51 | 체크리스트템플릿 | checklist_templates | ✅ direct | |
| 넘버링 | ||||
| 52 | 넘버링규칙 | numbering_rules | ✅ direct | |
| 53 | 넘버링시퀀스 | numbering_sequences | ✅ direct | |
| 파일 | ||||
| 54 | 파일 | files | ✅ direct | |
| 55 | 폴더 | folders | ✅ direct | |
| 문서 | ||||
| 56 | 문서 | documents | ✅ direct | |
| 57 | 문서템플릿 | document_templates | ✅ direct | |
| 58 | 문서데이터 | document_data | ✅ direct | |
| 59 | 문서승인 | document_approvals | ✅ direct | |
| 60 | 문서첨부 | document_attachments | ✅ direct | |
| 매출 | ||||
| 61 | 매출 | sales | ✅ direct | |
| 참조 (REPLACE INTO) | ||||
| 62 | 사용자 | users | ❌ 참조 | user_tenants 기준, DELETE 안 함 |
| 합계 | 62개 | direct 52 + FK 9 + 참조 1 |
2.2 파일 저장소
| 항목 | 값 |
|---|---|
| 로컬 경로 | api/storage/app/tenants/287/ |
| 개발서버 경로 | /home/webservice/api/storage/app/tenants/287/ |
| 파일 수 | 47개 |
| 총 크기 | 8.9MB |
| 하위 구조 | items/, temp/, logo_*.jpeg |
2.3 참조 users 동기화
user_tenants에서tenant_id=287인 user_id를 수집- 해당 users만
REPLACE INTO로 동기화 (DELETE 안 함 — 다른 테넌트 영향 방지) - 대상: 거의 모든 테이블의
created_by,updated_by,assignee_id,inspector_id등
2.4 제외 대상
| 테이블 | 제외 사유 |
|---|---|
| tenants | 환경별 독립 관리 |
| user_tenants, tenant_user_profiles | 개발서버에서 별도 설정 |
| audit_logs | 감사 로그는 환경별 독립 |
| file_share_links, file_deletion_logs | 환경별 독립 |
| storage_usage_history | 모니터링 환경별 독립 |
| schedules, equipments 등 | 현재 데이터 0건 (향후 데이터 생기면 추가) |
| kd_price_tables | 삭제됨 (EstimatePriceService가 items+prices로 대체) |
3. 스크립트 설계
3.1 파일 위치
scripts/data-sync.sh # 메인 스크립트 (이것만 실행하면 됨)
3.2 실행 흐름
1. 환경 검증 (SSH 접속, Docker 컨테이너 확인)
2. 로컬 DB dump (Docker 컨테이너 내부에서 mysqldump)
3. 개발서버 해당 테넌트 DELETE (SSH → mysql)
4. dump 파일 전송 + import (scp → SSH mysql)
5. 파일 동기화 (rsync)
6. 검증 (건수 비교)
7. 임시 파일 정리
3.3 핵심 로직
DB dump (sam-mysql-1 컨테이너 내부)
# tenant_id 있는 테이블 (25개)
docker exec sam-mysql-1 mysqldump -u samuser -psampass \
--no-create-info --complete-insert --skip-triggers \
--where="tenant_id=287" \
samdb items quotes orders ... > /tmp/sam-sync/direct_tables.sql
# tenant_id 없는 테이블 (10개) — FK 경유
# 예: work_order_items는 work_orders에서 ID 조회 후 IN 조건
docker exec sam-mysql-1 bash -c "
WO_IDS=\$(mysql -u samuser -psampass -N -e \"SELECT GROUP_CONCAT(id) FROM work_orders WHERE tenant_id=287\" samdb)
mysqldump -u samuser -psampass --no-create-info --complete-insert --skip-triggers \
--where=\"work_order_id IN (\$WO_IDS)\" samdb work_order_items
" >> /tmp/sam-sync/fk_tables.sql
개발서버 DELETE (SSH)
ssh hskwon@114.203.209.83 "mysql -u codebridge -p'...' sam" << 'SQL'
SET FOREIGN_KEY_CHECKS = 0;
-- FK 경유 테이블 (부모 JOIN 삭제)
DELETE t FROM work_order_items t JOIN work_orders p ON t.work_order_id=p.id WHERE p.tenant_id=287;
DELETE t FROM work_order_bending_details t JOIN work_orders p ON t.work_order_id=p.id WHERE p.tenant_id=287;
DELETE t FROM work_order_issues t JOIN work_orders p ON t.work_order_id=p.id WHERE p.tenant_id=287;
DELETE t FROM shipment_items t JOIN shipments p ON t.shipment_id=p.id WHERE p.tenant_id=287;
DELETE t FROM process_steps t JOIN processes p ON t.process_id=p.id WHERE p.tenant_id=287;
DELETE t FROM process_classification_rules t JOIN processes p ON t.process_id=p.id WHERE p.tenant_id=287;
DELETE t FROM quality_document_orders t JOIN quality_documents p ON t.quality_document_id=p.id WHERE p.tenant_id=287;
DELETE t FROM quality_document_locations t JOIN quality_documents p ON t.quality_document_id=p.id WHERE p.tenant_id=287;
DELETE t FROM performance_reports t JOIN quality_documents p ON t.quality_document_id=p.id WHERE p.tenant_id=287;
-- direct 테이블 (tenant_id 직접)
DELETE FROM work_order_material_inputs WHERE tenant_id=287;
DELETE FROM work_order_step_progress WHERE tenant_id=287;
DELETE FROM work_order_assignees WHERE tenant_id=287;
DELETE FROM shipment_vehicle_dispatches WHERE tenant_id=287;
DELETE FROM quote_items WHERE tenant_id=287;
DELETE FROM quote_revisions WHERE tenant_id=287;
DELETE FROM order_items WHERE tenant_id=287;
DELETE FROM order_nodes WHERE tenant_id=287;
DELETE FROM stock_lots WHERE tenant_id=287;
DELETE FROM stock_transactions WHERE tenant_id=287;
DELETE FROM numbering_sequences WHERE tenant_id=287;
DELETE FROM files WHERE tenant_id=287;
DELETE FROM work_orders WHERE tenant_id=287;
DELETE FROM shipments WHERE tenant_id=287;
DELETE FROM inspections WHERE tenant_id=287;
DELETE FROM quality_documents WHERE tenant_id=287;
DELETE FROM quotes WHERE tenant_id=287;
DELETE FROM receivings WHERE tenant_id=287;
DELETE FROM sales WHERE tenant_id=287;
DELETE FROM orders WHERE tenant_id=287;
DELETE FROM stocks WHERE tenant_id=287;
DELETE FROM processes WHERE tenant_id=287;
DELETE FROM numbering_rules WHERE tenant_id=287;
DELETE FROM folders WHERE tenant_id=287;
DELETE FROM items WHERE tenant_id=287;
DELETE FROM categories WHERE tenant_id=287;
SET FOREIGN_KEY_CHECKS = 1;
SQL
파일 동기화
rsync -avz --delete \
api/storage/app/tenants/287/ \
hskwon@114.203.209.83:/home/webservice/api/storage/app/tenants/287/
# 권한 복구
ssh hskwon@114.203.209.83 \
"sudo chown -R www-data:develop /home/webservice/api/storage/app/tenants/287/"
4. 주의사항
4.1 SoftDeletes 처리
대상 62개 중 다수 테이블에 SoftDeletes 적용 (Item, Order, WorkOrder, Quote 등).
- dump:
--where="tenant_id=287"은 soft deleted 포함 → 올바름 (상태 보존) - DELETE: SQL DELETE는 deleted_at과 무관하게 모두 삭제 → 올바름
- 결과: 로컬의 soft deleted 데이터도 그대로 개발서버에 반영됨
4.2 안전장치
- FOREIGN_KEY_CHECKS = 0: DELETE/INSERT 시 FK 제약 임시 해제
- tenant_id 필터: 모든 DELETE에
WHERE tenant_id = 287→ 다른 테넌트 보호 - complete-insert: ID 값 포함 dump → auto_increment 충돌 방지
- order_nodes 자체참조: FK_CHECKS=0이므로 삽입 순서 무관
- users REPLACE INTO: DELETE 안 함 → 다른 테넌트의 사용자 데이터 보호
4.3 반복 실행 시 주의
- 삭제 → 삽입: 개발서버에서 직접 추가한 287 데이터는 사라짐
- 동기화 전 개발서버 보존 필요시 별도 백업
- 개발서버 DB 비밀번호는 스크립트 내 변수로 관리 (git 제외)
5. 향후 확장
필요시 다음을 추가 가능:
- mng 웹 UI: Artisan 커맨드 + Blade 화면 (Docker에 ssh/mysqldump 설치 필요)
- 대상 테이블 추가: schedules, equipments 등 (데이터 생기면)
- 다중 테넌트: 287 외 다른 테넌트도 동기화
- 자동 실행: cron으로 주기적 동기화
변경 로그
| 날짜 | 작업 | 비고 |
|---|---|---|
| 2026-03-10 | 최초 작성 | 대상 35개 테이블, 47개 파일 |
| 2026-03-10 | 단순화 | Artisan+웹UI → 셸 스크립트 1개. IP 수정 (211.117.60.189→114.203.209.83). numbering_sequences FK 오류 수정. SoftDeletes 처리 명시. 제외 테이블 보완 |
| 2026-03-17 | 대폭 확장 | 35개→62개 테이블. 소스 코드 belongsTo 기준 FK 의존성 전수 분석. departments, clients, client_groups, prices, item_, order_histories, audit_, common_codes, account_codes 등 21개 추가. users 참조 동기화 (REPLACE INTO). kd_price_tables 삭제 (미사용 레거시) |