---
title: 시스템 아키텍처 및 데이터 구조 설계
---

# GLOBEAU 뷰티 플랫폼 - 시스템 아키텍처 및 데이터 구조 설계
(GLOBEAU System Architecture & Data Structure Design)

---

## 문서 제어 및 개정 이력 (Document Control & Revision History)

### 기본 제어 정보
| 항목 | 내용 |
|---|---|
| **문서명** | GLOBEAU 플랫폼 시스템 아키텍처 및 데이터 구조 설계 가이드 |
| **현재 버전** | v1.5.0 |
| **최종 개정일** | 2026-10-17 |
| **작성/관리자** | 본사 시스템개발팀 |
| **적용 시스템** | GLOBEAU 플랫폼 전체 인프라, 사용자 웹(/), 본사 관리자(/admin), 뷰티샵 백오피스(/shop-admin), 자체 문서 센터(/docs) |
| **문서 목적** | 플랫폼 전체 인프라 환경, 핵심 엔티티 조감표 및 관계(ERD) 흐름, 도메인별 진행 단계 및 상태값 흐름, 뷰티샵 등록 3대 경로, 중앙 집중형 미디어 자산 관리(DAM) 원리, 알림 발송 4단계 파이프라인, 마크다운 문서 뷰어 서브시스템의 총괄 설계 표준 수립 |
| **문서 상태** | 개발 및 운영 공식 표준 (Production Standard) |

### 개정 및 변경 이력
| 버전 | 개정일자 | 구분 | 주요 변경 내역 | 작업자 |
|:---:|:---:|:---:|---|:---:|
| **v1.5.0** | 2026-10-17 | 구조개편 | • 단일 진실 공급원(SSOT) 확립을 위해 중복된 세부 컬럼 명세표를 개별 도메인 문서로 위임<br>• 플랫폼 전체를 한눈에 조망할 수 있는 **'핵심 엔티티 조감표 및 관계 흐름'** 중심으로 1장 전면 경량화<br>• 타이틀 및 영문 부제를 '시스템 아키텍처 및 데이터 구조 설계'로 표준화 | 개발팀 |
| **v1.4.1** | 2026-10-17 | 용어순화 | • 번역투 표현인 '생애주기(Lifecycle)'를 직관적인 '진행 단계 및 상태값 흐름'으로 전면 수정<br>• '전사' 표현을 '플랫폼 전체 / 시스템 전체'로 순화 | 개발팀 |
| **v1.4.0** | 2026-10-17 | 기능확장 | • 뷰티샵 등록 3대 경로(자율신청/계정선발급/직권등록) 및 본사 직영점 1인 다매장 세션 반영<br>• 중앙 집중형 미디어 라이브러리(DAM) 4대 스키마 편입 및 SHA-256 디듀플리케이션 표준화 | 개발팀 |
| **v1.3.0** | 2026-10-16 | 기능확장 | • 알림 템플릿 관리 4단계 발송 체계 및 `notification_logs` 묶음 추적(`batch_id`) 아키텍처 반영<br>• 파일 기반 마크다운 기술 문서 뷰어 서브시스템 전사 표준 편입 | 개발팀 |

---

## 1. 시스템 환경 및 기술 스택 (System Environment & Tech Stack)

- **Server OS:** Ubuntu 22.04 LTS
- **Web Server:** Apache2
- **Backend Framework:** Laravel 13 (PHP 8.4)
- **Database:** MariaDB 10.6+
- **Background Daemon:** Systemd Queue Worker (`laravel-queue.service`, PHP 8.4 CLI)
- **UI/CSS Framework:** Bootstrap 5, FontAwesome 6.4.0, `public/css/admin_custom.css` (브랜드 모카 테마: `#b18977`, 고정 둥글기: `6px`)
- **Authentication & Permission:** Laravel Breeze, Socialite (Kakao, Naver, Google SNS 로그인), Spatie Laravel-Permission
- **Core Subsystems:**
  * 중앙 집중형 미디어 자산 관리(DAM) 서브시스템 (SHA-256 중복 방지, 가상 폴더 N:M 피벗, M:N 슬롯 다형성, Intervention Image v3, AVIF/WebP 비동기 최적화 큐)
  * 다계층 카테고리 연동 시스템 (Tree Picker)
  * Daum 우편번호 서비스 + Kakao Local Geocoder (LBS 위치 좌표 자동 산출 엔진)
  * Cafe24 SMS / LMS 게이트웨이 연동 및 NotificationTemplate 기반 비동기 알림 엔진 (`notification_logs` 단일 사건 `batch_id` 관제)
  * 파일 기반 자체 기술 문서 센터 뷰어 서브시스템 (`marked.js`, `highlight.js`, `mermaid.js`, Custom Lightbox, Floating Quick Nav)

---

## 2. 플랫폼 핵심 데이터베이스 엔티티 조감표 (Database Entity Overview)

GLOBEAU 플랫폼은 데이터의 중복 관리를 배제하고 단일 진실 공급원(SSOT)을 유지하기 위해, **본 1장에서는 전체 테이블 목록과 엔티티 간 관계를 조망**하고 **세부 58개/43개 컬럼 명세표는 개별 도메인 전용 매뉴얼에서 상세히 관리**합니다.

