Files
sam-docs/dev/dev_plans/local-to-dev-data-sync-plan.md
권혁성 542ba40fa3 docs: [data-sync] 마스터 데이터 동기화 계획 추가 + 전체 동기화 문서 업데이트
- master-data-sync-plan.md 신규: 31개 마스터 테이블, 양방향(local↔dev↔prod)
- local-to-dev-data-sync-plan.md 업데이트: 35→62개 테이블 확장, FK 의존성 전수 분석
- kd_price_tables 삭제 반영 (미사용 레거시)
2026-03-18 14:53:17 +09:00

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 삭제 (미사용 레거시)