Files
sam-manage/claudedocs/server-local-data-sync.md

5.5 KiB

MNG 서버 ↔ 로컬 데이터 동기화 가이드

적용 범위: MNG 프로젝트(/home/aweso/sam/mng)에만 해당 API 프로젝트는 별도 환경이므로 이 가이드를 적용하지 않습니다. 시더(Seeder)는 사용하지 않습니다. tinker + 임시 PHP 스크립트 방식으로 동기화합니다.

핵심 원리

서버 ↔ 로컬 데이터 이동은 3단계:

1. 원본에서 데이터 추출 (DB → JSON, 파일 → base64)
2. 전송 (SSH/curl 경유)
3. 대상에 저장 (JSON → DB, base64 → 파일)

왜 이 방식인가?

제약 사항 우회 방법
서버 storage는 www-data 소유 → SSH(pro)로 직접 접근 불가 public/에 임시 PHP 스크립트 → curl로 실행 (www-data 권한)
로컬 앱은 Docker 컨테이너 안에 있음 docker exec sam-mng-1 php artisan tinker로 DB 조작
SCP로 storage 디렉토리에 직접 쓰기 불가 base64 인코딩 → PHP Storage::put()으로 저장
시더 사용 금지 (권한 초기화 위험) tinker 또는 임시 PHP 스크립트로 개별 INSERT

MNG 환경 정보

항목
서버 SSH pro@114.203.209.83
서버 MNG 경로 /home/webservice/mng
서버 웹 도메인 https://mng.codebridge-x.com
서버 PHP 실행 nginx + php8.4-fpm (www-data)
로컬 Docker 컨테이너 sam-mng-1
로컬 Storage 경로 /var/www/mng/storage/app/private/
서버 Storage 경로 /home/webservice/mng/storage/app/private/

1. 특정 레코드 동기화 (조건부)

서버 → 로컬

서버(mng.codebridge-x.com)의 [테이블명]에서 [조건]에 해당하는 데이터를
로컬 Docker(sam-mng-1)로 복사해줘.

절차:
1. 서버에서 tinker로 DB 데이터 추출 (JSON)
2. 파일이 있으면 public/에 임시 PHP로 base64 export → curl로 다운로드
3. 로컬 Docker에 파일 복사 (docker cp) 후 tinker로 DB INSERT
4. 임시 파일 모두 삭제

로컬 → 서버

로컬 Docker(sam-mng-1)의 [테이블명]에서 [조건]에 해당하는 데이터를
서버(mng.codebridge-x.com)로 복사해줘.

절차:
1. 로컬 Docker에서 tinker로 DB 데이터 추출 (JSON)
2. 파일이 있으면 docker cp로 호스트로 꺼내기 → base64로 서버 /tmp에 전송
3. 서버 public/에 임시 PHP 작성 → curl로 실행 (base64 디코딩 + Storage::put + DB INSERT)
4. 임시 파일 모두 삭제

2. 테이블 전체 동기화 (로컬 → 서버)

로컬에서 개발/테스트한 데이터를 서버에 그대로 적용할 때 사용합니다. 서버에 이미 데이터가 있으면 중복 방지 전략을 선택해야 합니다.

프롬프트

로컬(sam-mng-1)의 [테이블명] 테이블 데이터를 서버에 동기화해줘.

동기화 방식: [아래에서 선택]
- 서버 비어있음 → 전체 INSERT
- 서버에 기존 데이터 있음 → 로컬 기준으로 덮어쓰기 (서버 데이터 TRUNCATE 후 INSERT)
- 서버에 기존 데이터 있음 → 로컬에만 있는 것만 추가 (중복 제외 INSERT)
- 서버에 기존 데이터 있음 → upsert (있으면 UPDATE, 없으면 INSERT)

관련 테이블: [자식 테이블이 있으면 명시, 예: esign_field_template_items]
Storage 파일: [연관 파일이 있으면 경로 패턴 명시, 예: esign/1/templates/*.pdf]
중복 판단 기준: [어떤 컬럼으로 같은 레코드인지 판단, 예: name, business_number 등]

사용 예시

로컬의 esign_field_templates 테이블 전체를 서버에 동기화해줘.

동기화 방식: 서버 비어있음 → 전체 INSERT
관련 테이블: esign_field_template_items (template_id FK)
Storage 파일: esign/1/templates/*.pdf (file_path 컬럼 참조)
로컬의 clients 테이블 데이터를 서버에 동기화해줘.

동기화 방식: 로컬에만 있는 것만 추가
관련 테이블: 없음
Storage 파일: 없음
중복 판단 기준: client_code
로컬의 menus 테이블을 서버와 동기화해줘.

동기화 방식: upsert (id 기준, 있으면 UPDATE, 없으면 INSERT)
관련 테이블: 없음
Storage 파일: 없음
중복 판단 기준: id
주의: permission_overrides 테이블은 건드리지 말 것

3. 테이블 전체 동기화 (서버 → 로컬)

서버의 운영 데이터를 로컬 개발환경에서 테스트하고 싶을 때 사용합니다.

프롬프트

서버(mng.codebridge-x.com)의 [테이블명] 테이블 데이터를 로컬로 동기화해줘.

동기화 방식: [위와 동일한 옵션]
관련 테이블: [자식 테이블]
Storage 파일: [연관 파일 경로]
중복 판단 기준: [컬럼명]

사용 예시

서버의 tenant_prospects 테이블 전체를 로컬로 동기화해줘.

동기화 방식: 로컬 비어있음 → 전체 INSERT
관련 테이블: 없음
Storage 파일: prospect/ 하위 이미지 (business_card_path, id_card_path, bankbook_path)

주의사항

  • 작업 후 public/의 임시 PHP 스크립트는 반드시 삭제 (보안)
  • ID는 서버/로컬이 다를 수 있으므로 이름/조건 기반으로 매칭
  • FK가 있는 자식 테이블은 부모 먼저 생성 후 새 ID로 자식 INSERT
  • 대량 데이터는 DB::beginTransaction()으로 원자성 보장
  • menus 테이블 동기화 시 permission_overrides는 절대 건드리지 않음
  • TRUNCATE는 신중하게 — 서버 운영 데이터 삭제 전 반드시 확인
  • 동기화 전 서버/로컬 양쪽의 현재 레코드 수를 먼저 확인하고 보고