| 도메인 | 물리 테이블명 | 논리 테이블명 | 주요 역할 및 핵심 제약조건 | 상세 명세 문서 |
|---|---|---|---|---|
| **회원/인증** | `users` | 회원 마스터 | 플랫폼 통합 계정 정보, 소셜 분기 비밀번호, 휴대폰 인증 플래그 | 본 문서 (제3장) |
| | `social_accounts` | 소셜 연동 계정 | 카카오·네이버·구글 OAuth 고유 ID 매핑 (`provider, provider_id` Unique) | 본 문서 (제3장) |
| **뷰티샵** | `shops` | 뷰티샵 매장 마스터 | 매장 기본 정보, LBS 위경도 좌표, 영업시간 및 휴무일 JSON, 정산 계좌 (총 58개 컬럼) | `02_shop_guide/01_shop_apply.md` |
| **미디어(DAM)**| `images` | 중앙 미디어 마스터 | 물리 파일 메타데이터, 다중 포맷 경로(WebP/AVIF/Thumb), SHA-256 해시, 보호 잠금(🔒) | `05_dam_guide/01_media_library.md` |
| | `imageables` | 다형성 슬롯 피벗 | Shop, Program 등과 이미지 간 슬롯(`type`: logo, banner 등) 매핑 피벗 | `05_dam_guide/01_media_library.md` |
| | `image_folders` | 가상 폴더 마스터 | 미디어 보관함 내 계층형(Parent-Child) 디렉터리 분류 트리 | `05_dam_guide/01_media_library.md` |
| | `image_folder_pivot` | 이미지-폴더 피벗 | 가상 폴더와 이미지 간 N:M 매핑 피벗 (폴더 삭제 시 원본 이미지 안전 보존) | `05_dam_guide/01_media_library.md` |
| **시술상품** | `programs` | 시술 프로그램 마스터 | 시술 상품 정보, 3대 실행방식(`single`, `package_*`), 소요시간, 소비자가 (총 43개 컬럼) | `03_program_guide/01_program.md` |
| | `program_bundles` | 패키지 번들 구성 피벗 | 패키지(부모)와 단위 시술(자식) 간 수량 매핑 피벗 | `03_program_guide/01_program.md` |
| | `shop_program` | 매장별 배정 피벗 | 최고관리자 배포 프로그램의 매장별 판매 활성화(`is_active`) 및 노쇼 규약 통제 피벗 | `03_program_guide/02_sales.md` |
| **주문/결제** | `orders` | 주문 마스터 | 실결제 금액, 결제 수단(카드/무통장), 입금 기한, PG사 승인 키 (총 32개 컬럼) | `04_order_guide/01_order.md` |
| | `order_items` | 주문 상품 상세 | 구매 당시 상품명 및 단가 스냅샷 보존 다형성 상세 (총 15개 컬럼) | `04_order_guide/01_order.md` |
| | `order_item_options` | 주문 옵션 상세 | 선택된 추가 옵션명 및 옵션 추가금액 스냅샷 | `04_order_guide/01_order.md` |
| **디지털티켓** | `user_tickets` | 디지털 티켓 마스터 | 16자리 고유 `ticket_code` 기반 모바일 티켓 마스터 및 전체 유효 만료일 관리 | `04_order_guide/02_ticket.md` |
| | `user_ticket_items`| 회차 아이템 슬롯 | 실제 방문 예약 시 1회씩 차감되는 단위 프로그램 회차 슬롯 (`remaining_count`) | `04_order_guide/02_ticket.md` |
| **방문예약** | `reservations` | 방문 예약 마스터 | 희망 방문 일시, 예약 슬롯, 뷰티샵 매장 연결 및 현장 QR 차감 이력 | `04_order_guide/03_reservation.md` |
| **알림/관제** | `notification_templates` | 알림 템플릿 마스터 | 카테고리별 알림 문구, 수신 대상, 치환 변수 템플릿 (총 14개 컬럼) | `04_notification/01_logs.md` |
| | `notification_logs` | 통합 발송 관제 로그 | 단일 사건(`batch_id`: M포함 12자리) 기준 다채널 발송 묶음 추적 로그 (총 21개 컬럼) | `04_notification/01_logs.md` |
| | `settings` | 전역 환경 설정 | 동적 관리자 알림 수신 번호 목록 JSON 및 전역 비즈니스 상수 저장소 | `04_notification/01_logs.md` |

---

## 3. 핵심 엔티티 간 연관 관계도 (Entity Relationship Flow)

플랫폼의 모든 데이터는 회원(`users`)을 정점으로 하여 매장, 상품, 결제, 티켓, 예약이 유기적인 외래키(FK)로 연결됩니다.

```
 [User (회원)]
   │
   ├─ (1 : N) ──▶ [SocialAccount (소셜 계정)]
   │
   ├─ (1 : N) ──▶ [Shop (뷰티샵 매장)] ── (1 : N) ──▶ [ShopProgram] ◀── (N : 1) ── [Program]
   │                │                                                                  │
   │                └─ (N : M) ──▶ [ImageFolderPivot] ◀── [ImageFolder]               │
   │                                      │                                            │
   │                                      ▼                                            │
   ├─ (N : M) ──────────────────────▶ [Image (DAM)] ◀──────────────────────────────────┘
   │                                      ▲
   │                                      │ (M:N 다형성 슬롯 피벗: imageables)
   │
   └─ (1 : N) ──▶ [Order (주문)]
                    │
                    └─ (1 : N) ──▶ [OrderItem (주문상품)]
                                     │
                                     └─ (1 : 1) ──▶ [UserTicket (티켓 마스터)]
                                                      │
                                                      └─ (1 : N) ──▶ [UserTicketItem (회차 슬롯)]
                                                                       │
                                                                       └─ (1 : N) ──▶ [Reservation (방문예약)]
```

---

## 4. 주요 데이터별 진행 단계 및 상태값 흐름 (Domain Status Transition)

플랫폼 내부에서 관리되는 회원, 매장, 프로그램, 주문/티켓, 예약 데이터는 고유한 상태값(`status`, `operating_status`)을 가지며, 업무 진행 단계에 따라 정해진 규칙으로 안전하게 상태가 전환됩니다.

### 4.1 회원 및 인증 진행 단계 (User & Auth)
카카오·네이버·구글 간편 로그인을 통한 최소 정보 수집 후 비즈니스 액션(주문/결제, 입점 신청, 회원정보 수정) 시점에 추가 인증을 수행하는 점진적 온보딩(Progressive Onboarding) 방식을 적용합니다.

- **회원 상태값 (`users.status`)**:
  * `active`: 정상 활동 회원 (가입 시 기본값)
  * `suspended`: 이용 제재 또는 정지된 회원 (소셜 로그인 즉시 차단)
  * `withdrawn`: 탈퇴 회원 (소프트 딜리트 `deleted_at` 병행 기록, 소셜 로그인 시 재가입 차단)

```
    [방문자] ──▶ 소셜 간편 로그인 (Kakao / Naver / Google) ──▶ [User: active (phone: null)]
    [User: active] ──▶ [입점 신청, 주문 결제, 또는 프로필 수정] ──▶ SMS 휴대전화 본인인증 완료 ──▶ [phone 등록 및 is_phone_verified = true]
    [User: active] ──▶ [회원 탈퇴 (ProfileController@destroy)] ──▶ [status: withdrawn (softDeletes)]
```

### 4.2 뷰티샵 심사, 영업 및 취소 대기 진행 단계 (Shop)
입점 심사 상태(`status`)와 실제 영업 노출 상태(`operating_status`)를 독립된 플래그로 분리 관리합니다. 뷰티샵 등록 경로(자율신청, 계정선발급, 직권등록)와 무관하게 **승인 시점의 영업 상태는 무조건 `temp_closed`(영업 준비중/임시휴무)로 초기화**되어 원장(또는 본사 관리자)의 실무 세팅 완료 전 고객 오노출을 원천 방지합니다.

- **심사 진행 상태값 (`shops.status`)**:
  * `pending`: 입점 신청 직후 심사 대기 (신청 기본값)
  * `approved`: 최고관리자 심사 통과 (원장 계정에 Role `shop` 동기화)
  * `rejected`: 심사 반려 (`rejection_reason` 명시)
  * `canceled`: 사용자 자율 취소 (소프트 딜리트 병행, 24시간 재신청 대기 시간 작동)

- **실제 영업 상태값 (`shops.operating_status`)**:
  * `suspended`: 운영 정지 (신청 초기 기본값, 미승인 상태, 본사 제재)
  * `temp_closed`: 원장 설정에 따른 임시 휴무 또는 승인 직후 영업 준비 상태 (초기 기본값)
  * `active`: 정상 영업 및 사용자단 서비스 노출 (필수 정보 입력 가드 통과 시)
  * `closed`: 폐업 처리

```
    [3대 등록 경로 접수 (자율신청 / 온보딩 / 직권등록)] ──▶ status: pending (또는 직권 approved) / operating_status: temp_closed
    [본사 심사 반려] ──▶ status: rejected / operating_status: suspended (반려 사유 확인 후 수정 재심사 가능)
    [사용자 자율 취소] ──▶ status: canceled / 고유키 NULL 처리 및 admin_memo 백업 ──▶ 24시간 재신청 대기 시간 작동
    [본사 심사 승인] ──▶ status: approved / operating_status: temp_closed (기본정보, 영업시간, 휴무일, 정산계좌, 프로그램 On/Off 세팅 대기)
    [원장 실무 세팅 완료 후 영업 개시] ──▶ operating_status: active (일반 사용자 예약 캘린더 정식 노출)
```

### 4.3 주문, 티켓 및 방문 예약 진행 단계 (Order, Ticket & Reservation)
- **주문 상태값 (`orders.status`)**: `pending`(입금대기) ──▶ `paid`(결제완료, 티켓자동발급) ──▶ `cancelled` / `refunded`
- **티켓 아이템 상태값 (`user_ticket_items.status`)**: `active`(잔여회차 보유) ──▶ `exhausted`(회차 소진완료)
- **방문 예약 상태값 (`reservations.status`)**: `pending`(신청대기) ──▶ `confirmed`(원장승인) ──▶ `completed`(현장QR스캔 및 회차차감) / `cancelled`(취소)

```
    [주문 결제 완료 (status: paid)]
                 │
                 ▼
    [UserTicket 마스터 생성] ──▶ [UserTicketItem 회차 슬롯 생성 (status: active, remaining_count: N)]
                                              │
                                              ▼ (고객 매장 및 슬롯 선택)
                                 [Reservation 신청 (status: pending)]
                                              │
                                              ▼ (원장 일정 확인 및 승인)
                                 [Reservation 확정 (status: confirmed)]
                                              │
                                              ▼ (현장 모바일 QR 스캔)
                                 [Reservation 시술 완료 (status: completed)]
                                 ──▶ 해당 UserTicketItem 회차 1회 차감 (0 도달 시 status: exhausted)
```

---

## 5. 다중 소셜 로그인 및 계정 자동 통합 엔진 (Multi-Social Login & Identity Merging)

글로뷰는 사용자 편의성과 전환율을 극대화하기 위해 국내 3대 소셜 인증(카카오, 네이버, 구글)을 통합 제공하며, 주문/티켓/예약 데이터 파편화를 원천 차단하는 계정 통합 아키텍처를 가집니다.

### 5.1 소셜 가입자의 비밀번호 메커니즘 및 듀얼 로그인 지원
1. **최초 가입 시 난수 비밀번호 주입 이유**: `users.password` 컬럼의 무결성(NOT NULL) 보장 및 외부 침입자의 일반 로그인 창 무작위 대입 방어를 위해, 시스템 내부에서 `Hash::make(Str::random(32))` 난수를 생성해 최초 1회 저장합니다. 이 값은 이후 소셜 로그인을 반복해도 변경되지 않습니다.
2. **소셜 로그인 독립성**: 소셜 인증은 OAuth2 프로바이더 ID(`social_accounts.provider_id`)를 대조하여 세션을 발급하므로, 비밀번호의 유무나 변경 여부와 완전히 무관하게 작동합니다.
3. **듀얼 로그인(소셜 간편인증 + 자체 ID/PW) 활성화**: 소셜 회원이 마이페이지 정보수정에서 자체 비밀번호를 등록하면 기존 난수 해시가 고객의 비밀번호 해시로 교체됩니다. 이후 해당 계정은 소셜 원클릭 로그인과 일반 이메일/비밀번호 로그인을 모두 자유롭게 이용할 수 있습니다.

### 5.2 계정 자동 통합 및 트랜잭션 동시성 제어 흐름
- **1단계 (기존 연동 확인)**: 소셜 콜백 인입 시 `social_accounts` 테이블에서 `(provider, provider_id)` 검색 ──▶ 일치 시 `status === 'active'` 검증 후 로그인 및 `last_login_at` 갱신
- **2단계 (신규 소셜 진입 및 DB 트랜잭션)**: 연동 기록 부재 시 `DB::transaction` 및 `User::lockForUpdate()` 진입
  * 이메일(`email`) 대조 결과 기존 가입자가 존재하는 경우: 기존 회원 정보 유지, 프로필 사진 보강 후 `social_accounts`에 `[user_id, provider, provider_id]` 레코드 추가
  * 이메일이 없거나 신규 회원인 경우: `users` 테이블에 신규 회원 생성(`status='active'`, Spatie `user` 역할 부여) 후 `social_accounts`에 연동 레코드 추가
- **3단계 (인증 완료)**: `Auth::login($user)` 실행 및 세션에 저장된 원래 이동 대상 페이지(`intendedUrl`)로 리다이렉트

---

## 6. 뷰티샵 등록 3대 경로 및 점주 온보딩 아키텍처 (Shop 3-Way Onboarding & Setup)

뷰티샵 파트너가 플랫폼에 안착하는 3대 진입 경로를 체계화하여 다양한 오프라인/온라인 영업 환경을 지원합니다.

```
    [경로 1: 일반 회원 자율 신청 (인바운드 파트너)]
    일반 회원 로그인 ──▶ /shops/create (SMS인증 + 사업자진위확인 + LBS주소)
                      ──▶ 신청 완료 (pending / temp_closed)
                      ──▶ 본사 승인 (approved) ──▶ Role shop 부여 ──▶ /shop-admin 진입

    [경로 2: 본사 계정 선발급 + 점진적 온보딩 (오프라인 가맹 영업)]
    본사 관리자가 점주 회원 생성 ──▶ 점주에게 ID/PW 전달 ──▶ 점주 /shop-admin 접속
                      ──▶ EnsureShopOnboarding 4단계 모달 가드 (휴대폰인증 ──▶ 샵등록)
                      ──▶ 신청 완료 (pending) ──▶ 본사 승인 ──▶ /shop-admin 세팅 완료

    [경로 3: 본사 직권 등록 및 점주 매핑 (직영점 및 전략 제휴)]
    본사가 /admin/shops에서 매장 직접 생성 ──▶ 회원 목록 중 원장(또는 본사관리자) 매핑
                      ──▶ 즉시 승인 상태 (approved / temp_closed) 부여 ──▶ 즉시 운영 가능
```

### 6.1 취소 후 24시간 재신청 대기 시간 및 고유키 보존 정책
- **취소 시 대기 시간 검증**: 무분별한 반복 취소/접수를 방지하기 위해 취소 시점(`deleted_at`)으로부터 만 1일(24시간) 동안 동일 사업자번호로의 재신청을 차단합니다.
- **고유키 NULL 처리 및 메모 백업 (`ShopController@applyCancel`)**:
  * 취소 시 `business_number`와 `code` 컬럼을 `null`로 갱신하여 유니크 제약 충돌을 해제하고, 원본 번호는 `admin_memo`에 `[사용자 취소] 원본 사업자번호: ... | 원본 코드: ...` 형태로 구조화하여 영구 보존함으로써 MySQL `1406 Data too long` 에러를 원천 방어합니다.

### 6.2 뷰티샵 관리자 2단계 미들웨어 체인
- **활성 매장 세션 검증 가드 (`EnsureShopActive`)**: 1인 다매장 소유 원장의 활성 매장(`session('active_shop_id')`) 유효성을 검증하며, 본사 최고관리자 계정에 여러 직영점 매장(`shops.user_id = admin_id`)을 바인딩하여 직영 매장 전환 운영을 지원합니다.
- **온보딩 4단계 모달 가드 (`EnsureShopOnboarding`)**: 미인증/미등록/대기/반려 상태에 따라 대시보드 진입 시 전용 안내 모달을 띄워 안전하게 온보딩을 완수하도록 통제합니다.

---

## 7. 중앙 집중형 미디어 라이브러리(DAM) 핵심 아키텍처 (Centralized DAM Engine)

가상서버 스토리지 용량을 절감하고 데이터 프라이버시를 보호하기 위해 개별 도메인별 업로드를 폐지하고, `ImageService` 중심의 중앙 DAM 파이프라인을 구축했습니다.

### 7.1 SHA-256 내용 기반 중복 저장 방지 (Zero Duplication)
업로드된 파일의 실제 바이너리 해시를 계산하여 `images.hash`와 대조합니다. 동일한 내용의 파일이 이미 존재할 경우 새로 파일을 디스크에 쓰지 않고 기존 `Image` 레코드를 즉시 재사용하여 디스크 공간을 절약합니다.

### 7.2 임시 파일 승격 및 피벗 분리 파이프라인
1. **임시 업로드 (`uploadToTemp`)**: 파일 업로드 시 1차로 `temp/` 디렉터리에 저장하고 `is_temp = true`로 마킹합니다.
2. **정식 승격 (`promote`)**: 엔티티(매장, 프로그램 등) 저장 완료 시 `temp/` 디렉터리의 물리 파일들을 해당 엔티티 폴더(`shops/{id}/...`, `programs/{id}/...`)로 이동하고 경로를 일괄 갱신합니다.
3. **가상 폴더 피벗 분리 (`image_folder_pivot`)**: 폴더와 이미지를 N:M 피벗으로 연결하여, 가상 폴더를 삭제하더라도 실물 이미지는 '전체 이미지'에 안전하게 보존됩니다.
4. **차세대 포맷 비동기 큐 인코딩**: 400px WebP 썸네일과 본문용 WebP는 동기 생성하며, 압축률이 가장 높은 AVIF 포맷은 `OptimizeImageJob` 큐 워커를 통해 백그라운드에서 비동기 변환합니다.

---

## 8. 시술 프로그램 3대 실행 방식 및 패키지 번들 엔진 (Program Engine)

- **기본 프로그램 (`single`)**: 단일 케어 프로그램으로 회차는 무조건 1회(`session_count = 1`)로 고정.
- **베이직 패키지 (`package_single`)**: 여러 프로그램을 묶어 당일 1회 방문에 연속 시술하는 결합 상품으로 무조건 1회차(`session_count = 1`).
- **스페셜 패키지 (`package_separate`)**: N회차 또는 복합 프로그램을 결합하여 여러 번에 나누어 개별 예약·사용하는 다회권. 회차는 번들 구성품 수량의 총합으로 자동 계산.
- **매장별 판매 통제 (`shop_program`)**: 최고관리자가 배포한 프로그램을 개별 샵 상황에 따라 판매 활성화(`is_active`), 최소 사전 예약 시간(`min_advance_hours`), 노쇼 규약(`after_deadline_policy`)으로 통제합니다.

---

## 9. 위치기반(LBS) 엔진 및 모바일 QR 티켓 시스템 (LBS & Mobile QR Engine)

- **주소 정제 및 좌표 자동 연동**: Daum 우편번호 서비스 + 카카오 지도 Geocoder API로 위경도(`latitude`, `longitude`) 자동 추출 및 DB 인덱싱 저장.
- **고객 맞춤 샵 탐색**: 브라우저 HTML5 Geolocation API 기반 현재 접속자 좌표 수집 및 하버사인 공식(Haversine Formula)을 활용한 직선거리(km) 기준 가까운 매장 정렬 렌더링.
- **모바일 티켓/예약권 QR 코드 엔진**: 고객 마이페이지 진입 시 실시간 QR 이미지 생성 (별도 앱 설치 없는 모바일 웹 뷰어).
- **현장 QR 차감 파이프라인**: 내방 고객의 QR 코드를 뷰티샵 관리자 스마트폰 카메라로 스캔 ──▶ 매장 일치 및 잔여 회차 즉시 검증 ──▶ `user_ticket_items.remaining_count` 1회 즉시 차감 및 예약 상태 `completed` 종결.

---

## 10. 메시징 및 통합 알림 관제 서브시스템 (Messaging & Notification Subsystem)

고객 본인인증, 주문/결제 확인, 뷰티샵 입점 및 취소 등 모든 플랫폼 통보는 중앙 집중형 알림 템플릿과 통합 발송 서비스를 통해 제어되며, 단일 사건 추적키(`batch_id`) 기반으로 감사 로그가 영구 보존됩니다.

### 10.1 알림 발송 표준 4단계 파이프라인 (`NotificationService::send()`)

    [1단계: 서비스 인스턴스 획득] ──▶ $notificationService = app(NotificationService::class);
    [2단계: 동일 사건 묶음키 선발행] ──▶ $batchId = NotificationLog::generateBatchId(); // M 포함 12자리
    [3단계: 치환변수 맵 조립 & 수신자 조회] ──▶ $variables = ['shop_name' => ..., 'user_name' => ...];
    [4단계: 수신 주체별 순회 발송] ──▶ send(templateCode, receiver, variables, userId, batchId, extraData)

1. **치환 파서 안전장치 (Fail-Safe)**: 누락된 치환 변수는 공백으로 안전하게 대체하여 무중단 발송 보장.
2. **EUC-KR 바이트 기반 채널 자동 승격**: 본문이 90바이트를 초과하면 시스템이 채널을 `SMS`에서 `LMS`로 자동 승격하여 메시지 잘림 사고 원천 방지.
3. **통신 장애 격리 및 관제 보존**: 외부 통신사 API 타임아웃이나 잔여 포인트 부족 등의 장애가 발생해도 예외를 격리하고, `notification_logs`에 `status = 'FAIL'`, `error_message`를 온전히 기록.

---

## 11. 마이페이지 회원정보 수정 파이프라인 (Mypage Profile Management Engine)

소셜 가입자와 일반 가입자를 모두 수용하며, 전화번호 변경 시 동적 SMS 본인인증 재검증, Daum 우편번호 인라인 레이어 검색, Flatpickr 한국어 생년월일 피커, 모카/브론즈 테마(`--primary-color: #b18977;`, 고정 둥글기 `6px`)를 적용한 마이페이지 핵심 서브시스템입니다.

- **전화번호 변경 감지 및 실시간 추적 (`public/js/sms_auth.js`)**:
  * 기존 인증 번호 스냅샷 보관 후 번호가 1자리라도 수정되면 `verified-flag`를 즉시 `false`로 리셋.
  * 인증 완료 상태에서는 인풋 잠금(`readOnly`) 및 [번호 수정] 토글 버튼 노출.
- **Daum 우편번호 인라인 레이어 (`#wrap`)**:
  * 모바일 팝업 차단 문제를 방지하기 위해 팝업 대신 인풋 하단 인라인 컨테이너에 `embed()` 렌더링.

---

## 12. 파일 기반 마크다운 기술 문서 뷰어 아키텍처 (File-based Markdown Viewer Subsystem)

데이터베이스 없이 서버 파일시스템(`storage/app/public/documents/*.md`)을 직접 읽어와 웹에서 체계적으로 열람하고 검색할 수 있는 자체 기술 문서 센터 엔진입니다.

### 12.1 디렉토리 구조 및 `01_readme.md` 기반 정렬 알고리즘
- **메타데이터 오버라이드 (`01_readme.md`)**: 각 폴더 내 `01_readme.md` 파일의 Front Matter(`section_key`, `section_label`)를 파싱하여 아코디언 헤더 명칭으로 바인딩합니다 (웹 리스트 목록 제외).
- **자연 순서 정렬 (Natural Sort)**: `DocumentController`에서 `strnatcasecmp` 함수를 통해 `chapter_1` → `chapter_2` → `chapter_10` 순서로 아코디언을 정렬하며, 루트 파일들은 최하단 `기타 문서` 섹션으로 자동 배치됩니다.

### 12.2 백엔드 파서 및 PHP 8.4 PCRE 정규식 방어 (`DocumentController.php`)
- **UTF-8 BOM 자동 제거**: 윈도우 에디터 저장 시 삽입되는 BOM(`\xEF\xBB\xBF`)을 사전 제거.
- **PCRE 규격 준수 (`\s*` 및 단독 `\R`)**: 문자 클래스 내부 `[...]`에 `\R` 중첩을 금지하는 PCRE 규칙을 준수하여 `^\s*---\s*\R(.*?)\R---\s*(?:\R|$)` 정규식으로 CRLF/LF 개행을 완벽히 방어.
- **다중 키워드 검색 및 스니펫 발췌**: 파일당 최대 5개 매칭 제한 및 전후 80자 스니펫(`snippet`)을 발췌.

### 12.3 프론트엔드 인터랙션 엔진 (`show.blade.php`)
- **Mermaid 1:1 픽셀 크기 고정**: SVG viewBox 폭을 픽셀 단위로 강제 고정하여 반응형 가로 스크롤 컨테이너 생성.
- **PC 마우스 & 모바일 터치 통합 라이트박스**: Fit 모드 / 100% Zoom 모드, PC 마우스 드래그/휠 줌, 모바일 1손가락 드래그 및 2손가락 핀치 줌(`touch-action: none`).
- **플로팅 퀵 네비게이션**: 스크롤 150px 이상 시 [목록] + [TOP] 노출, **5초 무동작 시 자동 페이드아웃** 및 마우스 호버/터치 중 타이머 일시정지 보호.

---

## 13. 핵심 디렉토리 및 클래스 맵 (Key Directory & Class Map)

- **Models**:
  * `App\Models\User`: 회원 계정 및 프로필 마스터
  * `App\Models\SocialAccount`: 다중 SNS 매핑 모델 (`belongsTo(User::class)`, `['provider', 'provider_id']` Unique)
  * `App\Models\Shop`: 뷰티샵 매장 정보, LBS 좌표, 영업/예약 시간 정책, 카테고리/이미지/프로그램 다대다 연동
  * `App\Models\Image`: 중앙 집중형 미디어 파일 정보, SHA-256 해시, 다중 포맷 경로(WebP/AVIF/Thumb), 보호 잠금(🔒)
  * `App\Models\ImageFolder`: 가상 이미지 폴더 트리 모델 (`parent_id` 재귀 관계)
  * `App\Models\Program`: 시술 상품 정보, 3대 실행 방식, 가격 및 회차 규약
  * `App\Models\ProgramBundle`: 패키지 프로그램(부모)과 구성요소(자식) 간의 수량 매핑 피벗 모델
  * `App\Models\Order`: 주문 마스터 모델 (결제 수단, 결제 상태, PG 키, 무통장 입금 정보)
  * `App\Models\OrderItem`: 다형성 주문 상세 레코드 및 단가 스냅샷
  * `App\Models\OrderItemOption`: 주문 당시 선택된 옵션 및 추가금 스냅샷
  * `App\Models\UserTicket`: 디지털 모바일 바우처 티켓 마스터 (16자리 `ticket_code`, 유효기간)
  * `App\Models\UserTicketItem`: 실제 예약 및 1회씩 차감되는 단위 회차 슬롯 모델
  * `App\Models\Reservation`: 뷰티샵 방문 예약 내역, 예약 일시, 상태 전이 모델
  * `App\Models\NotificationTemplate`: 알림 템플릿 마스터, 2단 분류 상수, 스코프 및 치환 파서(`parseContent`, `parseTitle`)
  * `App\Models\NotificationLog`: 전사 알림 발송 통합 관제 로그 (`batch_id` 묶음 추적, 채널, 상태, 에러 메시지)
  * `App\Models\Setting`: 본사 전역 설정 키-값 저장소 (캐시 자동 무효화 및 복수 관리자 번호 역직렬화)
- **Services**:
  * `App\Services\ImageService`: SHA-256 중복 방지 저장(`uploadToTemp`), 정식 디렉터리 승격(`promote`), 단일/다중 슬롯 동기화(`syncSingle`, `syncMulti`), 에디터 동기화(`syncEditorContent`), 고아 파일 삭제(`deleteOrphans`)
  * `App\Services\OrderService`: 비관적 락(`lockForUpdate`) 기반 주문 생성, 결제 수단별 처리, 모바일 티켓 및 슬롯 자동 발급
  * `App\Services\Cafe24SmsService`: 90바이트 SMS/LMS 자동 분기, 인증번호 발송, 발송 로그(`sms_logs`) 감사 추적
  * `App\Services\NotificationService`: 템플릿 기반 동적 알림 발송, `NotificationLog` 영구 적재 및 다중 채널 Fallback 처리
- **Jobs & Queue Workers**:
  * `App\Jobs\OptimizeImageJob`: 비동기 AVIF 차세대 포맷 백그라운드 인코딩 큐 워커 Job
- **Controllers & Middleware**:
  * `App\Http\Controllers\Admin\ImageController`: 중앙 집중형 미디어 라이브러리 CRUD, 4단 정렬, 가상 폴더 검색, 일괄 삭제, 보호 잠금
  * `App\Http\Controllers\Admin\ImageFolderController`: 가상 폴더 트리 조회, 생성, 폴더명 변경, 계층 이동, 파일 이동/복사
  * `App\Http\Controllers\DocumentController`: 파일 기반 마크다운 기술 문서 목록 조회, 섹션 자연 정렬, 검색 스니펫 발췌, 상세 렌더링
  * `App\Http\Controllers\ProfileController`: 마이페이지 회원정보 수정(`edit`, `update`), 소셜 분기 비밀번호 관리(`updatePassword`), 계정 탈퇴(`destroy`)
  * `App\Http\Controllers\Auth\SocialLoginController`: 3대 소셜 로그인 리다이렉트 및 콜백 동시성 계정 통합 제어
  * `App\Http\Controllers\Auth\VerifyPhoneController`: 휴대폰 SMS 인증번호 발송(`/auth/phone/send`) 및 6자리 검증(`/auth/phone/verify`)
  * `App\Http\Controllers\Common\VerifyBusinessController`: 국세청 사업자등록번호 10자리 진위 확인 공용 API 컨트롤러
  * `App\Http\Controllers\ShopController`: 사용자 입점 신청 폼 및 저장(경로 1), 취소 후 24시간 재신청 대기 시간 처리(`applyCancel`), 상태 확인(`applyStatus`)
  * `App\Http\Controllers\Admin\ShopController`: 최고관리자 뷰티샵 직권 등록(경로 3), 심사, 인라인 통제, 미디어 싱크 및 CRUD
  * `App\Http\Controllers\Admin\ProgramController`: 시술 프로그램 및 패키지 번들 구성, 뷰티샵 배포 관리
  * `App\Http\Controllers\Admin\NotificationTemplateController`: 알림 템플릿 CRUD, 원클릭 발송 ON/OFF 토글, 실시간 모바일 목업 프리뷰 동기화
  * `App\Http\Controllers\Admin\NotificationLogController`: 단일 사건(`batch_id`) 기준 통합 발송 관제 마스터 리스트, 아코디언, 단건 모달 API
  * `App\Http\Controllers\ReservationController`: 사용자 티켓 기반 샵 예약 신청 및 조회
  * `App\Http\Controllers\ShopAdmin\DashboardController`: 뷰티샵 관리자 메인 대시보드
  * `App\Http\Controllers\ShopAdmin\ShopController`: 뷰티샵 모달 등록(경로 2), 재심사 요청, 샵 기본 정보 및 `holiday_configs` 영업/정산 설정 수정 관리
  * `App\Http\Controllers\ShopAdmin\ReservationController`: 원장 예약 승인/확정 및 현장 모바일 QR 스캔 차감
  * `App\Http\Middleware\EnsureShopActive`: 1인 다매장 세션(`active_shop_id`) 자동 세팅 및 무매장 신규 점주 온보딩 통과 가드
  * `App\Http\Middleware\EnsureShopOnboarding`: 뷰티샵 관리자 패널 진입 시 4단계(폰인증 ──▶ 샵등록 ──▶ 대기 ──▶ 반려) 뷰 공유 모달 가드

---

## 14. 관리자 및 사용자 레이아웃/기술 자산 명세 (Tech Stack & View Manifest)

### 14.1 관리자 통합 레이아웃 구조 (`resources/views/layouts/admin.blade.php`)
최고관리자와 매장관리자는 단일 메인 래퍼 레이아웃을 공유하며, 진입 URL 접두어에 따라 사이드바 컴포넌트를 동적으로 분기합니다.

- **FOUC(깜빡임) 방지 즉시 실행 스크립트**:
  * 데스크톱 브라우저에서 `localStorage.getItem('sidebarCollapsed')` 또는 화면 폭(1200px 이하)을 HTML 파싱 즉시 평가하여 `document.documentElement`에 `preload-collapsed` 클래스를 선적용함으로써 렌더링 시 깜빡임 차단
- **사이드바 분기 로직**:
  * `request()->is('admin*')` ──▶ `@include('admin.partials.sidebar')` (본사 최고관리자 메뉴: 상점관리, 뷰티샵관리, 미디어 라이브러리, 프로그램관리, 주문/티켓관리, 알림 템플릿 및 관제 로그 등)
  * `request()->is('shop-admin*')` ──▶ `@include('admin.partials.shop_sidebar')` (뷰티샵 원장 전용 메뉴: 대시보드, 매장정보 및 영업설정, 예약접수, 현장 QR인증 등)
- **공통 프레임워크 컴포넌트**: TNB 상단 내비게이션 바(`admin.partials.topbar`), 메인 본문 컨테이너(`content-body`), 푸터(`admin.partials.footer`), 상단 이동 버튼 (`#scrollTopBtn`)
- **글로벌 UI/UX 라이브러리**: Bootstrap 5, FontAwesome 6.4.0 Icons, SweetAlert2 v11 CDN

### 14.2 프론트엔드 스크립트 및 스타일 자산 맵 (Frontend Asset Map)

| 분류 | 파일 경로 | 설명 및 주요 역할 |
|---|---|---|
| **미디어 라이브러리 JS**| `public/js/modal_media.js` | **중앙 집중형 미디어 탐색기 프론트엔드 엔진**: 50개 단위 무한스크롤, 4단 정렬, WebKit 드롭존(OS 폴더 업로드), 폴더 트리 양방향 D&D, 마우스 영역 드래그 다중 선택(Marquee) |
| **공통 인증 모듈 JS** | `public/js/sms_auth.js` | **범용 SMS 본인인증 통합 모듈**: 010/02 자동 하이픈 포맷팅, 카운트다운 타이머, **인증완료 후 번호 실시간 수정 감지 및 verified-flag 자동 초기화/복원** |
| | `public/js/biz_auth.js` | **국세청 사업자등록번호 10자리 진위확인 API 비동기 연동 모듈**: 실시간 10자리 포맷팅 및 통신 성공 시 초록색 (`#3b7a57`) / 실패 시 붉은색 (`#e11d48`) 에러 텍스트 강제 오버라이드 |
| **공통 관리자 JS** | `public/js/admin_custom.js` | 사이드바 토글, 스크롤탑 제어, SweetAlert2 전역 래퍼, 공통 비동기 셋업 |
| **관리자 모듈 JS** | `public/js/admin/admin_shop.js` | 뷰티샵 CRUD 전용 UI, 상태 인라인 변경 AJAX, 다음 주소 연동, 썸네일 제어 |
| | `public/js/admin/admin_program.js`| 프로그램 등록/수정, 3대 실행방식 선택 시 번들 추가 슬롯 렌더링, 샵 배정 피커 UI |
| | `public/js/admin/category_picker.js`| 뷰티샵/프로그램 카테고리 다대다 선택 및 트리 피커 제어 |
| | `public/js/admin/admin_notification.js` | 알림 템플릿 발송 ON/OFF 즉시 토글, 삭제 컨펌, 실시간 모바일 목업 프리뷰 동기화, 대문자 변환 |
| **사용자 모듈 JS** | `public/js/user_custom.js` | 사용자단 SweetAlert2 래퍼(`showSwalAlert`, `showSwalConfirm`, `showToast`), 클립보드 복사, 폰트 크기 조절 |
| | `public/js/address_search.js` | **Daum 우편번호 레이어 검색 및 카카오 지도 Geocoder 좌표 자동 생성 스크립트**: 주소 선택 시 위도(`latitude`), 경도(`longitude`), 권역 카테고리(`region_*`)를 히든 필드에 자동 주입 |
| | `public/js/reservation_picker.js` | 예약 화면 일자 선택, LBS 지도 카카오 맵 렌더링, 시간 슬롯 동적 계산 |
| **문서 뷰어 라이브러리**| `marked.min.js`, `highlight.min.js`, `mermaid.min.js` | 클라이언트 마크다운 파싱, 코드 신택스 하이라이팅, 1:1 픽셀 다이어그램 렌더링 |
| **외부 라이브러리 CDN**| `flatpickr.min.js`, `l10n/ko.js` | 마이페이지 생년월일 전용 모바일 최적화 한국어 달력 피커 |
| | `postcode.v2.js` | 카카오 Daum 우편번호 검색 서비스 CDN |
| **공통 관리자 CSS**| `public/css/admin_custom.css` | 관리자 전체 베이스 스타일 및 레이아웃 커스텀 변수 |
| **관리자 모듈 CSS**| `public/css/admin/sidebar.css` | 슬라이드 사이드바 애니메이션 및 축소(Collapsed) 모드 스타일링 |
| | `public/css/admin/admin_notification.css` | 스마트폰 디바이스 목업 프레임, 노치/상태바, 채널별(알림톡/SMS/이메일) 액정 테마 및 말풍선 그리드 스타일 |
| **공통 사용자 CSS** | `public/css/user_custom.css` | 글로뷰 전역 디자인 변수(`--primary-color: #b18977;`, `--radius-fixed: 6px;`), 폰트 유틸(`fs-xs`~`fs-md`), 버튼 시스템 |
| **마이페이지 CSS** | `public/css/mypage/user_mypage.css` | 마이페이지 대시보드 카드, 티켓 패스, 캘린더 큐브, Flatpickr 글로뷰 브론즈 테마 오버라이드 |

### 14.3 주요 Blade 뷰 라우팅 및 템플릿 구조
- **인증 뷰 (`resources/views/auth/`)**:
  * `login.blade.php`: 글로뷰 웜 브론즈 프리미엄 테마 적용, 카카오(노랑)/네이버(초록)/구글(화이트&4색G) 3대 간편 로그인 버튼 완비
- **최고관리자 뷰 (`resources/views/admin/`)**:
  * `images/`: 중앙 집중형 미디어 라이브러리 메인 캔버스 및 탐색기 그리드(`index`)
  * `shops/`: 승인 매장 목록(`index`), 심사 대기(`pending`, `pending_show`), 등록/수정(`create`, `edit`)
  * `programs/`: 시술 상품 목록(`index`), 3대 실행방식 등록/수정(`create`, `edit`)
  * `notifications/`: 알림 템플릿 모바일 목업 카드 그리드 목록(`index`), 실시간 스마트폰 프리뷰 등록/수정(`create`, `edit`), 단일 사건(`batch_id`) 통합 발송 관제 로그 목록(`logs.blade.php`)
- **뷰티샵 관리자 뷰 (`resources/views/shop_admin/`)**:
  * `index.blade.php`: 원장 메인 대시보드 (온보딩 모달 4종 렌더링 베이스 화면)
  * `shop/edit.blade.php`: 소유 매장 기본 정보 수정 화면
  * `shop/schedule.blade.php`: `holiday_configs` 기반 영업시간, 예약 단위 및 정기/고정 휴무일 설정 화면
- **자체 기술 문서 센터 뷰 (`resources/views/documents/`)**:
  * `index.blade.php`: 장별 아코디언 문서 목록 및 검색 결과 리스트 뷰 (`01_readme.md` 라벨 및 물리 파일명 뱃지 표기)
  * `show.blade.php`: 개별 마크다운 상세 뷰어 (GitHub CSS, 가로 스크롤 테이블, 인터랙티브 터치 줌 라이트박스, 5초 자동 숨김 플로팅 퀵 네비게이션)
- **사용자 쇼핑 및 주문 퍼널 (`resources/views/orders/`)**:
  * `checkout.blade.php`: 결제서 작성 (소셜 가입자 폰인증, 무통장 입금자명 입력, 필수 이용약관/환불규정 열람 체크)
  * `complete.blade.php`: 결제 완료 및 무통장 입금 계좌/기한 안내 화면
- **사용자 마이페이지 (`resources/views/mypage/`)**:
  * `partner.blade.php`: 마이페이지 파트너 센터 (3대 파트너 가입 액션, 뷰티샵 신청 현황 카드, 24시간 재신청 대기 시간 컨펌 모달)
  * `profile/edit.blade.php`: 회원정보 수정 메인 뷰 (기본 정보 + SMS 인증 + Flatpickr 생년월일 + Daum 우편번호 인라인 검색 + 마케팅 수신동의 + 소셜 분기 비밀번호 등록/변경 카드)
  * `orders/index.blade.php`: 주문 및 결제 내역 리스트 (입금 대기 중 뱃지 표시)
  * `tickets/list.blade.php`: 디지털 티켓 보관함 (세로형 티켓 카드, 잔여 회차, [예약하기], [QR보기] 버튼)
  * `reservations/create.blade.php`: 방문 일자 선택, LBS 카카오 지도, 방문 슬롯 선택 및 예약 신청 모달
  * `reservations/show.blade.php`: 예약 상세 명세 및 현장 확인용 QR 코드
- **뷰티샵 입점 및 관리 뷰**:
  * `shops/create.blade.php`: 사용자 입점 신청 폼 (`sms_auth.js` 휴대폰 인증, `biz_auth.js` 국세청 사업자 진위확인, `address_search.js` Daum 주소 및 LBS 카카오 Geocoder 좌표 연동)
  * `shops/status.blade.php`: 사용자 입점 심사 현황 접수증 및 반려 사유 확인 / 재신청 안내 화면