docs: [bending] 절곡품 전용 테이블 분리 완료 문서

- README: bending_items 266건 + bending_models 62건 DB 검증 완료
- README: 하장바 검색 문제 해결 (10건 정상)
- README: bending_data JSON 통합, bending_item_mappings DROP
- README: LOT 코드 체계, 테이블 관계도, 레거시 대응표 갱신
- step1: 데이터분석 업데이트
- step5: canvas 그리기 추가
- .gitattributes CRLF→LF 정규화
This commit is contained in:
강영보
2026-03-19 20:03:46 +09:00
parent 6484e73976
commit 220ab78041
41 changed files with 16081 additions and 14435 deletions

View File

@@ -1,344 +1,344 @@
# 결재관리 MNG↔API 비교 분석 및 반영 가이드
> **작성일**: 2026-03-11
> **상태**: 분석 완료
> **목적**: React 결재관리 화면 구현 시 참고 자료
---
## 1. 개요
### 1.1 배경
결재관리는 API(2025-12-17)에서 최초 구현되었고, MNG(2026-02-27)가 이를 참조하여 구축했다. MNG가 실제 관리자 화면을 만들면서 ~90개 커밋에 걸쳐 대폭 진화했으며, API는 2026-03-11에 "MNG 스타일로 전면 개선" 커밋으로 역반영을 시작했다.
### 1.2 핵심 사실
- MNG와 API는 **동일한 5개 테이블**을 공유한다 (`approvals`, `approval_steps`, `approval_lines`, `approval_forms`, `approval_delegations`)
- 마이그레이션은 **API에서만** 관리한다 (24개 마이그레이션)
- MNG 모델은 API 모델의 **수동 동기 사본**이다
---
## 2. 개발 타임라인
```
2025-12-17 API 최초 구현 (기본 CRUD + 워크플로우 4종)
▼ ─── 약 2개월간 API만 단독 운영 ───
2026-02-27 MNG Phase 1 MVP (API 참조하여 구축, 19파일 2806줄)
2026-02-27 MNG Phase 2 고급기능 (보류/전결/복사재기안, 10파일 757줄)
▼ ─── MNG 독자 진화 시작 ───
2026-02-28 결재선 UI/UX 대폭 개선 (~12 커밋)
- Alpine.js v3 호환, 2패널 에디터, Toss 스타일
- 결재선 템플릿 CRUD, 드래그앤드롭, 모달 전환
- 기본 결재선 자동 선택, Quill.js 편집기
2026-02-28 휴가신청 → 전자결재 자동연동
2026-03-03 삭제 권한 기능 (isDeletableBy, 관리자 삭제)
2026-03-04 지출결의서 전용 폼 (첨부파일 GCS, 법인카드/송금 선택)
2026-03-05 반려이력/재상신, 결재서명란, 거래처 검색, 불러오기
2026-03-05 증명서류 양식 (재직/경력/위촉증명서, 사직서) + PDF
2026-03-06 업무양식 (품의서5종, 인감/위임장/의사록/견적서/공문서)
2026-03-07 연차촉진통지서, 결재/참조선 2영역 분리
▼ ─── MNG 실무 검증 완료 ───
2026-03-11 API "MNG 스타일로 전면 개선" (역방향 반영)
```
---
## 3. 공유 테이블 (5개)
| 테이블 | MNG 모델 경로 | API 모델 경로 |
|--------|-------------|-------------|
| `approvals` | `mng/app/Models/Approvals/Approval.php` | `api/app/Models/Tenants/Approval.php` |
| `approval_steps` | `mng/app/Models/Approvals/ApprovalStep.php` | `api/app/Models/Tenants/ApprovalStep.php` |
| `approval_lines` | `mng/app/Models/Approvals/ApprovalLine.php` | `api/app/Models/Tenants/ApprovalLine.php` |
| `approval_forms` | `mng/app/Models/Approvals/ApprovalForm.php` | `api/app/Models/Tenants/ApprovalForm.php` |
| `approval_delegations` | `mng/app/Models/Approvals/ApprovalDelegation.php` | `api/app/Models/Tenants/ApprovalDelegation.php` |
> MNG에만 있는 별도 테이블: `document_approvals`, `document_template_approval_lines` (문서관리 전용, 메인 결재관리와 무관)
---
## 4. MNG vs API 기능 비교
### 4.1 MNG에서 추가/개선된 기능 (API 원본에 없던 것)
| 분류 | MNG 기능 | 설명 | API 반영 상태 |
|------|----------|------|-------------|
| **워크플로우** | 보류/해제 | `hold()`, `releaseHold()` | ✅ 반영됨 |
| **워크플로우** | 전결 | `preDecide()` — 이후 단계 건너뜀 | ✅ 반영됨 |
| **워크플로우** | 복사재기안 | `copyForRedraft()` — 완료/반려/회수 문서 복사 | ✅ 반영됨 |
| **재상신** | `resubmit_count`, `rejection_history` | 반려 이력 JSON, 재상신 횟수 추적 | ✅ 반영됨 |
| **결재선 UI** | 2패널 에디터 | 좌: 조직도, 우: 선택된 결재선 | ❌ React 구현 필요 |
| **결재선 UI** | 드래그앤드롭 | 결재 순서 변경 | ❌ React 구현 필요 |
| **결재선 UI** | 결재/참조 2영역 분리 | 결재선과 참조선 별도 관리 | ❌ React 구현 필요 |
| **결재선 UI** | Toss 스타일 모달 | 결재선 관리 모달 | ❌ React 구현 필요 |
| **양식 시스템** | 2단계 선택 | 분류 → 양식 드릴다운 | ❌ React 구현 필요 |
| **양식 시스템** | 본문 자동채움 | `body_template` 기반 자동 렌더링 | ❌ React 구현 필요 |
| **양식 시스템** | Quill.js 편집기 | 리치텍스트 본문 편집 토글 | ❌ React 구현 필요 |
| **전용 양식 15종** | 지출결의서 외 다수 | 아래 4.2 참조 | ❌ React 구현 필요 |
| **지출결의서** | 법인카드/송금 선택 | 지출형식별 동적 UI | ❌ React 구현 필요 |
| **지출결의서** | 첨부파일 업로드 | GCS 연동 | ❌ API 엔드포인트 필요 |
| **지출결의서** | 거래처 검색 | 업체명 자동완성 | ❌ React 구현 필요 |
| **지출결의서** | 불러오기 | 이전 결의서 복사 | ❌ React 구현 필요 |
| **결재서명란** | 전통 도장식 테이블 | `_approval-stamp-table.blade.php` | ❌ React 구현 필요 |
| **증명서 PDF** | 4종 PDF 다운로드 | 재직/경력/위촉증명서, 사직서 | ❌ API PDF 엔드포인트 필요 |
| **삭제 권한** | `isDeletableBy()` | 관리자/슈퍼관리자 강제삭제, 일괄삭제 | ❌ API 엔드포인트 필요 |
| **뱃지** | 진행중 건수 | 기안함 뱃지 = 진행중 문서 수 | ✅ badge-counts 반영 |
| **완료함** | 미읽음 알림 | `drafter_read_at` 기반 | ✅ 반영됨 |
| **휴가 연동** | 결재→Leave 자동 변경 | 승인/반려/회수 시 Leave 상태 동기화 | ✅ 반영됨 |
### 4.2 MNG 전용 양식 목록 (15종+)
| 카테고리 | 양식명 | MNG Blade 파일 | PDF |
|---------|--------|---------------|-----|
| **근태** | 연차/반차/조퇴 신청 | `_leave-form.blade.php` | — |
| **지출** | 지출결의서 | `_expense-form.blade.php` | — |
| **품의** | 지출품의서 | `_purchase-request-form.blade.php` | — |
| **품의** | 계약체결품의서 | 상동 (5종 분기) | — |
| **품의** | 구매품의서 | 상동 | — |
| **품의** | 출장품의서 | 상동 | — |
| **품의** | 비용정산서 | 상동 | — |
| **증명** | 재직증명서 | `_certificate-form.blade.php` | ✅ |
| **증명** | 경력증명서 | `_career-cert-form.blade.php` | ✅ |
| **증명** | 위촉증명서 | `_appointment-cert-form.blade.php` | ✅ |
| **인사** | 사직서 | `_resignation-form.blade.php` | ✅ |
| **업무** | 사용인감계 | `_seal-usage-form.blade.php` | — |
| **업무** | 위임장 | `_delegation-form.blade.php` | — |
| **업무** | 이사회의사록 | `_board-minutes-form.blade.php` | — |
| **업무** | 견적서 | `_quotation-form.blade.php` | — |
| **업무** | 공문서 | `_official-letter-form.blade.php` | — |
| **근태** | 연차촉진통지서 1차 | `_leave-promotion-1st-form.blade.php` | — |
| **근태** | 연차촉진통지서 2차 | `_leave-promotion-2nd-form.blade.php` | — |
> 각 양식은 `_<name>-form.blade.php` (기안 작성)와 `_<name>-show.blade.php` (상세 조회) 쌍으로 구성
---
## 5. API 반영 현황
### 5.1 이미 반영 완료
| 항목 | 설명 |
|------|------|
| DB 스키마 | 마이그레이션 24개 — MNG와 완전 동기화 |
| 모델 상수/관계/헬퍼 | 6가지 문서 상태, 5가지 단계 상태, 3가지 step_type |
| 워크플로우 전체 | submit/approve/reject/cancel/hold/releaseHold/preDecide/copyForRedraft |
| 위임 CRUD | delegations 엔드포인트 4개 |
| 결재함 4종 + badge-counts | drafts/inbox/reference/completed + summary |
| FormRequest 검증 21개 | MNG보다 정교하게 분리 |
| Swagger 문서 | 3개 파일 (ApprovalApi, ApprovalFormApi, ApprovalLineApi) |
| Leave/Document 연동 | 결재 상태 변경 시 연관 엔티티 자동 동기화 |
| Observer 알림 | TodayIssue 발행 (ApprovalIssueObserver, ApprovalStepIssueObserver) |
| 테넌트 부트스트랩 | 새 테넌트 생성 시 기본 양식 5종 자동 시딩 |
### 5.2 API에 미반영 (React 화면 개발 시 필요)
| 항목 | 설명 | 난이도 | 비고 |
|------|------|--------|------|
| 🔴 전용 양식 렌더링 | 15종 양식별 폼 UI + 조회 UI | 대형 | MNG Blade를 React로 재구현 |
| 🔴 결재선 에디터 UI | 2패널 + 드래그앤드롭 + 결재/참조 분리 | 대형 | MNG의 `_approval-line-editor.blade.php` 참조 |
| 🟡 결재서명란 | 전통 도장식 결재 테이블 | 중형 | MNG의 `_approval-stamp-table.blade.php` 참조 |
| 🟡 양식 2단계 선택 | 분류 → 양식 드릴다운 | 중형 | |
| 🟡 증명서 PDF 출력 | API에서 DomPDF 렌더링 엔드포인트 | 중형 | MNG는 자체 처리 중 |
| 🟡 위임 결재 실제 동작 | `acted_by` 대결 처리 로직 | 중형 | Phase 3 |
| 🟡 병렬 결재 | `parallel_group` 활용 로직 | 중형 | Phase 3 |
| 🟢 첨부파일 업로드 | 결재 전용 업로드/다운로드 엔드포인트 | 소형 | 공통 File API 활용 가능 |
| 🟢 관리자 강제삭제 | 슈퍼관리자 권한 관리/일괄삭제 | 소형 | |
| 🟢 결재 통계/리포트 | 기간별/부서별/양식별 통계 | 소형 | Phase 4 |
---
## 6. 프로젝트별 역할 분담
```
MNG (관리자 화면 - Blade) API (REST 백엔드) React (사용자 화면)
┌──────────────────────┐ ┌──────────────────────┐ ┌──────────────────────┐
│ ✅ 결재 전체 기능 │ │ ✅ 워크플로우 로직 │ │ ❌ 화면 미구현 │
│ ✅ 15종+ 양식 UI │ │ ✅ REST API 전체 │ │ │
│ ✅ 결재선 에디터 │ │ ✅ FormRequest 검증 │ │ React에서 구현 필요: │
│ ✅ 결재서명란 │ │ ✅ Swagger 문서 │ │ - 양식별 폼 UI │
│ ✅ PDF 출력 4종 │ │ ✅ Observer 알림 │ │ - 결재선 에디터 │
│ ✅ 첨부파일 GCS │ │ ✅ Leave/Doc 연동 │ │ - 결재서명란 │
│ ✅ 관리자 강제삭제 │ │ ✅ 테넌트 부트스트랩 │ │ - PDF 다운로드 │
│ ✅ 일괄삭제 │ │ │ │ - 파일 업로드 │
│ │ │ ❌ PDF 생성 엔드포인트│ │ │
│ │ │ ❌ 위임 대결 로직 │ │ │
│ │ │ ❌ 병렬 결재 로직 │ │ │
└──────────────────────┘ └──────────────────────┘ └──────────────────────┘
가장 완성도 높음 백엔드 로직 완성 UI 구현 대기 중
```
---
## 7. React 구현 시 MNG 참조 파일 가이드
### 7.1 뷰 파일 구조 (`mng/resources/views/approvals/`)
```
approvals/
├── drafts.blade.php ← 기안함 목록
├── pending.blade.php ← 결재 대기함 목록
├── completed.blade.php ← 처리 완료함 목록
├── references.blade.php ← 참조함 목록
├── create.blade.php ← 기안 작성
├── edit.blade.php ← 기안 수정
├── show.blade.php ← 결재 상세 조회
├── partials/
│ ├── _approval-line-editor.blade.php ← 🔴 결재선 에디터 (핵심 UI)
│ ├── _approval-stamp-table.blade.php ← 🟡 결재서명란
│ ├── _status-badge.blade.php ← 상태 뱃지
│ ├── _step-progress.blade.php ← 결재 진행 현황
│ │
│ ├── _expense-form.blade.php ← 지출결의서 기안
│ ├── _expense-show.blade.php ← 지출결의서 조회
│ ├── _certificate-form.blade.php ← 재직증명서 기안
│ ├── _certificate-show.blade.php ← 재직증명서 조회
│ ├── _career-cert-form.blade.php ← 경력증명서 기안
│ ├── _career-cert-show.blade.php ← 경력증명서 조회
│ ├── _appointment-cert-form.blade.php ← 위촉증명서 기안
│ ├── _appointment-cert-show.blade.php ← 위촉증명서 조회
│ ├── _resignation-form.blade.php ← 사직서 기안
│ ├── _resignation-show.blade.php ← 사직서 조회
│ ├── _purchase-request-form.blade.php ← 품의서 기안 (5종)
│ ├── _purchase-request-show.blade.php ← 품의서 조회
│ ├── _seal-usage-form.blade.php ← 인감 기안
│ ├── _seal-usage-show.blade.php ← 인감 조회
│ ├── _delegation-form.blade.php ← 위임장 기안
│ ├── _delegation-show.blade.php ← 위임장 조회
│ ├── _board-minutes-form.blade.php ← 의사록 기안
│ ├── _board-minutes-show.blade.php ← 의사록 조회
│ ├── _quotation-form.blade.php ← 견적서 기안
│ ├── _quotation-show.blade.php ← 견적서 조회
│ ├── _official-letter-form.blade.php ← 공문서 기안
│ ├── _official-letter-show.blade.php ← 공문서 조회
│ ├── _leave-form.blade.php ← 근태신청 기안
│ ├── _leave-show.blade.php ← 근태신청 조회
│ ├── _leave-promotion-1st-form.blade.php ← 연차촉진 1차
│ ├── _leave-promotion-1st-show.blade.php
│ ├── _leave-promotion-2nd-form.blade.php ← 연차촉진 2차
│ └── _leave-promotion-2nd-show.blade.php
```
### 7.2 API 엔드포인트 참조
| MNG 엔드포인트 (내부 API) | 대응하는 API 엔드포인트 |
|--------------------------|----------------------|
| `POST /api/v1/approval-mgmt` | `POST /v1/approvals` |
| `GET /api/v1/approval-mgmt/{id}` | `GET /v1/approvals/{id}` |
| `PUT /api/v1/approval-mgmt/{id}` | `PATCH /v1/approvals/{id}` |
| `DELETE /api/v1/approval-mgmt/{id}` | `DELETE /v1/approvals/{id}` |
| `POST /api/v1/approval-mgmt/{id}/submit` | `POST /v1/approvals/{id}/submit` |
| `POST /api/v1/approval-mgmt/{id}/approve` | `POST /v1/approvals/{id}/approve` |
| `POST /api/v1/approval-mgmt/{id}/reject` | `POST /v1/approvals/{id}/reject` |
| `POST /api/v1/approval-mgmt/{id}/cancel` | `POST /v1/approvals/{id}/cancel` |
| `POST /api/v1/approval-mgmt/{id}/hold` | `POST /v1/approvals/{id}/hold` |
| `POST /api/v1/approval-mgmt/{id}/release-hold` | `POST /v1/approvals/{id}/release-hold` |
| `POST /api/v1/approval-mgmt/{id}/pre-decide` | `POST /v1/approvals/{id}/pre-decide` |
| `POST /api/v1/approval-mgmt/{id}/copy` | `POST /v1/approvals/{id}/copy` |
| `GET /api/v1/approval-mgmt/forms` | `GET /v1/approval-forms/active` |
| `GET /api/v1/approval-mgmt/lines` | `GET /v1/approval-lines` |
| `POST /api/v1/approval-mgmt/upload-file` | (공통 File API 사용) |
| `GET /api/v1/approval-mgmt/badge-counts` | `GET /v1/approvals/badge-counts` |
### 7.3 서비스 클래스 비교
| 기능 | MNG `ApprovalService` | API `ApprovalService` |
|------|----------------------|----------------------|
| 기안함 | `getMyDrafts()` | `drafts()` |
| 결재함 | `getPendingForMe()` | `inbox()` |
| 완료함 | `getCompletedByMe()` | `completed()` |
| 참조함 | `getReferencesForMe()` | `reference()` |
| 현황 카드 | — | `draftsSummary()`, `inboxSummary()`, `completedSummary()` |
| 생성 | `createApproval()` | `store()` |
| 수정 | `updateApproval()` | `update()` |
| 삭제 | `deleteApproval()`, `forceDeleteApproval()` | `destroy()` |
| 상신 | `submitApproval()` | `submit()` |
| 승인 | `approveApprovalStep()` | `approve()` |
| 반려 | `rejectApprovalStep()` | `reject()` |
| 회수 | `cancelApproval()` | `cancel()` |
| 보류 | `holdApproval()` | `hold()` |
| 보류해제 | `releaseApprovalHold()` | `releaseHold()` |
| 전결 | `preDecide()` (ApprovalApiController 내) | `preDecide()` |
| 복사재기안 | `copyForRedraft()` | `copyForRedraft()` |
| 결재선 CRUD | `createLine()`, `updateLine()`, `deleteLine()` | `lineStore()`, `lineUpdate()`, `lineDestroy()` |
| 양식 CRUD | — | `formStore()`, `formUpdate()`, `formDestroy()` |
| 위임 CRUD | — | `delegationStore()`, `delegationUpdate()`, `delegationDestroy()` |
| 휴가 연동 | `handleApprovalCompleted/Rejected/Deleted/Cancelled()` | 내부 처리 |
| PDF 생성 | 컨트롤러에서 DomPDF 직접 호출 | ❌ 미구현 |
---
## 8. 모델 동기화 주의사항
### 8.1 동기화가 필요한 시점
| 이벤트 | 조치 |
|--------|------|
| API에서 마이그레이션 추가 | MNG 모델의 `$fillable`, `$casts` 업데이트 |
| API 모델에 새 관계 추가 | MNG 모델에도 동일 관계 추가 |
| API 모델에 새 상수 추가 | MNG 모델에도 동일 상수 추가 |
| MNG에서 새 헬퍼 메서드 추가 | API 모델에 반영 여부 판단 (UI 전용이면 불필요) |
### 8.2 현재 차이점
| 항목 | MNG 모델 | API 모델 |
|------|---------|---------|
| Trait | `BelongsToTenant`, `SoftDeletes` | `BelongsToTenant`, `SoftDeletes`, `Auditable`, `ModelTrait` |
| 네임스페이스 | `App\Models\Approvals` | `App\Models\Tenants` |
| 감사 로깅 | — | `Auditable` trait으로 자동 기록 |
---
## 9. React 구현 우선순위 제안
### Phase A: 기본 결재 (필수)
1. 기안함/결재함/완료함/참조함 목록 화면
2. 기안 작성 (양식 선택 → 결재선 지정 → 본문 작성 → 상신)
3. 결재 상세 조회 + 승인/반려/회수 액션
4. 결재선 에디터 (2패널 + 결재/참조 분리)
5. badge-counts (사이드바 뱃지)
### Phase B: 양식 확장
1. 지출결의서 전용 폼 (법인카드/송금/첨부파일)
2. 품의서 5종
3. 근태신청 (휴가 연동)
4. 결재서명란
### Phase C: 증명서/업무 양식
1. 재직/경력/위촉증명서 + PDF 다운로드
2. 사직서, 인감, 위임장, 의사록, 견적서, 공문서
3. 연차촉진통지서
### Phase D: 고급 기능
1. 위임 대결 (Phase 3)
2. 병렬 결재 (Phase 3)
3. 결재 통계/리포트 (Phase 4)
---
## 관련 문서
- [결재관리 개요](README.md) — 시스템 전체 개요
- [양식 기술 명세](form-types.md) — 양식별 필드, JSON 구조
- [워크플로우 상세](workflows.md) — 각 동작의 흐름
- [API 명세](api-reference.md) — 엔드포인트 목록
- [UI 화면 구성](ui-screens.md) — MNG 화면별 UI
- [DB 변경 및 모델 동기화](db-changes-and-model-sync.md) — 마이그레이션 이력
- [API 결재 연동 명세](../../frontend/api-specs/approval-api.md) — React용 API 명세
- [결재 통합 계획](../../dev/dev_plans/approval-system-unification-plan.md) — MNG→API 통합 계획
---
**최종 업데이트**: 2026-03-11
# 결재관리 MNG↔API 비교 분석 및 반영 가이드
> **작성일**: 2026-03-11
> **상태**: 분석 완료
> **목적**: React 결재관리 화면 구현 시 참고 자료
---
## 1. 개요
### 1.1 배경
결재관리는 API(2025-12-17)에서 최초 구현되었고, MNG(2026-02-27)가 이를 참조하여 구축했다. MNG가 실제 관리자 화면을 만들면서 ~90개 커밋에 걸쳐 대폭 진화했으며, API는 2026-03-11에 "MNG 스타일로 전면 개선" 커밋으로 역반영을 시작했다.
### 1.2 핵심 사실
- MNG와 API는 **동일한 5개 테이블**을 공유한다 (`approvals`, `approval_steps`, `approval_lines`, `approval_forms`, `approval_delegations`)
- 마이그레이션은 **API에서만** 관리한다 (24개 마이그레이션)
- MNG 모델은 API 모델의 **수동 동기 사본**이다
---
## 2. 개발 타임라인
```
2025-12-17 API 최초 구현 (기본 CRUD + 워크플로우 4종)
▼ ─── 약 2개월간 API만 단독 운영 ───
2026-02-27 MNG Phase 1 MVP (API 참조하여 구축, 19파일 2806줄)
2026-02-27 MNG Phase 2 고급기능 (보류/전결/복사재기안, 10파일 757줄)
▼ ─── MNG 독자 진화 시작 ───
2026-02-28 결재선 UI/UX 대폭 개선 (~12 커밋)
- Alpine.js v3 호환, 2패널 에디터, Toss 스타일
- 결재선 템플릿 CRUD, 드래그앤드롭, 모달 전환
- 기본 결재선 자동 선택, Quill.js 편집기
2026-02-28 휴가신청 → 전자결재 자동연동
2026-03-03 삭제 권한 기능 (isDeletableBy, 관리자 삭제)
2026-03-04 지출결의서 전용 폼 (첨부파일 GCS, 법인카드/송금 선택)
2026-03-05 반려이력/재상신, 결재서명란, 거래처 검색, 불러오기
2026-03-05 증명서류 양식 (재직/경력/위촉증명서, 사직서) + PDF
2026-03-06 업무양식 (품의서5종, 인감/위임장/의사록/견적서/공문서)
2026-03-07 연차촉진통지서, 결재/참조선 2영역 분리
▼ ─── MNG 실무 검증 완료 ───
2026-03-11 API "MNG 스타일로 전면 개선" (역방향 반영)
```
---
## 3. 공유 테이블 (5개)
| 테이블 | MNG 모델 경로 | API 모델 경로 |
|--------|-------------|-------------|
| `approvals` | `mng/app/Models/Approvals/Approval.php` | `api/app/Models/Tenants/Approval.php` |
| `approval_steps` | `mng/app/Models/Approvals/ApprovalStep.php` | `api/app/Models/Tenants/ApprovalStep.php` |
| `approval_lines` | `mng/app/Models/Approvals/ApprovalLine.php` | `api/app/Models/Tenants/ApprovalLine.php` |
| `approval_forms` | `mng/app/Models/Approvals/ApprovalForm.php` | `api/app/Models/Tenants/ApprovalForm.php` |
| `approval_delegations` | `mng/app/Models/Approvals/ApprovalDelegation.php` | `api/app/Models/Tenants/ApprovalDelegation.php` |
> MNG에만 있는 별도 테이블: `document_approvals`, `document_template_approval_lines` (문서관리 전용, 메인 결재관리와 무관)
---
## 4. MNG vs API 기능 비교
### 4.1 MNG에서 추가/개선된 기능 (API 원본에 없던 것)
| 분류 | MNG 기능 | 설명 | API 반영 상태 |
|------|----------|------|-------------|
| **워크플로우** | 보류/해제 | `hold()`, `releaseHold()` | ✅ 반영됨 |
| **워크플로우** | 전결 | `preDecide()` — 이후 단계 건너뜀 | ✅ 반영됨 |
| **워크플로우** | 복사재기안 | `copyForRedraft()` — 완료/반려/회수 문서 복사 | ✅ 반영됨 |
| **재상신** | `resubmit_count`, `rejection_history` | 반려 이력 JSON, 재상신 횟수 추적 | ✅ 반영됨 |
| **결재선 UI** | 2패널 에디터 | 좌: 조직도, 우: 선택된 결재선 | ❌ React 구현 필요 |
| **결재선 UI** | 드래그앤드롭 | 결재 순서 변경 | ❌ React 구현 필요 |
| **결재선 UI** | 결재/참조 2영역 분리 | 결재선과 참조선 별도 관리 | ❌ React 구현 필요 |
| **결재선 UI** | Toss 스타일 모달 | 결재선 관리 모달 | ❌ React 구현 필요 |
| **양식 시스템** | 2단계 선택 | 분류 → 양식 드릴다운 | ❌ React 구현 필요 |
| **양식 시스템** | 본문 자동채움 | `body_template` 기반 자동 렌더링 | ❌ React 구현 필요 |
| **양식 시스템** | Quill.js 편집기 | 리치텍스트 본문 편집 토글 | ❌ React 구현 필요 |
| **전용 양식 15종** | 지출결의서 외 다수 | 아래 4.2 참조 | ❌ React 구현 필요 |
| **지출결의서** | 법인카드/송금 선택 | 지출형식별 동적 UI | ❌ React 구현 필요 |
| **지출결의서** | 첨부파일 업로드 | GCS 연동 | ❌ API 엔드포인트 필요 |
| **지출결의서** | 거래처 검색 | 업체명 자동완성 | ❌ React 구현 필요 |
| **지출결의서** | 불러오기 | 이전 결의서 복사 | ❌ React 구현 필요 |
| **결재서명란** | 전통 도장식 테이블 | `_approval-stamp-table.blade.php` | ❌ React 구현 필요 |
| **증명서 PDF** | 4종 PDF 다운로드 | 재직/경력/위촉증명서, 사직서 | ❌ API PDF 엔드포인트 필요 |
| **삭제 권한** | `isDeletableBy()` | 관리자/슈퍼관리자 강제삭제, 일괄삭제 | ❌ API 엔드포인트 필요 |
| **뱃지** | 진행중 건수 | 기안함 뱃지 = 진행중 문서 수 | ✅ badge-counts 반영 |
| **완료함** | 미읽음 알림 | `drafter_read_at` 기반 | ✅ 반영됨 |
| **휴가 연동** | 결재→Leave 자동 변경 | 승인/반려/회수 시 Leave 상태 동기화 | ✅ 반영됨 |
### 4.2 MNG 전용 양식 목록 (15종+)
| 카테고리 | 양식명 | MNG Blade 파일 | PDF |
|---------|--------|---------------|-----|
| **근태** | 연차/반차/조퇴 신청 | `_leave-form.blade.php` | — |
| **지출** | 지출결의서 | `_expense-form.blade.php` | — |
| **품의** | 지출품의서 | `_purchase-request-form.blade.php` | — |
| **품의** | 계약체결품의서 | 상동 (5종 분기) | — |
| **품의** | 구매품의서 | 상동 | — |
| **품의** | 출장품의서 | 상동 | — |
| **품의** | 비용정산서 | 상동 | — |
| **증명** | 재직증명서 | `_certificate-form.blade.php` | ✅ |
| **증명** | 경력증명서 | `_career-cert-form.blade.php` | ✅ |
| **증명** | 위촉증명서 | `_appointment-cert-form.blade.php` | ✅ |
| **인사** | 사직서 | `_resignation-form.blade.php` | ✅ |
| **업무** | 사용인감계 | `_seal-usage-form.blade.php` | — |
| **업무** | 위임장 | `_delegation-form.blade.php` | — |
| **업무** | 이사회의사록 | `_board-minutes-form.blade.php` | — |
| **업무** | 견적서 | `_quotation-form.blade.php` | — |
| **업무** | 공문서 | `_official-letter-form.blade.php` | — |
| **근태** | 연차촉진통지서 1차 | `_leave-promotion-1st-form.blade.php` | — |
| **근태** | 연차촉진통지서 2차 | `_leave-promotion-2nd-form.blade.php` | — |
> 각 양식은 `_<name>-form.blade.php` (기안 작성)와 `_<name>-show.blade.php` (상세 조회) 쌍으로 구성
---
## 5. API 반영 현황
### 5.1 이미 반영 완료
| 항목 | 설명 |
|------|------|
| DB 스키마 | 마이그레이션 24개 — MNG와 완전 동기화 |
| 모델 상수/관계/헬퍼 | 6가지 문서 상태, 5가지 단계 상태, 3가지 step_type |
| 워크플로우 전체 | submit/approve/reject/cancel/hold/releaseHold/preDecide/copyForRedraft |
| 위임 CRUD | delegations 엔드포인트 4개 |
| 결재함 4종 + badge-counts | drafts/inbox/reference/completed + summary |
| FormRequest 검증 21개 | MNG보다 정교하게 분리 |
| Swagger 문서 | 3개 파일 (ApprovalApi, ApprovalFormApi, ApprovalLineApi) |
| Leave/Document 연동 | 결재 상태 변경 시 연관 엔티티 자동 동기화 |
| Observer 알림 | TodayIssue 발행 (ApprovalIssueObserver, ApprovalStepIssueObserver) |
| 테넌트 부트스트랩 | 새 테넌트 생성 시 기본 양식 5종 자동 시딩 |
### 5.2 API에 미반영 (React 화면 개발 시 필요)
| 항목 | 설명 | 난이도 | 비고 |
|------|------|--------|------|
| 🔴 전용 양식 렌더링 | 15종 양식별 폼 UI + 조회 UI | 대형 | MNG Blade를 React로 재구현 |
| 🔴 결재선 에디터 UI | 2패널 + 드래그앤드롭 + 결재/참조 분리 | 대형 | MNG의 `_approval-line-editor.blade.php` 참조 |
| 🟡 결재서명란 | 전통 도장식 결재 테이블 | 중형 | MNG의 `_approval-stamp-table.blade.php` 참조 |
| 🟡 양식 2단계 선택 | 분류 → 양식 드릴다운 | 중형 | |
| 🟡 증명서 PDF 출력 | API에서 DomPDF 렌더링 엔드포인트 | 중형 | MNG는 자체 처리 중 |
| 🟡 위임 결재 실제 동작 | `acted_by` 대결 처리 로직 | 중형 | Phase 3 |
| 🟡 병렬 결재 | `parallel_group` 활용 로직 | 중형 | Phase 3 |
| 🟢 첨부파일 업로드 | 결재 전용 업로드/다운로드 엔드포인트 | 소형 | 공통 File API 활용 가능 |
| 🟢 관리자 강제삭제 | 슈퍼관리자 권한 관리/일괄삭제 | 소형 | |
| 🟢 결재 통계/리포트 | 기간별/부서별/양식별 통계 | 소형 | Phase 4 |
---
## 6. 프로젝트별 역할 분담
```
MNG (관리자 화면 - Blade) API (REST 백엔드) React (사용자 화면)
┌──────────────────────┐ ┌──────────────────────┐ ┌──────────────────────┐
│ ✅ 결재 전체 기능 │ │ ✅ 워크플로우 로직 │ │ ❌ 화면 미구현 │
│ ✅ 15종+ 양식 UI │ │ ✅ REST API 전체 │ │ │
│ ✅ 결재선 에디터 │ │ ✅ FormRequest 검증 │ │ React에서 구현 필요: │
│ ✅ 결재서명란 │ │ ✅ Swagger 문서 │ │ - 양식별 폼 UI │
│ ✅ PDF 출력 4종 │ │ ✅ Observer 알림 │ │ - 결재선 에디터 │
│ ✅ 첨부파일 GCS │ │ ✅ Leave/Doc 연동 │ │ - 결재서명란 │
│ ✅ 관리자 강제삭제 │ │ ✅ 테넌트 부트스트랩 │ │ - PDF 다운로드 │
│ ✅ 일괄삭제 │ │ │ │ - 파일 업로드 │
│ │ │ ❌ PDF 생성 엔드포인트│ │ │
│ │ │ ❌ 위임 대결 로직 │ │ │
│ │ │ ❌ 병렬 결재 로직 │ │ │
└──────────────────────┘ └──────────────────────┘ └──────────────────────┘
가장 완성도 높음 백엔드 로직 완성 UI 구현 대기 중
```
---
## 7. React 구현 시 MNG 참조 파일 가이드
### 7.1 뷰 파일 구조 (`mng/resources/views/approvals/`)
```
approvals/
├── drafts.blade.php ← 기안함 목록
├── pending.blade.php ← 결재 대기함 목록
├── completed.blade.php ← 처리 완료함 목록
├── references.blade.php ← 참조함 목록
├── create.blade.php ← 기안 작성
├── edit.blade.php ← 기안 수정
├── show.blade.php ← 결재 상세 조회
├── partials/
│ ├── _approval-line-editor.blade.php ← 🔴 결재선 에디터 (핵심 UI)
│ ├── _approval-stamp-table.blade.php ← 🟡 결재서명란
│ ├── _status-badge.blade.php ← 상태 뱃지
│ ├── _step-progress.blade.php ← 결재 진행 현황
│ │
│ ├── _expense-form.blade.php ← 지출결의서 기안
│ ├── _expense-show.blade.php ← 지출결의서 조회
│ ├── _certificate-form.blade.php ← 재직증명서 기안
│ ├── _certificate-show.blade.php ← 재직증명서 조회
│ ├── _career-cert-form.blade.php ← 경력증명서 기안
│ ├── _career-cert-show.blade.php ← 경력증명서 조회
│ ├── _appointment-cert-form.blade.php ← 위촉증명서 기안
│ ├── _appointment-cert-show.blade.php ← 위촉증명서 조회
│ ├── _resignation-form.blade.php ← 사직서 기안
│ ├── _resignation-show.blade.php ← 사직서 조회
│ ├── _purchase-request-form.blade.php ← 품의서 기안 (5종)
│ ├── _purchase-request-show.blade.php ← 품의서 조회
│ ├── _seal-usage-form.blade.php ← 인감 기안
│ ├── _seal-usage-show.blade.php ← 인감 조회
│ ├── _delegation-form.blade.php ← 위임장 기안
│ ├── _delegation-show.blade.php ← 위임장 조회
│ ├── _board-minutes-form.blade.php ← 의사록 기안
│ ├── _board-minutes-show.blade.php ← 의사록 조회
│ ├── _quotation-form.blade.php ← 견적서 기안
│ ├── _quotation-show.blade.php ← 견적서 조회
│ ├── _official-letter-form.blade.php ← 공문서 기안
│ ├── _official-letter-show.blade.php ← 공문서 조회
│ ├── _leave-form.blade.php ← 근태신청 기안
│ ├── _leave-show.blade.php ← 근태신청 조회
│ ├── _leave-promotion-1st-form.blade.php ← 연차촉진 1차
│ ├── _leave-promotion-1st-show.blade.php
│ ├── _leave-promotion-2nd-form.blade.php ← 연차촉진 2차
│ └── _leave-promotion-2nd-show.blade.php
```
### 7.2 API 엔드포인트 참조
| MNG 엔드포인트 (내부 API) | 대응하는 API 엔드포인트 |
|--------------------------|----------------------|
| `POST /api/v1/approval-mgmt` | `POST /v1/approvals` |
| `GET /api/v1/approval-mgmt/{id}` | `GET /v1/approvals/{id}` |
| `PUT /api/v1/approval-mgmt/{id}` | `PATCH /v1/approvals/{id}` |
| `DELETE /api/v1/approval-mgmt/{id}` | `DELETE /v1/approvals/{id}` |
| `POST /api/v1/approval-mgmt/{id}/submit` | `POST /v1/approvals/{id}/submit` |
| `POST /api/v1/approval-mgmt/{id}/approve` | `POST /v1/approvals/{id}/approve` |
| `POST /api/v1/approval-mgmt/{id}/reject` | `POST /v1/approvals/{id}/reject` |
| `POST /api/v1/approval-mgmt/{id}/cancel` | `POST /v1/approvals/{id}/cancel` |
| `POST /api/v1/approval-mgmt/{id}/hold` | `POST /v1/approvals/{id}/hold` |
| `POST /api/v1/approval-mgmt/{id}/release-hold` | `POST /v1/approvals/{id}/release-hold` |
| `POST /api/v1/approval-mgmt/{id}/pre-decide` | `POST /v1/approvals/{id}/pre-decide` |
| `POST /api/v1/approval-mgmt/{id}/copy` | `POST /v1/approvals/{id}/copy` |
| `GET /api/v1/approval-mgmt/forms` | `GET /v1/approval-forms/active` |
| `GET /api/v1/approval-mgmt/lines` | `GET /v1/approval-lines` |
| `POST /api/v1/approval-mgmt/upload-file` | (공통 File API 사용) |
| `GET /api/v1/approval-mgmt/badge-counts` | `GET /v1/approvals/badge-counts` |
### 7.3 서비스 클래스 비교
| 기능 | MNG `ApprovalService` | API `ApprovalService` |
|------|----------------------|----------------------|
| 기안함 | `getMyDrafts()` | `drafts()` |
| 결재함 | `getPendingForMe()` | `inbox()` |
| 완료함 | `getCompletedByMe()` | `completed()` |
| 참조함 | `getReferencesForMe()` | `reference()` |
| 현황 카드 | — | `draftsSummary()`, `inboxSummary()`, `completedSummary()` |
| 생성 | `createApproval()` | `store()` |
| 수정 | `updateApproval()` | `update()` |
| 삭제 | `deleteApproval()`, `forceDeleteApproval()` | `destroy()` |
| 상신 | `submitApproval()` | `submit()` |
| 승인 | `approveApprovalStep()` | `approve()` |
| 반려 | `rejectApprovalStep()` | `reject()` |
| 회수 | `cancelApproval()` | `cancel()` |
| 보류 | `holdApproval()` | `hold()` |
| 보류해제 | `releaseApprovalHold()` | `releaseHold()` |
| 전결 | `preDecide()` (ApprovalApiController 내) | `preDecide()` |
| 복사재기안 | `copyForRedraft()` | `copyForRedraft()` |
| 결재선 CRUD | `createLine()`, `updateLine()`, `deleteLine()` | `lineStore()`, `lineUpdate()`, `lineDestroy()` |
| 양식 CRUD | — | `formStore()`, `formUpdate()`, `formDestroy()` |
| 위임 CRUD | — | `delegationStore()`, `delegationUpdate()`, `delegationDestroy()` |
| 휴가 연동 | `handleApprovalCompleted/Rejected/Deleted/Cancelled()` | 내부 처리 |
| PDF 생성 | 컨트롤러에서 DomPDF 직접 호출 | ❌ 미구현 |
---
## 8. 모델 동기화 주의사항
### 8.1 동기화가 필요한 시점
| 이벤트 | 조치 |
|--------|------|
| API에서 마이그레이션 추가 | MNG 모델의 `$fillable`, `$casts` 업데이트 |
| API 모델에 새 관계 추가 | MNG 모델에도 동일 관계 추가 |
| API 모델에 새 상수 추가 | MNG 모델에도 동일 상수 추가 |
| MNG에서 새 헬퍼 메서드 추가 | API 모델에 반영 여부 판단 (UI 전용이면 불필요) |
### 8.2 현재 차이점
| 항목 | MNG 모델 | API 모델 |
|------|---------|---------|
| Trait | `BelongsToTenant`, `SoftDeletes` | `BelongsToTenant`, `SoftDeletes`, `Auditable`, `ModelTrait` |
| 네임스페이스 | `App\Models\Approvals` | `App\Models\Tenants` |
| 감사 로깅 | — | `Auditable` trait으로 자동 기록 |
---
## 9. React 구현 우선순위 제안
### Phase A: 기본 결재 (필수)
1. 기안함/결재함/완료함/참조함 목록 화면
2. 기안 작성 (양식 선택 → 결재선 지정 → 본문 작성 → 상신)
3. 결재 상세 조회 + 승인/반려/회수 액션
4. 결재선 에디터 (2패널 + 결재/참조 분리)
5. badge-counts (사이드바 뱃지)
### Phase B: 양식 확장
1. 지출결의서 전용 폼 (법인카드/송금/첨부파일)
2. 품의서 5종
3. 근태신청 (휴가 연동)
4. 결재서명란
### Phase C: 증명서/업무 양식
1. 재직/경력/위촉증명서 + PDF 다운로드
2. 사직서, 인감, 위임장, 의사록, 견적서, 공문서
3. 연차촉진통지서
### Phase D: 고급 기능
1. 위임 대결 (Phase 3)
2. 병렬 결재 (Phase 3)
3. 결재 통계/리포트 (Phase 4)
---
## 관련 문서
- [결재관리 개요](README.md) — 시스템 전체 개요
- [양식 기술 명세](form-types.md) — 양식별 필드, JSON 구조
- [워크플로우 상세](workflows.md) — 각 동작의 흐름
- [API 명세](api-reference.md) — 엔드포인트 목록
- [UI 화면 구성](ui-screens.md) — MNG 화면별 UI
- [DB 변경 및 모델 동기화](db-changes-and-model-sync.md) — 마이그레이션 이력
- [API 결재 연동 명세](../../frontend/api-specs/approval-api.md) — React용 API 명세
- [결재 통합 계획](../../dev/dev_plans/approval-system-unification-plan.md) — MNG→API 통합 계획
---
**최종 업데이트**: 2026-03-11

View File

@@ -1,419 +1,398 @@
# 바로빌(Barobill) 연동 시스템
> **작성일**: 2026-03-17
> **상태**: MNG 운영 중 / API SOAP 서비스 구축 완료 (2026-03-17)
---
## 1. 개요
### 1.1 목적
바로빌은 전자세금계산서, 계좌조회, 카드내역, 홈택스 연동, 카카오톡/SMS 발송 등을 제공하는 SOAP 기반 B2B 서비스다. SAM에서 재무/회계 데이터를 자동 수집하고 세금계산서를 발행하기 위해 연동한다.
### 1.2 현재 상태
| 항목 | MNG (백오피스) | API (서비스) | React (프론트) |
|------|:------------:|:----------:|:------------:|
| SOAP 연동 서비스 | ✅ 완료 (1,761줄) | **구축 완료** (49+7 메서드) | — |
| 회원사 관리 | ✅ 운영 중 | ✅ SOAP 등록/수정/상태 | 설정 페이지 |
| 카드 거래 조회 | ✅ 운영 중 | ✅ REST 16개 + SOAP 동기화 | — |
| 은행 거래 조회 | ✅ 운영 중 | ✅ REST 13개 + SOAP 동기화 | — |
| 홈택스 세금계산서 | ✅ 운영 중 | ✅ REST 13개 + upsert 동기화 | — |
| 카카오톡/SMS | ✅ 운영 중 | **SOAP 메서드 구현** (19개) | — |
| 과금 시스템 | ✅ 구현 완료 | — (모델만 존재) | — |
| 자동 동기화 | MNG 수동 | ✅ Queue Job + 스케줄러 | — |
> **현재 상태 (2026-03-17)**: API SOAP 서비스가 MNG와 100% 동등하게 구축되었다. MNG(본사 tenant_id=1)와 API(서비스 tenant_id=2~N)가 각각 독립적으로 SOAP 호출하며, 같은 DB(samdb)를 공유한다.
```
MNG (본사 전용, 수정 없음) API (서비스 고객용, 신규 구축 완료)
┌──────────────────────┐ ┌──────────────────────┐
│ BarobillService │ │ BarobillSoapService │
│ (1,761줄 그대로) │ │ (49+7 메서드) │
│ BankSyncService │ │ BankSyncService │
│ HometaxSyncService │ │ CardSyncService │
│ │ │ HometaxSyncService │
│ tenant_id=1 본사 │ │ tenant_id=2~N 고객 │
└──────────┬───────────┘ └──────────┬───────────┘
│ │
└────────── 같은 DB (samdb) ────────────┘
```
### 1.3 바로빌 공식 자료
- 개발자 센터: `https://dev.barobill.co.kr/`
- 운영 WSDL: `https://ws.baroservice.com/`
- 테스트 WSDL: `https://testws.baroservice.com/`
---
## 2. 테스트 모드 vs 운영 모드
> **경고: 개발 시 반드시 테스트 모드를 사용한다. 운영 모드는 실제 과금이 발생한다.**
### 2.1 모드 비교
| 항목 | 테스트 모드 | 운영 모드 |
|------|-----------|----------|
| WSDL 엔드포인트 | `https://testws.baroservice.com/` | `https://ws.baroservice.com/` |
| CERTKEY | 테스트용 별도 발급 | 운영용 별도 발급 |
| 과금 | ❌ 무과금 | ✅ 실제 과금 |
| 데이터 | 테스트 데이터 (초기화 가능) | 실제 세금계산서/거래 데이터 |
| 국세청 전송 | ❌ 미전송 | ✅ 실제 전송 |
| 회원사 등록 | 테스트 서버에 등록 | 운영 서버에 등록 |
| 인증서 | 테스트 인증서 사용 가능 | 실제 공동인증서 필수 |
### 2.2 모드 전환 구조
```
┌───────────────────────────────────────────────────────┐
모드 결정 흐름
├───────────────────────────────────────────────────────┤
1. BarobillMember.server_mode
│ └─ 'test' 또는 'production' (회원사별 설정)
│ │
│ 2. BarobillService.switchServerMode(isTestMode) │
│ └─ SOAP 클라이언트 재초기화 │
│ └─ initializeConfig() 호출 │
│ │
│ 3. initializeConfig() │
│ ├─ DB 우선: BarobillConfig.getActive(isTestMode) │
│ │ └─ environment = 'test' | 'production' │
│ └─ .env 폴백: │
│ ├─ test → BAROBILL_CERT_KEY_TEST │
│ └─ prod → BAROBILL_CERT_KEY_PROD │
│ │
│ 4. SOAP URL 구성 │
│ ├─ test → testws.baroservice.com/* │
└─ prod → ws.baroservice.com/* │
│ │
└───────────────────────────────────────────────────────┘
```
### 2.3 설정 우선순위
1. **DB 설정** (`barobill_configs` 테이블) — 최우선
2. **.env 환경변수** — DB 설정 없을 때 폴백
```php
// BarobillService::initializeConfig()
$dbConfig = BarobillConfig::getActive($this->isTestMode);
if ($dbConfig) {
// DB에서 cert_key, corp_num, base_url 사용
} else {
// .env에서 BAROBILL_CERT_KEY_TEST/PROD, BAROBILL_CORP_NUM 사용
}
```
### 2.4 환경변수
```bash
# .env (MNG, API 동일)
BAROBILL_CERT_KEY_TEST=<테스트 인증키>
BAROBILL_CERT_KEY_PROD=<운영 인증키>
BAROBILL_CORP_NUM=<파트너 사업자번호>
BAROBILL_TEST_MODE=true # 기본값: 테스트 모드
```
### 2.5 개발 시 주의사항
```
✅ 로컬/개발 서버: BAROBILL_TEST_MODE=true (기본값)
✅ 운영 서버: BAROBILL_TEST_MODE=false + 운영 CERTKEY
✅ 회원사별 server_mode로 개별 전환 가능
❌ 테스트 CERTKEY로 운영 서버 호출 불가 (에러 -11102)
❌ 운영 모드에서 테스트 데이터 생성 금지 (실제 과금)
```
---
## 3. 아키텍처
### 3.1 전체 데이터 흐름
```
바로빌 SOAP API (ws.baroservice.com / testws.baroservice.com)
SOAP (6개 서비스) SOAP (6개 서비스)
▼ ▼
┌──────────────────────────────┐ ┌──────────────────────────────────┐
MNG (BarobillService) │ │ API (BarobillSoapService)
본사 전용 (tenant_id=1) 서비스 고객 (tenant_id=2~N)
│ ├─ CORPSTATE 회원관리 │ │ ├─ CORPSTATE 회원관리 │
│ ├─ TI 세금계산서 │ │ ├─ TI 세금계산서
├─ BANKACCOUNT 계좌 │ │ ├─ BANKACCOUNT 계좌 │
│ ├─ CARD 카드 │ │ ├─ CARD 카드 │
├─ KAKAOTALK 알림톡 │ │ ├─ KAKAOTALK 알림톡
SMS 문자 │ │ └─ SMS 문자
└──────────┬───────────────────┘ │ + BankSyncService (동기화)
│ │ + CardSyncService (동기화)
│ │ + HometaxSyncService (동기화) │
│ + SyncBarobillDataJob (스케줄러)│
│ └──────────┬───────────────────────┘
│ │
└─────────── MySQL (samdb) ─────────┘
REST API (53개 엔드포인트)
┌────────────────────┐
│ React (사용자 UI) │
└────────────────────┘
```
### 3.2 SOAP 서비스 목록
| 서비스 | WSDL 경로 | 기능 |
|--------|----------|------|
| CORPSTATE | `/CORPSTATE.asmx` | 회원사 등록/조회/수정 |
| TI | `/TI.asmx` | 전자세금계산서 발행/조회 |
| BANKACCOUNT | `/BANKACCOUNT.asmx` | 계좌 등록/입출금 내역 조회 |
| CARD | `/CARD.asmx` | 카드 등록/사용내역 조회 |
| KAKAOTALK | `/KAKAOTALK.asmx` | 카카오톡 알림톡 발송 |
| SMS | `/SMS.asmx` | 문자 메시지 발송 |
### 3.3 인증 구조
```
모든 API 호출
└─ CERTKEY (파트너 인증키) — 필수 파라미터
├─ 바로빌 파트너 계약 시 발급
├─ 테스트/운영 별도 키
└─ BarobillService.call()에서 자동 주입
```
---
## 4. 과금 정책
### 4.1 바로빌 과금 구조 (SAM 내부 정책)
| 서비스 | 월정액 | 비고 |
|--------|-------|------|
| 계좌조회 (`bank_account`) | 10,000원/월 | 테넌트별 |
| 카드내역 (`card`) | 10,000원/월 | 테넌트별 |
| 홈택스 매입/매출 (`hometax`) | 0원 | 본사 부담 (무료 제공) |
### 4.2 추가 과금 (건별)
`BarobillPricingPolicy` 모델 기반:
| 서비스 | 무료 기본량 | 추가 과금 단위 | 추가 금액 |
|--------|-----------|-------------|----------|
| 법인카드 등록 (`card`) | 정책 설정값 | 정책 설정값 | 정책 설정값 |
| 계산서 발행 (`tax_invoice`) | 정책 설정값 | 건당 | 정책 설정값 |
| 계좌조회 수집 (`bank_account`) | 정책 설정값 | 정책 설정값 | 정책 설정값 |
> 과금 계산: `BarobillPricingPolicy::calculateBilling(usageCount)` — 무료 제공량 초과분만 과금
### 4.3 과금 처리 흐름
```
매월 1일 (배치)
└─ BarobillBillingService::processMonthlyBilling()
├─ 활성 구독 조회 (BarobillSubscription::active())
├─ 이미 과금된 기록 중복 방지
├─ BarobillBillingRecord 생성 (subscription 타입)
└─ BarobillMonthlySummary 갱신
건별 발생 시
└─ BarobillBillingService::recordUsage()
├─ BarobillBillingRecord 생성 (usage 타입)
└─ BarobillMonthlySummary 갱신
```
### 4.4 테스트 모드에서의 과금
```
✅ 테스트 모드: 바로빌 API 호출에 대한 바로빌 측 과금 없음
✅ SAM 내부 과금 시스템은 모드와 무관하게 기록 가능 (테스트용)
❌ 운영 모드: 바로빌 측 실제 과금 발생 (충전잔액 차감)
```
---
## 5. 멀티테넌트 처리
### 5.1 데이터 격리
모든 바로빌 테이블은 `tenant_id` 컬럼으로 데이터를 격리한다.
```
tenant_id=1 (코드브릿지엑스) → 본사 실무 데이터
tenant_id=N (고객사) → 해당 고객사 데이터만 접근
```
### 5.2 회원사별 설정
각 테넌트는 `barobill_members` 테이블에 독립된 바로빌 회원사 정보를 가진다:
| 컬럼 | 설명 |
|------|------|
| `tenant_id` | 테넌트 FK |
| `biz_no` | 사업자번호 (UNIQUE with tenant_id) |
| `barobill_id` | 바로빌 로그인 ID |
| `barobill_pwd` | 바로빌 비밀번호 (Laravel Encryption) |
| `server_mode` | `test` 또는 `production` (회원사별 전환) |
| `status` | `active` / `inactive` / `pending` |
### 5.3 서비스 이관 시 고려사항
```
🔴 필수: 테넌트별 CERTKEY 관리 방안 (현재는 전역 1개)
🔴 필수: 테넌트 온보딩 시 바로빌 회원 자동 등록 플로우
🟡 중요: 테스트→운영 모드 전환 프로세스 정의
🟡 중요: 과금 정책을 테넌트별로 다르게 적용 가능하도록 확장
🟢 권장: 바로빌 API 호출 로그/모니터링
```
---
## 6. 프로젝트별 코드 위치
### 6.1 MNG (`/home/aweso/sam/mng`)
| 유형 | 경로 |
|------|------|
| 서비스 | `app/Services/Barobill/BarobillService.php` (1,761줄, 핵심) |
| 서비스 | `app/Services/Barobill/HometaxSyncService.php` |
| 서비스 | `app/Services/Barobill/BarobillBillingService.php` |
| 서비스 | `app/Services/Barobill/BarobillUsageService.php` |
| 서비스 | `app/Services/Barobill/BarobillBankSyncService.php` |
| 모델 | `app/Models/Barobill/` (18개 모델) |
| 컨트롤러 | `app/Http/Controllers/Barobill/` (7개) |
| Admin API | `app/Http/Controllers/Api/Admin/Barobill/` (7개) |
| 뷰 | `resources/views/barobill/` (10개 페이지) |
### 6.2 API (`/home/aweso/sam/api`)
| 유형 | 경로 | 설명 |
|------|------|------|
| **SOAP 서비스** | `app/Services/Barobill/BarobillSoapService.php` | 6개 SOAP 서비스, 49+7 메서드 |
| **동기화** | `app/Services/Barobill/BarobillBankSyncService.php` | 은행 거래 SOAP→DB 동기화 |
| **동기화** | `app/Services/Barobill/BarobillCardSyncService.php` | 카드 거래 SOAP→DB 동기화 |
| **동기화** | `app/Services/Barobill/HometaxSyncService.php` | 홈택스 세금계산서 upsert |
| **기존 서비스** | `app/Services/BarobillService.php` | REST 설정/세금계산서 발행 (기존) |
| **Queue Job** | `app/Jobs/Barobill/SyncBarobillDataJob.php` | 자동 동기화 스케줄러 Job |
| **컨트롤러** | `app/Http/Controllers/Api/V1/BarobillSyncController.php` | SOAP 동기화/회원/인증서 API |
| **컨트롤러** | `app/Http/Controllers/Api/V1/BarobillController.php` | 기존 설정/URL API (보강됨) |
| 모델 | `app/Models/Barobill/` (15개) | 기존 모델 |
| 라우트 | `routes/api/v1/finance.php` | 기존 42개 + 신규 11개 |
| 스케줄러 | `routes/console.php` | 06:00 은행, 06:30 카드 동기화 |
### 6.3 React (`/home/aweso/sam/react`)
| 유형 | 경로 |
|------|------|
| 컴포넌트 | `src/components/settings/BarobillIntegration/` |
| 페이지 | `/settings/barobill-integration` |
---
## 7. DB 테이블 구조
### 7.1 테이블 목록
| 테이블 | 용도 | 마이그레이션 위치 |
|--------|------|-----------------|
| `barobill_members` | 회원사 정보 | API |
| `barobill_configs` | API 설정 (test/prod 분리) | API |
| `barobill_settings` | 테넌트별 서비스 설정 | API |
| `barobill_subscriptions` | 월정액 구독 | API |
| `barobill_billing_records` | 과금 기록 | API |
| `barobill_monthly_summaries` | 월별 과금 요약 | API |
| `barobill_pricing_policies` | 요금 정책 | API |
| `hometax_invoices` | 홈택스 세금계산서 | API |
| `hometax_invoice_journals` | 세금계산서 분개 | API |
| `barobill_bank_transactions` | 은행 거래 내역 | API |
| `barobill_bank_transaction_overrides` | 은행 적요 수정 | API |
| `barobill_bank_transaction_splits` | 은행 거래 분할 | API |
| `barobill_bank_sync_status` | 은행 동기화 상태 | API |
| `barobill_card_transactions` | 카드 거래 내역 | API |
| `barobill_card_transaction_splits` | 카드 거래 분할 | API |
| `barobill_card_transaction_amount_logs` | 카드 금액 수정 로그 | API |
| `barobill_card_transaction_hides` | 카드 거래 숨김 | API |
| `account_codes` | 계정과목 마스터 | API |
### 7.2 핵심 테이블 스키마
**barobill_members**:
- `tenant_id` + `biz_no` UNIQUE
- `server_mode`: `test` | `production`
- `barobill_pwd`: Laravel Encryption (복호화 가능, API 호출 시 필요)
**hometax_invoices**:
- `tenant_id` + `nts_confirm_num` + `invoice_type` UNIQUE
- `invoice_type`: `sales` | `purchase`
- `tax_type`: 1=과세, 2=영세, 3=면세
- `issue_type`: 1=정발행, 2=역발행
---
## 8. 에러 코드 매핑
| 코드 | 의미 | 대응 |
|------|------|------|
| -11101 | 사업자번호 미설정/유효하지 않음 | 회원사 정보 확인 |
| -11102 | CERTKEY 유효하지 않음 | 테스트/운영 키 확인 |
| -11103 | 인증서 만료/유효하지 않음 | 공동인증서 갱신 |
| -11104 | 미등록 사업자 | 회원사 등록 먼저 |
| -11105 | 이미 등록된 사업자 | 중복 등록 방지 |
| -26001 | 공동인증서 미등록 | 인증서 등록 안내 |
| -32001 | 사업자번호 형식 오류 | 10자리 숫자 확인 |
| -32010 | 이미 등록된 사업자번호 | 기존 회원 확인 |
| -32011 | 이미 등록된 아이디 | 다른 아이디 사용 |
---
## 9. 서비스 이관 계획
### 9.1 이관 현황 (2026-03-17 기준)
| 기능 | MNG | API 이관 | React | 상태 |
|------|:---:|:-------:|:-----:|:----:|
| SOAP 연동 서비스 (6개) | ✅ | ✅ **완료** | — | 49 메서드 100% |
| 회원사 등록/관리 | ✅ | ✅ **완료** | 설정 페이지 | API 3개 엔드포인트 |
| 테스트/운영 모드 전환 | ✅ | ✅ **완료** | — | initForMember() |
| 은행 거래 동기화 | ✅ | ✅ **완료** | — | BankSyncService |
| 카드 거래 동기화 | ✅ | ✅ **완료** | — | CardSyncService |
| 홈택스 동기화 | ✅ | ✅ **완료** | — | HometaxSyncService |
| 자동 동기화 스케줄러 | — | ✅ **완료** | — | 06:00/06:30 Job |
| 카카오톡 (15개) | ✅ | ✅ **완료** | — | SOAP 메서드 |
| SMS (4개) | ✅ | ✅ **완료** | — | SOAP 메서드 |
| 세금계산서 발행 | ✅ | ✅ 기존 REST | — | BarobillService |
| 과금 시스템 | ✅ | 모델만 | — | **미이관** |
| 카카오톡/SMS API 엔드포인트 | ✅ | — | — | **미구현** (SOAP만) |
| 온보딩 대시보드 (MNG) | — | — | — | **기획 중** |
### 9.2 남은 과제
| 우선순위 | 과제 | 설명 |
|---------|------|------|
| 🔴 P1 | 온보딩 실제 테스트 | 테스트 테넌트로 풀 시나리오 검증 |
| 🔴 P1 | 카카오톡/SMS REST API 엔드포인트 | SOAP 메서드는 구현됨, Controller+Route 추가 필요 |
| 🟡 P2 | React 바로빌 관리 화면 | 동기화 트리거, 인증서/계좌/카드 관리 |
| 🟡 P2 | MNG 온보딩 대시보드 | 테넌트별 연동 진행 상태 시각화 |
| 🟢 P3 | 과금 시스템 API 이관 | BillingService, UsageService |
| 🟢 P3 | 인증서 만료/잔액 부족 알림 | 스케줄러 기반 자동 알림 |
---
## 관련 문서
| 문서 | 설명 |
|------|------|
| [테넌트 온보딩](./tenant-onboarding.md) | 온보딩 개념 정의, 테스트→운영 전환 프로세스 |
| [API SOAP 기술 참조](./api-soap-reference.md) | API BarobillSoapService 전체 메서드, 동기화, 스케줄러 |
| [온보딩 실행 가이드](../../guides/barobill-onboarding-guide.md) | 7단계 실행 절차, API 예시, 트러블슈팅, 고객 안내 |
| [바로빌 API 명세](../../frontend/api-specs/barobill-api.md) | 카드/은행/홈택스 REST API 42개 엔드포인트 |
| [바로빌 회원 마이그레이션](../../dev/guides/barobill-members-migration.md) | 회원 데이터 이관 가이드 |
| [바로빌 카카오톡](../barobill-kakaotalk/README.md) | 카카오톡 알림톡 연동 |
| [바로빌 출시 계획](../../dev/dev_plans/barobill-service-launch-plan.md) | 4단계 출시 로드맵 |
| [재무관리](../finance/README.md) | 재무/자금관리 전체 개요 |
---
**최종 업데이트**: 2026-03-17
# 바로빌(Barobill) 연동 시스템
> **작성일**: 2026-03-17
> **상태**: MNG 운영 중 / 서비스 이관 준비
---
## 1. 개요
### 1.1 목적
바로빌은 전자세금계산서, 계좌조회, 카드내역, 홈택스 연동, 카카오톡/SMS 발송 등을 제공하는 SOAP 기반 B2B 서비스다. SAM에서 재무/회계 데이터를 자동 수집하고 세금계산서를 발행하기 위해 연동한다.
### 1.2 현재 상태
| 항목 | MNG (백오피스) | API (서비스) | React (프론트) |
|------|:------------:|:----------:|:------------:|
| SOAP 연동 서비스 | ✅ 완료 (1,761줄) | 기본 설정만 | — |
| 회원사 관리 | ✅ 운영 중 | 모델만 존재 | 설정 페이지 |
| 카드 거래 조회 | ✅ 운영 중 | ✅ REST API 16개 | — |
| 은행 거래 조회 | ✅ 운영 중 | ✅ REST API 13개 | — |
| 홈택스 세금계산서 | ✅ 운영 중 | ✅ REST API 13개 | — |
| 카카오톡/SMS | ✅ 운영 중 | | — |
| 과금 시스템 | ✅ 구현 완료 | — | — |
> **핵심**: tenant_id=1 (코드브릿지엑스 본사)에서 실무 운영 중. 서비스 이관 시 멀티테넌트 SOAP 연동이 핵심 과제.
### 1.3 바로빌 공식 자료
- 개발자 센터: `https://dev.barobill.co.kr/`
- 운영 WSDL: `https://ws.baroservice.com/`
- 테스트 WSDL: `https://testws.baroservice.com/`
---
## 2. 테스트 모드 vs 운영 모드
> **경고: 개발 시 반드시 테스트 모드를 사용한다. 운영 모드는 실제 과금이 발생한다.**
### 2.1 모드 비교
| 항목 | 테스트 모드 | 운영 모드 |
|------|-----------|----------|
| WSDL 엔드포인트 | `https://testws.baroservice.com/` | `https://ws.baroservice.com/` |
| CERTKEY | 테스트용 별도 발급 | 운영용 별도 발급 |
| 과금 | ❌ 무과금 | ✅ 실제 과금 |
| 데이터 | 테스트 데이터 (초기화 가능) | 실제 세금계산서/거래 데이터 |
| 국세청 전송 | ❌ 미전송 | ✅ 실제 전송 |
| 회원사 등록 | 테스트 서버에 등록 | 운영 서버에 등록 |
| 인증서 | 테스트 인증서 사용 가능 | 실제 공동인증서 필수 |
### 2.2 모드 전환 구조
```
┌───────────────────────────────────────────────────────┐
│ 모드 결정 흐름 │
├───────────────────────────────────────────────────────┤
│ │
│ 1. BarobillMember.server_mode │
│ └─ 'test' 또는 'production' (회원사별 설정) │
│ │
│ 2. BarobillService.switchServerMode(isTestMode) │
│ └─ SOAP 클라이언트 재초기화 │
│ └─ initializeConfig() 호출 │
│ │
│ 3. initializeConfig() │
│ ├─ DB 우선: BarobillConfig.getActive(isTestMode) │
│ │ └─ environment = 'test' | 'production' │
│ └─ .env 폴백: │
│ ├─ test → BAROBILL_CERT_KEY_TEST │
└─ prod → BAROBILL_CERT_KEY_PROD
│ │
4. SOAP URL 구성
├─ test → testws.baroservice.com/*
│ └─ prod → ws.baroservice.com/*
│ │
└───────────────────────────────────────────────────────┘
```
### 2.3 설정 우선순위
1. **DB 설정** (`barobill_configs` 테이블) — 최우선
2. **.env 환경변수** — DB 설정 없을 때 폴백
```php
// BarobillService::initializeConfig()
$dbConfig = BarobillConfig::getActive($this->isTestMode);
if ($dbConfig) {
// DB에서 cert_key, corp_num, base_url 사용
} else {
// .env에서 BAROBILL_CERT_KEY_TEST/PROD, BAROBILL_CORP_NUM 사용
}
```
### 2.4 환경변수
```bash
# .env (MNG, API 동일)
BAROBILL_CERT_KEY_TEST=<테스트 인증키>
BAROBILL_CERT_KEY_PROD=<운영 인증키>
BAROBILL_CORP_NUM=<파트너 사업자번호>
BAROBILL_TEST_MODE=true # 기본값: 테스트 모드
```
### 2.5 개발 시 주의사항
```
✅ 로컬/개발 서버: BAROBILL_TEST_MODE=true (기본값)
✅ 운영 서버: BAROBILL_TEST_MODE=false + 운영 CERTKEY
✅ 회원사별 server_mode로 개별 전환 가능
❌ 테스트 CERTKEY로 운영 서버 호출 불가 (에러 -11102)
❌ 운영 모드에서 테스트 데이터 생성 금지 (실제 과금)
```
---
## 3. 아키텍처
### 3.1 전체 데이터 흐름
```
바로빌 SOAP API (ws.baroservice.com)
│ SOAP (6개 서비스)
┌─────────────────────────────────┐
│ MNG (BarobillService) │
│ ├─ CORPSTATE — 회원사 관리 │
│ ├─ TI — 전자세금계산서 │
│ ├─ BANKACCOUNT — 계좌조회 │
│ ├─ CARD — 카드조회 │
│ ├─ KAKAOTALK — 알림톡 │
│ └─ SMS — 문자 발송 │
└──────────┬──────────────────────┘
│ MySQL 저장
┌─────────────────────────────────┐
│ MySQL (samdb)
│ ├─ barobill_members │
├─ barobill_card_transactions │
│ ├─ barobill_bank_transactions │
├─ hometax_invoices
└─ (18개 테이블)
└──────────┬──────────────────────┘
REST API
┌─────────────────────────────────┐
API (42개 엔드포인트)
/api/v1/barobill-card-*
│ ├─ /api/v1/barobill-bank-*
│ └─ /api/v1/hometax-invoices/*
└──────────┬──────────────────────┘
┌─────────────────────────────────┐
React (사용자 UI) │
│ └─ BarobillIntegration 컴포넌트
└─────────────────────────────────┘
```
### 3.2 SOAP 서비스 목록
| 서비스 | WSDL 경로 | 기능 |
|--------|----------|------|
| CORPSTATE | `/CORPSTATE.asmx` | 회원사 등록/조회/수정 |
| TI | `/TI.asmx` | 전자세금계산서 발행/조회 |
| BANKACCOUNT | `/BANKACCOUNT.asmx` | 계좌 등록/입출금 내역 조회 |
| CARD | `/CARD.asmx` | 카드 등록/사용내역 조회 |
| KAKAOTALK | `/KAKAOTALK.asmx` | 카카오톡 알림톡 발송 |
| SMS | `/SMS.asmx` | 문자 메시지 발송 |
### 3.3 인증 구조
```
모든 API 호출
└─ CERTKEY (파트너 인증키) — 필수 파라미터
├─ 바로빌 파트너 계약 시 발급
├─ 테스트/운영 별도 키
└─ BarobillService.call()에서 자동 주입
```
---
## 4. 과금 정책
### 4.1 바로빌 과금 구조 (SAM 내부 정책)
| 서비스 | 월정액 | 비고 |
|--------|-------|------|
| 계좌조회 (`bank_account`) | 10,000원/월 | 테넌트별 |
| 카드내역 (`card`) | 10,000원/월 | 테넌트별 |
| 홈택스 매입/매출 (`hometax`) | 0원 | 본사 부담 (무료 제공) |
### 4.2 추가 과금 (건별)
`BarobillPricingPolicy` 모델 기반:
| 서비스 | 무료 기본량 | 추가 과금 단위 | 추가 금액 |
|--------|-----------|-------------|----------|
| 법인카드 등록 (`card`) | 정책 설정값 | 정책 설정값 | 정책 설정값 |
| 계산서 발행 (`tax_invoice`) | 정책 설정값 | 건당 | 정책 설정값 |
| 계좌조회 수집 (`bank_account`) | 정책 설정값 | 정책 설정값 | 정책 설정값 |
> 과금 계산: `BarobillPricingPolicy::calculateBilling(usageCount)` — 무료 제공량 초과분만 과금
### 4.3 과금 처리 흐름
```
매월 1일 (배치)
└─ BarobillBillingService::processMonthlyBilling()
├─ 활성 구독 조회 (BarobillSubscription::active())
├─ 이미 과금된 기록 중복 방지
├─ BarobillBillingRecord 생성 (subscription 타입)
└─ BarobillMonthlySummary 갱신
건별 발생 시
└─ BarobillBillingService::recordUsage()
├─ BarobillBillingRecord 생성 (usage 타입)
└─ BarobillMonthlySummary 갱신
```
### 4.4 테스트 모드에서의 과금
```
✅ 테스트 모드: 바로빌 API 호출에 대한 바로빌 측 과금 없음
✅ SAM 내부 과금 시스템은 모드와 무관하게 기록 가능 (테스트용)
❌ 운영 모드: 바로빌 측 실제 과금 발생 (충전잔액 차감)
```
---
## 5. 멀티테넌트 처리
### 5.1 데이터 격리
모든 바로빌 테이블은 `tenant_id` 컬럼으로 데이터를 격리한다.
```
tenant_id=1 (코드브릿지엑스) → 본사 실무 데이터
tenant_id=N (고객사) → 해당 고객사 데이터만 접근
```
### 5.2 회원사별 설정
각 테넌트는 `barobill_members` 테이블에 독립된 바로빌 회원사 정보를 가진다:
| 컬럼 | 설명 |
|------|------|
| `tenant_id` | 테넌트 FK |
| `biz_no` | 사업자번호 (UNIQUE with tenant_id) |
| `barobill_id` | 바로빌 로그인 ID |
| `barobill_pwd` | 바로빌 비밀번호 (Laravel Encryption) |
| `server_mode` | `test` 또는 `production` (회원사별 전환) |
| `status` | `active` / `inactive` / `pending` |
### 5.3 서비스 이관 시 고려사항
```
🔴 필수: 테넌트별 CERTKEY 관리 방안 (현재는 전역 1개)
🔴 필수: 테넌트 온보딩 시 바로빌 회원 자동 등록 플로우
🟡 중요: 테스트→운영 모드 전환 프로세스 정의
🟡 중요: 과금 정책을 테넌트별로 다르게 적용 가능하도록 확장
🟢 권장: 바로빌 API 호출 로그/모니터링
```
---
## 6. 프로젝트별 코드 위치
### 6.1 MNG (`/home/aweso/sam/mng`)
| 유형 | 경로 |
|------|------|
| 서비스 | `app/Services/Barobill/BarobillService.php` (1,761줄, 핵심) |
| 서비스 | `app/Services/Barobill/HometaxSyncService.php` |
| 서비스 | `app/Services/Barobill/BarobillBillingService.php` |
| 서비스 | `app/Services/Barobill/BarobillUsageService.php` |
| 서비스 | `app/Services/Barobill/BarobillBankSyncService.php` |
| 모델 | `app/Models/Barobill/` (18개 모델) |
| 컨트롤러 | `app/Http/Controllers/Barobill/` (7개) |
| Admin API | `app/Http/Controllers/Api/Admin/Barobill/` (7개) |
| | `resources/views/barobill/` (10개 페이지) |
### 6.2 API (`/home/aweso/sam/api`)
| 유형 | 경로 |
|------|------|
| 서비스 | `app/Services/BarobillService.php` (기본 설정만) |
| 모델 | `app/Models/Barobill/` (15개) |
| 모델 | `app/Models/Tenants/BarobillSetting.php` |
| 컨트롤러 | `app/Http/Controllers/Api/V1/Barobill*Controller.php` |
| 마이그레이션 | `database/migrations/` (19개 바로빌 관련) |
### 6.3 React (`/home/aweso/sam/react`)
| 유형 | 경로 |
|------|------|
| 컴포넌트 | `src/components/settings/BarobillIntegration/` |
| 페이지 | `/settings/barobill-integration` |
---
## 7. DB 테이블 구조
### 7.1 테이블 목록
| 테이블 | 용도 | 마이그레이션 위치 |
|--------|------|-----------------|
| `barobill_members` | 회원사 정보 | API |
| `barobill_configs` | API 설정 (test/prod 분리) | API |
| `barobill_settings` | 테넌트별 서비스 설정 | API |
| `barobill_subscriptions` | 월정액 구독 | API |
| `barobill_billing_records` | 과금 기록 | API |
| `barobill_monthly_summaries` | 월별 과금 요약 | API |
| `barobill_pricing_policies` | 요금 정책 | API |
| `hometax_invoices` | 홈택스 세금계산서 | API |
| `hometax_invoice_journals` | 세금계산서 분개 | API |
| `barobill_bank_transactions` | 은행 거래 내역 | API |
| `barobill_bank_transaction_overrides` | 은행 적요 수정 | API |
| `barobill_bank_transaction_splits` | 은행 거래 분할 | API |
| `barobill_bank_sync_status` | 은행 동기화 상태 | API |
| `barobill_card_transactions` | 카드 거래 내역 | API |
| `barobill_card_transaction_splits` | 카드 거래 분할 | API |
| `barobill_card_transaction_amount_logs` | 카드 금액 수정 로그 | API |
| `barobill_card_transaction_hides` | 카드 거래 숨김 | API |
| `account_codes` | 계정과목 마스터 | API |
### 7.2 핵심 테이블 스키마
**barobill_members**:
- `tenant_id` + `biz_no` UNIQUE
- `server_mode`: `test` | `production`
- `barobill_pwd`: Laravel Encryption (복호화 가능, API 호출 시 필요)
**hometax_invoices**:
- `tenant_id` + `nts_confirm_num` + `invoice_type` UNIQUE
- `invoice_type`: `sales` | `purchase`
- `tax_type`: 1=과세, 2=영세, 3=면세
- `issue_type`: 1=정발행, 2=역발행
---
## 8. 에러 코드 매핑
| 코드 | 의미 | 대응 |
|------|------|------|
| -11101 | 사업자번호 미설정/유효하지 않음 | 회원사 정보 확인 |
| -11102 | CERTKEY 유효하지 않음 | 테스트/운영 키 확인 |
| -11103 | 인증서 만료/유효하지 않음 | 공동인증서 갱신 |
| -11104 | 미등록 사업자 | 회원사 등록 먼저 |
| -11105 | 이미 등록된 사업자 | 중복 등록 방지 |
| -26001 | 공동인증서 미등록 | 인증서 등록 안내 |
| -32001 | 사업자번호 형식 오류 | 10자리 숫자 확인 |
| -32010 | 이미 등록된 사업자번호 | 기존 회원 확인 |
| -32011 | 이미 등록된 아이디 | 다른 아이디 사용 |
---
## 9. 서비스 이관 계획
### 9.1 이관 범위
| 기능 | MNG (현재) | API 이관 | React 이관 | 우선순위 |
|------|:---------:|:-------:|:---------:|:-------:|
| SOAP 연동 서비스 | ✅ | 🔴 필수 | — | P1 |
| 회원사 등록/관리 | ✅ | 🔴 필수 | 🔴 필수 | P1 |
| 테스트/운영 모드 전환 | ✅ | 🔴 필수 | 🟡 관리자 | P1 |
| 카드 거래 동기화 | ✅ | 🟡 중요 | ✅ 완료 | P2 |
| 은행 거래 동기화 | ✅ | 🟡 중요 | — | P2 |
| 홈택스 동기화 | ✅ | 🟡 중요 | — | P2 |
| 세금계산서 발행 | ✅ | 🟡 중요 | 🟡 중요 | P2 |
| 과금 시스템 | ✅ | 🟢 권장 | 🟢 권장 | P3 |
| 카카오톡/SMS | ✅ | 🟢 권장 | — | P3 |
### 9.2 이관 시 핵심 과제
1. **SOAP 서비스 이관**: MNG의 `BarobillService` (1,761줄)를 API로 이동
2. **멀티테넌트 CERTKEY**: 테넌트별로 바로빌 파트너 계약이 필요한지, 공용 CERTKEY로 처리 가능한지 확인
3. **테스트 모드 관리**: 신규 테넌트는 테스트 모드로 시작 → 관리자가 운영 모드로 전환
4. **동기화 스케줄러**: MNG에서 실행 중인 은행/카드/홈택스 동기화를 API Queue로 이관
5. **인증서 관리**: 공동인증서 등록 URL을 테넌트 사용자에게 제공하는 플로우
---
## 관련 문서
| 문서 | 설명 |
|------|------|
| [테넌트 온보딩](./tenant-onboarding.md) | 온보딩 개념 정의, 테스트→운영 전환 프로세스 |
| [바로빌 API 명세](../../frontend/api-specs/barobill-api.md) | 카드/은행/홈택스 REST API 42개 엔드포인트 |
| [바로빌 회원 마이그레이션](../../dev/guides/barobill-members-migration.md) | 회원 데이터 이관 가이드 |
| [바로빌 카카오톡](../barobill-kakaotalk/README.md) | 카카오톡 알림톡 연동 |
| [재무관리](../finance/README.md) | 재무/자금관리 전체 개요 |
---
**최종 업데이트**: 2026-03-17

View File

@@ -1,236 +1,190 @@
# 바로빌 테넌트 온보딩 프로세스
> **작성일**: 2026-03-17
> **상태**: 설계 중 (서비스 이관 준비)
---
## 1. 온보딩(Onboarding)이란
### 1.1 정의
**온보딩**: 새로운 고객(테넌트)이 서비스에 가입하여 실제 사용을 시작하기까지의 초기 설정 과정.
SAM 바로빌 맥락에서는 **정식 계약 고객이 바로빌 연동 기능(계좌조회, 카드내역, 세금계산서 등)을 실무에서 사용할 수 있도록 초기 세팅하는 일련의 절차**를 의미한다.
### 1.2 온보딩 vs 베타테스트
| 구분 | 온보딩 | 베타테스트 |
|------|--------|----------|
| **대상** | 정식 계약 고객 | 서비스 출시 전 검증 참여자 |
| **목적** | 고객이 기능을 쓸 수 있게 초기 세팅 | 서비스 안정성/기능 검증 |
| **시점** | 고객 가입할 때마다 반복 발생 | 서비스 출시 전 1회성 |
| **테스트 모드** | 초기 세팅 확인용으로 잠깐 사용 가능 | 전체 기간 테스트 모드로 운영 |
| **데이터** | 실제 업무 데이터 | 검증용 테스트 데이터 |
| **과금** | 정식 과금 (운영 모드 전환 후) | 무과금 |
### 1.3 단계별 관계
서비스 이관 완료 후 다음 순서로 진행한다:
```
서비스 이관 (개발)
└─ 베타테스트 (출시 전 검증)
└─ 정식 출시
└─ 테넌트 온보딩 (고객 가입 시마다 반복)
```
---
## 2. 바로빌 온보딩 전체 흐름
### 2.1 단계별 프로세스
```
Phase 1: 테넌트 계약
┌──────────────────────────────────────────┐
│ 고객사 SAM 서비스 계약 체결 │
│ └─ SAM 테넌트 생성 (tenant_id 발급) │
│ └─ 바로빌 서비스 이용 여부 확인 │
└──────────────────────┬───────────────────┘
Phase 2: 바로빌 회원 등록 (테스트 모드)
┌──────────────────────────────────────────┐
│ 바로빌 회원사 등록 (BarobillService) │
│ ├─ 사업자번호, 상호, 대표자 등록 │
│ ├─ 바로빌 ID/PW 생성 │
│ ├─ server_mode = 'test' (기본값) │
│ └─ 테스트 서버에서 연동 확인 │
└──────────────────────┬───────────────────┘
Phase 3: 인증서 및 계좌/카드 연결
┌──────────────────────────────────────────┐
│ 공동인증서 등록 │
│ ├─ getCertificateRegistUrl() → 고객 직접│
│ ├─ 인증서 유효성 확인 │
│ └─ 인증서 만료일 모니터링 설정 │
│ │
│ 계좌 연결 │
│ ├─ getBankAccountScrapRequestUrl() │
│ └─ 고객이 직접 계좌 등록 │
│ │
│ 카드 연결 │
│ ├─ registCard() │
│ └─ 카드사별 등록 │
└──────────────────────┬───────────────────┘
Phase 4: 연동 검증
┌──────────────────────────────────────────┐
│ 테스트 모드에서 기능 확인 │
│ ├─ 계좌 입출금 내역 조회 확인 │
│ ├─ 카드 사용내역 조회 확인 │
│ ├─ 홈택스 세금계산서 수집 확인 │
│ └─ 문제 없으면 다음 단계 │
└──────────────────────┬───────────────────┘
Phase 5: 운영 모드 전환
┌──────────────────────────────────────────┐
│ 관리자가 server_mode → 'production' 전환 │
│ ├─ 운영 CERTKEY로 SOAP 재연결 │
│ ├─ 실제 데이터 수집 시작 │
│ └─ 과금 시작 (구독 등록) │
└──────────────────────┬───────────────────┘
Phase 6: 실무 사용 시작
┌──────────────────────────────────────────┐
│ 정기 동기화 스케줄러 활성화 │
│ ├─ 은행 거래 자동 수집 │
│ ├─ 카드 내역 자동 수집 │
│ ├─ 홈택스 세금계산서 자동 수집 │
│ └─ 월정액 과금 자동 처리 │
└──────────────────────────────────────────┘
```
### 2.2 역할 분담
| 단계 | 수행 주체 | 설명 |
|------|----------|------|
| 테넌트 생성 | SAM 관리자 | MNG에서 테넌트 생성 |
| 회원사 등록 | SAM 관리자 또는 고객 | 사업자 정보 입력 |
| 인증서 등록 | **고객 직접** | 바로빌 제공 URL에서 직접 등록 |
| 계좌/카드 등록 | **고객 직접** | 바로빌 제공 URL에서 직접 등록 |
| 연동 검증 | SAM 관리자 | 테스트 모드에서 데이터 수집 확인 |
| 운영 전환 | SAM 관리자 | `server_mode` 변경 |
---
## 3. 테스트 모드 활용
### 3.1 온보딩에서의 테스트 모드 역할
테스트 모드는 **온보딩 Phase 2~4에서 연동을 검증**하기 위해 사용한다.
```
✅ 바로빌 회원 등록이 정상적으로 되는지 확인
✅ 인증서/계좌/카드 연결이 작동하는지 확인
✅ API 호출이 정상 응답하는지 확인
❌ 실제 세금계산서 발행 (국세청 미전송)
❌ 실제 거래 데이터 수집 (테스트 데이터만)
```
### 3.2 테스트 모드 체크리스트
Phase 4 (연동 검증) 완료 기준:
- [ ] 바로빌 회원 상태: `active`
- [ ] 공동인증서: 등록됨 + 유효기간 확인
- [ ] 계좌: 1개 이상 등록, 입출금 조회 응답 정상
- [ ] 카드: 1개 이상 등록, 사용내역 조회 응답 정상
- [ ] 홈택스: 매출/매입 세금계산서 수집 응답 정상
- [ ] 에러 없이 모든 API 호출 성공
### 3.3 운영 전환 체크리스트
Phase 5 (운영 모드 전환) 전 확인:
- [ ] 테스트 모드 검증 완료
- [ ] 고객 동의 (실제 과금 시작 안내)
- [ ] 운영 CERTKEY 설정 확인
- [ ] 구독 등록 (월정액 과금 설정)
- [ ] `server_mode``production` 전환
- [ ] 운영 모드에서 첫 데이터 수집 성공 확인
---
## 4. 개발 시 주의사항
### 4.1 개발 단계에서의 테스트 모드
온보딩 프로세스와 별개로, **서비스 이관 개발 중에는 항상 테스트 모드를 사용**한다.
| 단계 | 모드 | 이유 |
|------|------|------|
| 서비스 이관 개발 | 테스트 | 코드 검증, 무과금 |
| 베타테스트 | 테스트 | 실사용 시나리오 검증, 무과금 |
| 고객 온보딩 Phase 2~4 | 테스트 | 연동 설정 확인, 무과금 |
| 고객 온보딩 Phase 5~ | **운영** | 실무 사용, 과금 시작 |
### 4.2 서비스 이관 완료 후 출시 순서
```
1. 서비스 이관 개발 완료 (테스트 모드)
2. 내부 베타테스트 (tenant_id=1, 코드브릿지엑스, 테스트 모드)
3. 외부 베타테스트 (선별 고객 2~3곳, 테스트 모드)
4. 정식 출시
5. 신규 고객 온보딩 프로세스 가동 (반복)
```
---
## 5. 구현 현황 (2026-03-17)
### 5.1 API SOAP 서비스 구축 완료
API에 MNG와 100% 동등한 SOAP 서비스가 독립 구축되었다.
| 항목 | 파일 | 상태 |
|------|------|:----:|
| SOAP 래퍼 (6개 서비스, 49 메서드) | `BarobillSoapService.php` | ✅ |
| 은행 동기화 | `BarobillBankSyncService.php` | ✅ |
| 카드 동기화 | `BarobillCardSyncService.php` | ✅ |
| 홈택스 동기화 | `HometaxSyncService.php` | ✅ |
| 동기화/회원 API (11개) | `BarobillSyncController.php` | ✅ |
| 자동 동기화 Job | `SyncBarobillDataJob.php` | ✅ |
> 상세: [API SOAP 기술 참조](./api-soap-reference.md)
### 5.2 테스트 환경 데이터
| tenant_id | 회사 | 바로빌 ID | 모드 | 테스트 적합성 |
|-----------|------|----------|------|:----------:|
| 290 | (주)주일기업 | `juil5130` | test | 즉시 가능 (Step 3~7) |
| 289 | (주)경동기업 | `kd5130` | test | 즉시 가능 |
| 291 | (미생성) | — | — | 풀 온보딩 테스트용 |
### 5.3 온보딩 테스트 시나리오
**시나리오 A: 빠른 SOAP 검증** (tenant_id=290)
```
이미 바로빌 회원이 등록된 상태.
→ Step 3(인증서 URL 확인)부터 Step 7(동기화)까지 테스트.
→ 소요: 10분
```
**시나리오 B: 풀 온보딩** (tenant_id=291 신규 생성)
```
테넌트 생성 → 바로빌 회원 등록 → 인증서/계좌/카드 → 검증 → 운영 전환
→ Step 1부터 Step 7까지 전 과정 테스트.
→ 소요: 1시간 (인증서/계좌 등록 포함)
```
---
## 관련 문서
| 문서 | 설명 |
|------|------|
| [바로빌 연동 시스템](./README.md) | 전체 구조, 테스트/운영 모드, 과금 정책 |
| [API SOAP 기술 참조](./api-soap-reference.md) | API SOAP 서비스 전체 메서드, 동기화, 스케줄러 |
| [온보딩 실행 가이드](../../guides/barobill-onboarding-guide.md) | 7단계 실행 절차, API 예시, 트러블슈팅 |
| [온보딩 실행 가이드 PPT](../../guides/barobill-onboarding-guide.pptx) | 12슬라이드 프레젠테이션 |
| [바로빌 API 명세](../../frontend/api-specs/barobill-api.md) | REST API 42개 + SOAP 11개 엔드포인트 |
| [데모 테넌트 정책](../sales/demo-tenant-policy.md) | 영업파트너 데모 테넌트 3-Tier 전략 |
---
**최종 업데이트**: 2026-03-17
# 바로빌 테넌트 온보딩 프로세스
> **작성일**: 2026-03-17
> **상태**: 설계 중 (서비스 이관 준비)
---
## 1. 온보딩(Onboarding)이란
### 1.1 정의
**온보딩**: 새로운 고객(테넌트)이 서비스에 가입하여 실제 사용을 시작하기까지의 초기 설정 과정.
SAM 바로빌 맥락에서는 **정식 계약 고객이 바로빌 연동 기능(계좌조회, 카드내역, 세금계산서 등)을 실무에서 사용할 수 있도록 초기 세팅하는 일련의 절차**를 의미한다.
### 1.2 온보딩 vs 베타테스트
| 구분 | 온보딩 | 베타테스트 |
|------|--------|----------|
| **대상** | 정식 계약 고객 | 서비스 출시 전 검증 참여자 |
| **목적** | 고객이 기능을 쓸 수 있게 초기 세팅 | 서비스 안정성/기능 검증 |
| **시점** | 고객 가입할 때마다 반복 발생 | 서비스 출시 전 1회성 |
| **테스트 모드** | 초기 세팅 확인용으로 잠깐 사용 가능 | 전체 기간 테스트 모드로 운영 |
| **데이터** | 실제 업무 데이터 | 검증용 테스트 데이터 |
| **과금** | 정식 과금 (운영 모드 전환 후) | 무과금 |
### 1.3 단계별 관계
서비스 이관 완료 후 다음 순서로 진행한다:
```
서비스 이관 (개발)
└─ 베타테스트 (출시 전 검증)
└─ 정식 출시
└─ 테넌트 온보딩 (고객 가입 시마다 반복)
```
---
## 2. 바로빌 온보딩 전체 흐름
### 2.1 단계별 프로세스
```
Phase 1: 테넌트 계약
┌──────────────────────────────────────────┐
│ 고객사 SAM 서비스 계약 체결 │
│ └─ SAM 테넌트 생성 (tenant_id 발급) │
│ └─ 바로빌 서비스 이용 여부 확인 │
└──────────────────────┬───────────────────┘
Phase 2: 바로빌 회원 등록 (테스트 모드)
┌──────────────────────────────────────────┐
│ 바로빌 회원사 등록 (BarobillService) │
│ ├─ 사업자번호, 상호, 대표자 등록 │
│ ├─ 바로빌 ID/PW 생성 │
│ ├─ server_mode = 'test' (기본값) │
│ └─ 테스트 서버에서 연동 확인 │
└──────────────────────┬───────────────────┘
Phase 3: 인증서 및 계좌/카드 연결
┌──────────────────────────────────────────┐
│ 공동인증서 등록 │
│ ├─ getCertificateRegistUrl() → 고객 직접│
│ ├─ 인증서 유효성 확인 │
│ └─ 인증서 만료일 모니터링 설정 │
│ │
│ 계좌 연결 │
│ ├─ getBankAccountScrapRequestUrl() │
│ └─ 고객이 직접 계좌 등록 │
│ │
│ 카드 연결 │
│ ├─ registCard() │
│ └─ 카드사별 등록 │
└──────────────────────┬───────────────────┘
Phase 4: 연동 검증
┌──────────────────────────────────────────┐
│ 테스트 모드에서 기능 확인 │
│ ├─ 계좌 입출금 내역 조회 확인 │
│ ├─ 카드 사용내역 조회 확인 │
│ ├─ 홈택스 세금계산서 수집 확인 │
│ └─ 문제 없으면 다음 단계 │
└──────────────────────┬───────────────────┘
Phase 5: 운영 모드 전환
┌──────────────────────────────────────────┐
│ 관리자가 server_mode → 'production' 전환 │
│ ├─ 운영 CERTKEY로 SOAP 재연결 │
│ ├─ 실제 데이터 수집 시작 │
│ └─ 과금 시작 (구독 등록) │
└──────────────────────┬───────────────────┘
Phase 6: 실무 사용 시작
┌──────────────────────────────────────────┐
│ 정기 동기화 스케줄러 활성화 │
│ ├─ 은행 거래 자동 수집 │
│ ├─ 카드 내역 자동 수집 │
│ ├─ 홈택스 세금계산서 자동 수집 │
│ └─ 월정액 과금 자동 처리 │
└──────────────────────────────────────────┘
```
### 2.2 역할 분담
| 단계 | 수행 주체 | 설명 |
|------|----------|------|
| 테넌트 생성 | SAM 관리자 | MNG에서 테넌트 생성 |
| 회원사 등록 | SAM 관리자 또는 고객 | 사업자 정보 입력 |
| 인증서 등록 | **고객 직접** | 바로빌 제공 URL에서 직접 등록 |
| 계좌/카드 등록 | **고객 직접** | 바로빌 제공 URL에서 직접 등록 |
| 연동 검증 | SAM 관리자 | 테스트 모드에서 데이터 수집 확인 |
| 운영 전환 | SAM 관리자 | `server_mode` 변경 |
---
## 3. 테스트 모드 활용
### 3.1 온보딩에서의 테스트 모드 역할
테스트 모드는 **온보딩 Phase 2~4에서 연동을 검증**하기 위해 사용한다.
```
✅ 바로빌 회원 등록이 정상적으로 되는지 확인
✅ 인증서/계좌/카드 연결이 작동하는지 확인
✅ API 호출이 정상 응답하는지 확인
❌ 실제 세금계산서 발행 (국세청 미전송)
❌ 실제 거래 데이터 수집 (테스트 데이터만)
```
### 3.2 테스트 모드 체크리스트
Phase 4 (연동 검증) 완료 기준:
- [ ] 바로빌 회원 상태: `active`
- [ ] 공동인증서: 등록됨 + 유효기간 확인
- [ ] 계좌: 1개 이상 등록, 입출금 조회 응답 정상
- [ ] 카드: 1개 이상 등록, 사용내역 조회 응답 정상
- [ ] 홈택스: 매출/매입 세금계산서 수집 응답 정상
- [ ] 에러 없이 모든 API 호출 성공
### 3.3 운영 전환 체크리스트
Phase 5 (운영 모드 전환) 전 확인:
- [ ] 테스트 모드 검증 완료
- [ ] 고객 동의 (실제 과금 시작 안내)
- [ ] 운영 CERTKEY 설정 확인
- [ ] 구독 등록 (월정액 과금 설정)
- [ ] `server_mode``production` 전환
- [ ] 운영 모드에서 첫 데이터 수집 성공 확인
---
## 4. 개발 시 주의사항
### 4.1 개발 단계에서의 테스트 모드
온보딩 프로세스와 별개로, **서비스 이관 개발 중에는 항상 테스트 모드를 사용**한다.
| 단계 | 모드 | 이유 |
|------|------|------|
| 서비스 이관 개발 | 테스트 | 코드 검증, 무과금 |
| 베타테스트 | 테스트 | 실사용 시나리오 검증, 무과금 |
| 고객 온보딩 Phase 2~4 | 테스트 | 연동 설정 확인, 무과금 |
| 고객 온보딩 Phase 5~ | **운영** | 실무 사용, 과금 시작 |
### 4.2 서비스 이관 완료 후 출시 순서
```
1. 서비스 이관 개발 완료 (테스트 모드)
2. 내부 베타테스트 (tenant_id=1, 코드브릿지엑스, 테스트 모드)
3. 외부 베타테스트 (선별 고객 2~3곳, 테스트 모드)
4. 정식 출시
5. 신규 고객 온보딩 프로세스 가동 (반복)
```
---
## 관련 문서
| 문서 | 설명 |
|------|------|
| [바로빌 연동 시스템](./README.md) | 전체 구조, 테스트/운영 모드, 과금 정책 |
| [바로빌 API 명세](../../frontend/api-specs/barobill-api.md) | REST API 42개 엔드포인트 |
| [데모 테넌트 정책](../sales/demo-tenant-policy.md) | 영업파트너 데모 테넌트 3-Tier 전략 |
---
**최종 업데이트**: 2026-03-17

File diff suppressed because it is too large Load Diff

View File

@@ -1,148 +1,148 @@
# 이메일 시스템 (Tenant Email)
> **상태**: Phase 1~2 구현 완료
> **최종 갱신**: 2026-03-12
---
## 1. 개요
SAM 멀티테넌시 환경에서 테넌트별 이메일 발송을 관리하는 시스템.
본사(코드브릿지엑스)가 MNG 관리 화면에서 각 테넌트의 메일 설정을 대행 관리한다.
**핵심 기능:**
- 테넌트별 SMTP 설정 및 발송 격리
- 한국 메일 제공자 프리셋 (Gmail, 네이버, 네이버웍스, 다음, MS365, 카페24, 가비아)
- SMTP 연결 테스트 (SmtpConnectionTester)
- 발송 기록 및 일일 쿼터 관리
- Fallback: 자체 SMTP 실패 시 플랫폼 기본 SMTP로 재시도
---
## 2. 아키텍처 (3-Layer)
```
┌─────────────────────────────────────────────────────────┐
│ Layer 1: 테넌트 메일 설정 (tenant_mail_configs) │
│ SMTP 설정, 발신자 주소, 브랜딩 정보 │
├─────────────────────────────────────────────────────────┤
│ Layer 2: 메일 발송 서비스 (TenantMailService) │
│ 테넌트 설정 자동 적용, 큐 발송, Fallback │
├─────────────────────────────────────────────────────────┤
│ Layer 3: 발송 기록 (mail_logs) │
│ 발송 이력, 상태 추적, 일일 쿼터 관리 │
└─────────────────────────────────────────────────────────┘
```
---
## 3. 테이블
| 테이블 | 설명 | 주요 컬럼 |
|--------|------|----------|
| `tenant_mail_configs` | 테넌트별 메일 설정 (1:1) | `tenant_id`, `provider`, `from_address`, `from_name`, `is_verified`, `daily_limit`, `options` |
| `mail_logs` | 발송 기록 | `tenant_id`, `mailable_type`, `to_address`, `from_address`, `subject`, `status`, `sent_at`, `options` |
**마이그레이션 위치**: `api/database/migrations/2026_03_12_*`
---
## 4. 모델
| 모델 | 위치 | Traits |
|------|------|--------|
| `TenantMailConfig` | API + MNG | BelongsToTenant, SoftDeletes, Auditable |
| `MailLog` | API + MNG | BelongsToTenant |
**`tenant_mail_configs.options` JSON 구조:**
| 키 | 설명 |
|----|------|
| `smtp.*` | SMTP 접속 정보 (host, port, username, password, encryption) |
| `preset` | 프리셋 식별자 (gmail, naver, custom 등) |
| `branding.*` | 메일 템플릿 브랜딩 (로고, 컬러, 회사명, 푸터) |
| `connection_test.*` | 마지막 SMTP 연결 테스트 결과 |
---
## 5. 서비스 (MNG)
| 서비스 | 설명 |
|--------|------|
| `TenantMailService` | 메일 발송 (설정 조회 → 쿼터 확인 → SMTP 구성 → 발송 → 로그) |
| `SmtpConnectionTester` | SMTP 연결 테스트 (TCP → TLS → AUTH → 테스트 메일) |
**에러 코드:**
| 코드 | 설명 |
|------|------|
| `CONN_REFUSED` | SMTP 서버 접속 거부 |
| `TLS_FAILED` | TLS 핸드셰이크 실패 |
| `AUTH_FAILED` | 인증 실패 (앱 비밀번호 확인) |
| `TIMEOUT` | 연결 시간 초과 |
---
## 6. MNG 파일 구조
```
mng/
├── app/Http/Controllers/System/
│ └── TenantMailConfigController.php
├── app/Services/Mail/
│ ├── TenantMailService.php
│ └── SmtpConnectionTester.php
├── config/
│ └── mail-presets.php
└── resources/views/system/tenant-mail/
├── index.blade.php (테넌트 목록)
└── edit.blade.php (설정 폼)
```
---
## 7. MNG 라우트
| Method | Path | 설명 |
|--------|------|------|
| `GET` | `/system/tenant-mail` | 테넌트 메일 설정 목록 |
| `GET` | `/system/tenant-mail/presets` | SMTP 프리셋 JSON |
| `GET` | `/system/tenant-mail/{tenant}/edit` | 설정 폼 |
| `PUT` | `/system/tenant-mail/{tenant}` | 설정 저장 |
| `POST` | `/system/tenant-mail/{tenant}/test` | SMTP 연결 테스트 |
---
## 8. 연동 방식 (3단계 전략)
| Phase | 방식 | 설명 | 상태 |
|-------|------|------|------|
| Phase 1 | 플랫폼 발송 + Reply-To | SAM 공용 SMTP로 발송, 테넌트 Reply-To 적용 | ✅ 구현 완료 |
| Phase 2 | SMTP 릴레이 + 프리셋 | 테넌트 자체 SMTP로 발송, 프리셋 자동 채움 | ✅ 구현 완료 |
| Phase 3 | OAuth2 연동 | Google/MS OAuth2 토큰 기반 발송 | 🟢 향후 |
---
## 9. 보안 규칙
```
✅ SMTP 비밀번호: encrypt()/decrypt()로 암호화 저장
✅ mail_logs에 메일 본문 저장 금지 (메타데이터만)
✅ API 응답에 SMTP 비밀번호 노출 금지 (hidden 처리)
✅ TenantScope 자동 적용 (테넌트 격리)
❌ Mail::to() 직접 호출 금지 → TenantMailService 사용
```
---
## 관련 문서
- [이메일 발송 정책](../../dev/standards/email-policy.md) — 내부 발송 아키텍처, 테이블 설계, 쿼터 관리, 서비스 설계
- [테넌트 이메일 연동 가이드](../../dev/guides/tenant-email-integration-guide.md) — SMTP 프리셋, MNG 관리 화면, 연결 테스트, 테넌트 사전 준비 안내
- [테넌트 DB 구조](../../system/database/tenants.md)
- [options JSON 컬럼 정책](../../dev/standards/options-column-policy.md)
- [전자서명 기능](../esign/README.md) — 메일 발송이 많은 주요 기능
---
**최종 업데이트**: 2026-03-12
# 이메일 시스템 (Tenant Email)
> **상태**: Phase 1~2 구현 완료
> **최종 갱신**: 2026-03-12
---
## 1. 개요
SAM 멀티테넌시 환경에서 테넌트별 이메일 발송을 관리하는 시스템.
본사(코드브릿지엑스)가 MNG 관리 화면에서 각 테넌트의 메일 설정을 대행 관리한다.
**핵심 기능:**
- 테넌트별 SMTP 설정 및 발송 격리
- 한국 메일 제공자 프리셋 (Gmail, 네이버, 네이버웍스, 다음, MS365, 카페24, 가비아)
- SMTP 연결 테스트 (SmtpConnectionTester)
- 발송 기록 및 일일 쿼터 관리
- Fallback: 자체 SMTP 실패 시 플랫폼 기본 SMTP로 재시도
---
## 2. 아키텍처 (3-Layer)
```
┌─────────────────────────────────────────────────────────┐
│ Layer 1: 테넌트 메일 설정 (tenant_mail_configs) │
│ SMTP 설정, 발신자 주소, 브랜딩 정보 │
├─────────────────────────────────────────────────────────┤
│ Layer 2: 메일 발송 서비스 (TenantMailService) │
│ 테넌트 설정 자동 적용, 큐 발송, Fallback │
├─────────────────────────────────────────────────────────┤
│ Layer 3: 발송 기록 (mail_logs) │
│ 발송 이력, 상태 추적, 일일 쿼터 관리 │
└─────────────────────────────────────────────────────────┘
```
---
## 3. 테이블
| 테이블 | 설명 | 주요 컬럼 |
|--------|------|----------|
| `tenant_mail_configs` | 테넌트별 메일 설정 (1:1) | `tenant_id`, `provider`, `from_address`, `from_name`, `is_verified`, `daily_limit`, `options` |
| `mail_logs` | 발송 기록 | `tenant_id`, `mailable_type`, `to_address`, `from_address`, `subject`, `status`, `sent_at`, `options` |
**마이그레이션 위치**: `api/database/migrations/2026_03_12_*`
---
## 4. 모델
| 모델 | 위치 | Traits |
|------|------|--------|
| `TenantMailConfig` | API + MNG | BelongsToTenant, SoftDeletes, Auditable |
| `MailLog` | API + MNG | BelongsToTenant |
**`tenant_mail_configs.options` JSON 구조:**
| 키 | 설명 |
|----|------|
| `smtp.*` | SMTP 접속 정보 (host, port, username, password, encryption) |
| `preset` | 프리셋 식별자 (gmail, naver, custom 등) |
| `branding.*` | 메일 템플릿 브랜딩 (로고, 컬러, 회사명, 푸터) |
| `connection_test.*` | 마지막 SMTP 연결 테스트 결과 |
---
## 5. 서비스 (MNG)
| 서비스 | 설명 |
|--------|------|
| `TenantMailService` | 메일 발송 (설정 조회 → 쿼터 확인 → SMTP 구성 → 발송 → 로그) |
| `SmtpConnectionTester` | SMTP 연결 테스트 (TCP → TLS → AUTH → 테스트 메일) |
**에러 코드:**
| 코드 | 설명 |
|------|------|
| `CONN_REFUSED` | SMTP 서버 접속 거부 |
| `TLS_FAILED` | TLS 핸드셰이크 실패 |
| `AUTH_FAILED` | 인증 실패 (앱 비밀번호 확인) |
| `TIMEOUT` | 연결 시간 초과 |
---
## 6. MNG 파일 구조
```
mng/
├── app/Http/Controllers/System/
│ └── TenantMailConfigController.php
├── app/Services/Mail/
│ ├── TenantMailService.php
│ └── SmtpConnectionTester.php
├── config/
│ └── mail-presets.php
└── resources/views/system/tenant-mail/
├── index.blade.php (테넌트 목록)
└── edit.blade.php (설정 폼)
```
---
## 7. MNG 라우트
| Method | Path | 설명 |
|--------|------|------|
| `GET` | `/system/tenant-mail` | 테넌트 메일 설정 목록 |
| `GET` | `/system/tenant-mail/presets` | SMTP 프리셋 JSON |
| `GET` | `/system/tenant-mail/{tenant}/edit` | 설정 폼 |
| `PUT` | `/system/tenant-mail/{tenant}` | 설정 저장 |
| `POST` | `/system/tenant-mail/{tenant}/test` | SMTP 연결 테스트 |
---
## 8. 연동 방식 (3단계 전략)
| Phase | 방식 | 설명 | 상태 |
|-------|------|------|------|
| Phase 1 | 플랫폼 발송 + Reply-To | SAM 공용 SMTP로 발송, 테넌트 Reply-To 적용 | ✅ 구현 완료 |
| Phase 2 | SMTP 릴레이 + 프리셋 | 테넌트 자체 SMTP로 발송, 프리셋 자동 채움 | ✅ 구현 완료 |
| Phase 3 | OAuth2 연동 | Google/MS OAuth2 토큰 기반 발송 | 🟢 향후 |
---
## 9. 보안 규칙
```
✅ SMTP 비밀번호: encrypt()/decrypt()로 암호화 저장
✅ mail_logs에 메일 본문 저장 금지 (메타데이터만)
✅ API 응답에 SMTP 비밀번호 노출 금지 (hidden 처리)
✅ TenantScope 자동 적용 (테넌트 격리)
❌ Mail::to() 직접 호출 금지 → TenantMailService 사용
```
---
## 관련 문서
- [이메일 발송 정책](../../dev/standards/email-policy.md) — 내부 발송 아키텍처, 테이블 설계, 쿼터 관리, 서비스 설계
- [테넌트 이메일 연동 가이드](../../dev/guides/tenant-email-integration-guide.md) — SMTP 프리셋, MNG 관리 화면, 연결 테스트, 테넌트 사전 준비 안내
- [테넌트 DB 구조](../../system/database/tenants.md)
- [options JSON 컬럼 정책](../../dev/standards/options-column-policy.md)
- [전자서명 기능](../esign/README.md) — 메일 발송이 많은 주요 기능
---
**최종 업데이트**: 2026-03-12

View File

@@ -1,489 +1,489 @@
{
"projectName": "SAM 설비관리 (Equipment Management)",
"company": "(주)코드브릿지엑스",
"author": "R&D실",
"date": "2026.03.12",
"version": "1.0",
"purpose": "생산 설비의 등록, 점검, 수리이력을 체계적으로 관리하는 설비관리 시스템의 화면 설계 기획서",
"features": [
"설비 대시보드 (현황 통계, 유형별 분포, 최근 수리이력)",
"설비 대장 CRUD (등록/조회/수정/삭제/복원)",
"6주기 점검 그리드 (일일/주간/월간/2개월/분기/반년)",
"점검 템플릿 관리 (설비별 점검항목 정의, 주기간 복사)",
"수리이력 관리 (사내/외주, 비용, 시간, 업체)",
"설비 사진 관리 (GCS 업로드, 자동 압축, 최대 10장)",
"엑셀 Import (미리보기 + 일괄등록, 이미지 포함)"
],
"effects": [
{ "icon": "📊", "title": "설비 현황 가시화", "desc": "대시보드를 통한 전체 설비 상태 실시간 파악" },
{ "icon": "🔧", "title": "정기 점검 체계화", "desc": "6주기 점검 그리드로 누락 없는 예방보전 관리" },
{ "icon": "📋", "title": "이력 추적성", "desc": "수리이력과 점검기록의 체계적 관리로 감사 대응" },
{ "icon": "📱", "title": "모바일 점검", "desc": "QR 스캔 기반 현장 모바일 점검 지원" }
],
"tocItems": [
{ "num": "01", "title": "프로젝트 개요", "desc": "설비관리 시스템 목적 및 주요 기능" },
{ "num": "02", "title": "메뉴 구조 (IA)", "desc": "Information Architecture" },
{ "num": "03", "title": "설비 대시보드", "desc": "현황 통계 및 유형별 분포" },
{ "num": "04", "title": "설비 대장 목록", "desc": "설비 목록 조회 및 필터링" },
{ "num": "05", "title": "설비 등록", "desc": "신규 설비 등록 폼" },
{ "num": "06", "title": "설비 상세", "desc": "설비 정보, 점검항목, 수리이력, 사진 탭" },
{ "num": "07", "title": "점검 그리드", "desc": "6주기 점검 현황 그리드" },
{ "num": "08", "title": "수리이력", "desc": "수리이력 목록 및 등록" },
{ "num": "09", "title": "엑셀 Import", "desc": "엑셀 파일 업로드 및 일괄 등록" }
],
"mainMenus": [
{
"title": "설비 대시보드",
"children": ["현황 통계", "유형별 분포", "최근 수리"]
},
{
"title": "설비 대장",
"children": ["목록", "등록", "상세/수정"]
},
{
"title": "점검 관리",
"children": ["점검 그리드", "점검항목 설정"]
},
{
"title": "수리이력",
"children": ["목록", "등록/수정"]
},
{
"title": "Import",
"children": ["엑셀 업로드"]
}
],
"screens": [
{
"taskName": "설비 대시보드",
"route": "/equipment",
"screenName": "설비 현황 대시보드",
"screenId": "EQP_001",
"descriptions": [
{
"title": "현황 통계 카드",
"content": "전체/가동/유휴/폐기 설비 수를 카드 형태로 표시. 각 카드 클릭 시 해당 상태 필터 적용된 목록으로 이동",
"markerX": 1.8,
"markerY": 1.5
},
{
"title": "유형별 분포 차트",
"content": "포밍기/미싱기/샤링기/V컷팅기/절곡기/프레스/드릴/기타별 설비 수를 PieChart로 시각화",
"markerX": 1.8,
"markerY": 2.8
},
{
"title": "최근 수리이력",
"content": "최근 5건의 수리이력을 테이블로 표시. 설비명, 수리일, 보전구분(사내/외주), 수리내용 포함",
"markerX": 4.2,
"markerY": 2.8
},
{
"title": "이번 달 점검 현황",
"content": "당월 점검 완료율, 미점검 설비 수 등 점검 진행 상황 요약",
"markerX": 4.2,
"markerY": 4.2
}
],
"wireframeElements": [
{"type": "rect", "x": 1.6, "y": 1.2, "w": 5.3, "h": 0.4, "text": "설비 현황 대시보드", "fontSize": 14, "bold": true, "color": "1e293b", "fill": "f8fafc"},
{"type": "rect", "x": 1.6, "y": 1.7, "w": 1.2, "h": 0.7, "fill": "0d9488", "text": "전체\n128대", "fontSize": 9, "color": "FFFFFF", "bold": true},
{"type": "rect", "x": 2.9, "y": 1.7, "w": 1.2, "h": 0.7, "fill": "22c55e", "text": "가동\n95대", "fontSize": 9, "color": "FFFFFF", "bold": true},
{"type": "rect", "x": 4.2, "y": 1.7, "w": 1.2, "h": 0.7, "fill": "f59e0b", "text": "유휴\n25대", "fontSize": 9, "color": "FFFFFF", "bold": true},
{"type": "rect", "x": 5.5, "y": 1.7, "w": 1.2, "h": 0.7, "fill": "dc2626", "text": "폐기\n8대", "fontSize": 9, "color": "FFFFFF", "bold": true},
{"type": "rect", "x": 1.6, "y": 2.6, "w": 2.5, "h": 2.2, "fill": "FFFFFF", "text": "[유형별 분포 PieChart]\n포밍기 32%\n미싱기 25%\n절곡기 18%\n기타 25%", "fontSize": 8, "color": "64748b"},
{"type": "rect", "x": 4.2, "y": 2.6, "w": 2.5, "h": 1.3, "fill": "FFFFFF", "text": "최근 수리이력\n───────────────\n포밍기-01 | 03.10 | 사내\n미싱기-03 | 03.08 | 외주\n절곡기-02 | 03.05 | 사내", "fontSize": 7, "color": "1e293b"},
{"type": "rect", "x": 4.2, "y": 4.0, "w": 2.5, "h": 0.8, "fill": "FFFFFF", "text": "이번 달 점검 현황\n완료율: 78% (94/120)\n미점검: 26건", "fontSize": 7, "color": "1e293b"}
]
},
{
"taskName": "설비 대장",
"route": "/equipment/registry",
"screenName": "설비 대장 목록",
"screenId": "EQP_002",
"descriptions": [
{
"title": "상태 필터 탭",
"content": "전체/가동(active)/유휴(idle)/폐기(disposed) 탭으로 상태별 필터링. 각 탭에 해당 건수 표시",
"markerX": 1.8,
"markerY": 1.5
},
{
"title": "검색 및 필터",
"content": "설비코드, 설비명으로 텍스트 검색. 생산라인(스라트/스크린/절곡/기타), 설비유형 드롭다운 필터",
"markerX": 1.8,
"markerY": 2.0
},
{
"title": "설비 목록 테이블",
"content": "설비코드, 설비명, 유형, 생산라인, 상태, 담당자, 구입일 컬럼. 행 클릭 시 상세 페이지로 이동",
"markerX": 1.8,
"markerY": 2.8
},
{
"title": "액션 버튼",
"content": "설비 등록 버튼, 엑셀 다운로드 버튼. UniversalListPage 템플릿 적용",
"markerX": 5.8,
"markerY": 1.5
}
],
"wireframeElements": [
{"type": "rect", "x": 1.6, "y": 1.2, "w": 5.3, "h": 0.4, "text": "설비 대장", "fontSize": 14, "bold": true, "color": "1e293b", "fill": "f8fafc"},
{"type": "rect", "x": 1.6, "y": 1.65, "w": 0.9, "h": 0.3, "fill": "0d9488", "text": "전체 128", "fontSize": 8, "color": "FFFFFF", "bold": true},
{"type": "rect", "x": 2.55, "y": 1.65, "w": 0.9, "h": 0.3, "fill": "e2e8f0", "text": "가동 95", "fontSize": 8, "color": "64748b"},
{"type": "rect", "x": 3.5, "y": 1.65, "w": 0.9, "h": 0.3, "fill": "e2e8f0", "text": "유휴 25", "fontSize": 8, "color": "64748b"},
{"type": "rect", "x": 4.45, "y": 1.65, "w": 0.9, "h": 0.3, "fill": "e2e8f0", "text": "폐기 8", "fontSize": 8, "color": "64748b"},
{"type": "rect", "x": 5.8, "y": 1.65, "w": 1.0, "h": 0.3, "fill": "0d9488", "text": "+ 설비 등록", "fontSize": 8, "color": "FFFFFF", "bold": true},
{"type": "rect", "x": 1.6, "y": 2.05, "w": 2.0, "h": 0.3, "fill": "FFFFFF", "text": "🔍 설비코드/설비명 검색", "fontSize": 8, "color": "94a3b8"},
{"type": "rect", "x": 3.7, "y": 2.05, "w": 1.2, "h": 0.3, "fill": "FFFFFF", "text": "생산라인 ▼", "fontSize": 8, "color": "64748b"},
{"type": "rect", "x": 5.0, "y": 2.05, "w": 1.2, "h": 0.3, "fill": "FFFFFF", "text": "설비유형 ▼", "fontSize": 8, "color": "64748b"},
{"type": "rect", "x": 1.6, "y": 2.5, "w": 5.3, "h": 0.35, "fill": "1e293b", "text": "설비코드 | 설비명 | 유형 | 생산라인 | 상태 | 담당자 | 구입일", "fontSize": 7, "color": "FFFFFF", "bold": true},
{"type": "rect", "x": 1.6, "y": 2.85, "w": 5.3, "h": 0.3, "fill": "FFFFFF", "text": "FM-001 | 포밍기 1호 | 포밍기 | 스라트 | 가동 | 김철수 | 2023-05-10", "fontSize": 7, "color": "1e293b"},
{"type": "rect", "x": 1.6, "y": 3.15, "w": 5.3, "h": 0.3, "fill": "f8fafc", "text": "MS-003 | 미싱기 3호 | 미싱기 | 스크린 | 가동 | 박영희 | 2024-01-15", "fontSize": 7, "color": "1e293b"},
{"type": "rect", "x": 1.6, "y": 3.45, "w": 5.3, "h": 0.3, "fill": "FFFFFF", "text": "SH-002 | 샤링기 2호 | 샤링기 | 절곡 | 유휴 | 이민수 | 2022-11-20", "fontSize": 7, "color": "1e293b"},
{"type": "rect", "x": 1.6, "y": 3.75, "w": 5.3, "h": 0.3, "fill": "f8fafc", "text": "VC-001 | V컷팅기 1호 | V컷팅기 | 스라트 | 가동 | 김철수 | 2024-06-01", "fontSize": 7, "color": "1e293b"},
{"type": "rect", "x": 1.6, "y": 4.05, "w": 5.3, "h": 0.3, "fill": "FFFFFF", "text": "PR-004 | 프레스 4호 | 프레스 | 기타 | 폐기 | - | 2019-03-22", "fontSize": 7, "color": "1e293b"},
{"type": "rect", "x": 3.0, "y": 4.5, "w": 2.0, "h": 0.3, "text": "< 1 2 3 4 5 >", "fontSize": 8, "color": "64748b"}
]
},
{
"taskName": "설비 대장",
"route": "/equipment/registry/create",
"screenName": "설비 등록",
"screenId": "EQP_003",
"descriptions": [
{
"title": "기본 정보 입력",
"content": "설비코드(tenant 내 unique), 설비명, 설비유형(드롭다운 8종), 생산라인(드롭다운 4종), 상태(active/idle/disposed)",
"markerX": 1.8,
"markerY": 1.7
},
{
"title": "담당자 지정",
"content": "정 담당자(manager_id), 부 담당자(sub_manager_id) 선택. 사용자 목록에서 검색 선택",
"markerX": 1.8,
"markerY": 2.8
},
{
"title": "구입/설치 정보",
"content": "구입일, 설치일(DatePicker), 구입가격(decimal), 내용연수(년), 메모(textarea)",
"markerX": 1.8,
"markerY": 3.6
},
{
"title": "공정 매핑",
"content": "설비가 소속된 공정을 N:N으로 선택. 주 설비 여부(is_primary) 체크박스",
"markerX": 4.5,
"markerY": 3.6
}
],
"wireframeElements": [
{"type": "rect", "x": 1.6, "y": 1.2, "w": 5.3, "h": 0.4, "text": "설비 등록", "fontSize": 14, "bold": true, "color": "1e293b", "fill": "f8fafc"},
{"type": "rect", "x": 1.6, "y": 1.7, "w": 2.5, "h": 0.35, "fill": "FFFFFF", "text": "설비코드 * FM-005", "fontSize": 8, "color": "1e293b"},
{"type": "rect", "x": 4.3, "y": 1.7, "w": 2.5, "h": 0.35, "fill": "FFFFFF", "text": "설비명 * 포밍기 5호", "fontSize": 8, "color": "1e293b"},
{"type": "rect", "x": 1.6, "y": 2.15, "w": 2.5, "h": 0.35, "fill": "FFFFFF", "text": "설비유형 포밍기 ▼", "fontSize": 8, "color": "1e293b"},
{"type": "rect", "x": 4.3, "y": 2.15, "w": 2.5, "h": 0.35, "fill": "FFFFFF", "text": "생산라인 스라트 ▼", "fontSize": 8, "color": "1e293b"},
{"type": "rect", "x": 1.6, "y": 2.6, "w": 2.5, "h": 0.35, "fill": "FFFFFF", "text": "상태 가동 ▼", "fontSize": 8, "color": "1e293b"},
{"type": "rect", "x": 1.6, "y": 3.05, "w": 2.5, "h": 0.35, "fill": "FFFFFF", "text": "정 담당자 김철수 ▼", "fontSize": 8, "color": "1e293b"},
{"type": "rect", "x": 4.3, "y": 3.05, "w": 2.5, "h": 0.35, "fill": "FFFFFF", "text": "부 담당자 박영희 ▼", "fontSize": 8, "color": "1e293b"},
{"type": "rect", "x": 1.6, "y": 3.5, "w": 1.6, "h": 0.35, "fill": "FFFFFF", "text": "구입일 2026-03-01", "fontSize": 8, "color": "1e293b"},
{"type": "rect", "x": 3.3, "y": 3.5, "w": 1.6, "h": 0.35, "fill": "FFFFFF", "text": "설치일 2026-03-10", "fontSize": 8, "color": "1e293b"},
{"type": "rect", "x": 1.6, "y": 3.95, "w": 1.6, "h": 0.35, "fill": "FFFFFF", "text": "구입가격 35,000,000", "fontSize": 8, "color": "1e293b"},
{"type": "rect", "x": 3.3, "y": 3.95, "w": 1.6, "h": 0.35, "fill": "FFFFFF", "text": "내용연수 10년", "fontSize": 8, "color": "1e293b"},
{"type": "rect", "x": 5.0, "y": 3.5, "w": 1.8, "h": 0.8, "fill": "f1f5f9", "text": "공정 매핑\n☑ 절곡공정 (주)\n☐ 포장공정\n☑ 조립공정", "fontSize": 7, "color": "1e293b"},
{"type": "rect", "x": 1.6, "y": 4.4, "w": 5.3, "h": 0.5, "fill": "FFFFFF", "text": "메모\n특이사항 입력...", "fontSize": 8, "color": "94a3b8"},
{"type": "rect", "x": 5.4, "y": 5.0, "w": 0.7, "h": 0.3, "fill": "0d9488", "text": "저장", "fontSize": 9, "color": "FFFFFF", "bold": true},
{"type": "rect", "x": 6.2, "y": 5.0, "w": 0.7, "h": 0.3, "fill": "64748b", "text": "취소", "fontSize": 9, "color": "FFFFFF"}
]
},
{
"taskName": "설비 대장",
"route": "/equipment/registry/{id}",
"screenName": "설비 상세 (기본정보 탭)",
"screenId": "EQP_004",
"descriptions": [
{
"title": "탭 구조",
"content": "기본정보 | 점검항목 | 수리이력 | 사진 4개 탭. 현재 활성 탭 하이라이트 표시",
"markerX": 1.8,
"markerY": 1.7
},
{
"title": "기본정보 그리드",
"content": "설비 기본 정보를 라벨:값 그리드로 표시. 수정 버튼 클릭 시 수정 페이지로 이동",
"markerX": 1.8,
"markerY": 2.3
},
{
"title": "상태 배지",
"content": "가동(녹색)/유휴(주황)/폐기(적색) 상태를 컬러 배지로 표시",
"markerX": 5.5,
"markerY": 1.5
},
{
"title": "액션 버튼",
"content": "수정, 삭제(SoftDelete), 복원 버튼. 삭제된 설비는 복원 버튼 표시",
"markerX": 5.5,
"markerY": 5.0
}
],
"wireframeElements": [
{"type": "rect", "x": 1.6, "y": 1.2, "w": 4.0, "h": 0.4, "text": "포밍기 1호 (FM-001)", "fontSize": 14, "bold": true, "color": "1e293b", "fill": "f8fafc"},
{"type": "rect", "x": 5.8, "y": 1.25, "w": 0.6, "h": 0.25, "fill": "22c55e", "text": "가동", "fontSize": 8, "color": "FFFFFF", "bold": true},
{"type": "rect", "x": 1.6, "y": 1.7, "w": 1.2, "h": 0.3, "fill": "0d9488", "text": "기본정보", "fontSize": 8, "color": "FFFFFF", "bold": true},
{"type": "rect", "x": 2.8, "y": 1.7, "w": 1.2, "h": 0.3, "fill": "e2e8f0", "text": "점검항목", "fontSize": 8, "color": "64748b"},
{"type": "rect", "x": 4.0, "y": 1.7, "w": 1.2, "h": 0.3, "fill": "e2e8f0", "text": "수리이력", "fontSize": 8, "color": "64748b"},
{"type": "rect", "x": 5.2, "y": 1.7, "w": 1.0, "h": 0.3, "fill": "e2e8f0", "text": "사진", "fontSize": 8, "color": "64748b"},
{"type": "rect", "x": 1.6, "y": 2.1, "w": 5.3, "h": 2.8, "fill": "FFFFFF"},
{"type": "rect", "x": 1.8, "y": 2.2, "w": 1.0, "h": 0.25, "text": "설비코드", "fontSize": 7, "color": "64748b", "bold": true},
{"type": "rect", "x": 2.8, "y": 2.2, "w": 1.5, "h": 0.25, "text": "FM-001", "fontSize": 7, "color": "1e293b"},
{"type": "rect", "x": 4.5, "y": 2.2, "w": 1.0, "h": 0.25, "text": "설비명", "fontSize": 7, "color": "64748b", "bold": true},
{"type": "rect", "x": 5.5, "y": 2.2, "w": 1.3, "h": 0.25, "text": "포밍기 1호", "fontSize": 7, "color": "1e293b"},
{"type": "rect", "x": 1.8, "y": 2.55, "w": 1.0, "h": 0.25, "text": "설비유형", "fontSize": 7, "color": "64748b", "bold": true},
{"type": "rect", "x": 2.8, "y": 2.55, "w": 1.5, "h": 0.25, "text": "포밍기", "fontSize": 7, "color": "1e293b"},
{"type": "rect", "x": 4.5, "y": 2.55, "w": 1.0, "h": 0.25, "text": "생산라인", "fontSize": 7, "color": "64748b", "bold": true},
{"type": "rect", "x": 5.5, "y": 2.55, "w": 1.3, "h": 0.25, "text": "스라트", "fontSize": 7, "color": "1e293b"},
{"type": "rect", "x": 1.8, "y": 2.9, "w": 1.0, "h": 0.25, "text": "정 담당자", "fontSize": 7, "color": "64748b", "bold": true},
{"type": "rect", "x": 2.8, "y": 2.9, "w": 1.5, "h": 0.25, "text": "김철수", "fontSize": 7, "color": "1e293b"},
{"type": "rect", "x": 4.5, "y": 2.9, "w": 1.0, "h": 0.25, "text": "부 담당자", "fontSize": 7, "color": "64748b", "bold": true},
{"type": "rect", "x": 5.5, "y": 2.9, "w": 1.3, "h": 0.25, "text": "박영희", "fontSize": 7, "color": "1e293b"},
{"type": "rect", "x": 1.8, "y": 3.25, "w": 1.0, "h": 0.25, "text": "구입일", "fontSize": 7, "color": "64748b", "bold": true},
{"type": "rect", "x": 2.8, "y": 3.25, "w": 1.5, "h": 0.25, "text": "2023-05-10", "fontSize": 7, "color": "1e293b"},
{"type": "rect", "x": 4.5, "y": 3.25, "w": 1.0, "h": 0.25, "text": "설치일", "fontSize": 7, "color": "64748b", "bold": true},
{"type": "rect", "x": 5.5, "y": 3.25, "w": 1.3, "h": 0.25, "text": "2023-06-01", "fontSize": 7, "color": "1e293b"},
{"type": "rect", "x": 1.8, "y": 3.6, "w": 1.0, "h": 0.25, "text": "구입가격", "fontSize": 7, "color": "64748b", "bold": true},
{"type": "rect", "x": 2.8, "y": 3.6, "w": 1.5, "h": 0.25, "text": "35,000,000원", "fontSize": 7, "color": "1e293b"},
{"type": "rect", "x": 4.5, "y": 3.6, "w": 1.0, "h": 0.25, "text": "내용연수", "fontSize": 7, "color": "64748b", "bold": true},
{"type": "rect", "x": 5.5, "y": 3.6, "w": 1.3, "h": 0.25, "text": "10년", "fontSize": 7, "color": "1e293b"},
{"type": "rect", "x": 5.5, "y": 4.95, "w": 0.7, "h": 0.3, "fill": "0d9488", "text": "수정", "fontSize": 9, "color": "FFFFFF", "bold": true},
{"type": "rect", "x": 6.3, "y": 4.95, "w": 0.7, "h": 0.3, "fill": "dc2626", "text": "삭제", "fontSize": 9, "color": "FFFFFF"}
]
},
{
"taskName": "설비 대장",
"route": "/equipment/registry/{id}#inspection-items",
"screenName": "설비 상세 (점검항목 탭)",
"screenId": "EQP_005",
"descriptions": [
{
"title": "주기 선택 탭",
"content": "일일/주간/월간/2개월/분기/반년 6개 주기 탭. 선택한 주기의 점검항목 표시",
"markerX": 1.8,
"markerY": 2.2
},
{
"title": "점검항목 목록",
"content": "항목번호, 점검개소, 점검항목, 시기(가동중/정지중), 점검방법 컬럼. 인라인 수정 지원",
"markerX": 1.8,
"markerY": 2.9
},
{
"title": "항목 추가/복사",
"content": "점검항목 추가 버튼으로 새 항목 생성. 주기간 복사 기능으로 다른 주기의 항목을 일괄 복사",
"markerX": 5.0,
"markerY": 2.2
},
{
"title": "항목 삭제",
"content": "각 행의 삭제 버튼으로 개별 항목 삭제. 삭제 시 확인 다이얼로그 표시",
"markerX": 6.5,
"markerY": 2.9
}
],
"wireframeElements": [
{"type": "rect", "x": 1.6, "y": 1.2, "w": 4.0, "h": 0.4, "text": "포밍기 1호 (FM-001)", "fontSize": 14, "bold": true, "color": "1e293b", "fill": "f8fafc"},
{"type": "rect", "x": 1.6, "y": 1.7, "w": 1.2, "h": 0.3, "fill": "e2e8f0", "text": "기본정보", "fontSize": 8, "color": "64748b"},
{"type": "rect", "x": 2.8, "y": 1.7, "w": 1.2, "h": 0.3, "fill": "0d9488", "text": "점검항목", "fontSize": 8, "color": "FFFFFF", "bold": true},
{"type": "rect", "x": 4.0, "y": 1.7, "w": 1.2, "h": 0.3, "fill": "e2e8f0", "text": "수리이력", "fontSize": 8, "color": "64748b"},
{"type": "rect", "x": 5.2, "y": 1.7, "w": 1.0, "h": 0.3, "fill": "e2e8f0", "text": "사진", "fontSize": 8, "color": "64748b"},
{"type": "rect", "x": 1.6, "y": 2.1, "w": 0.7, "h": 0.25, "fill": "0d9488", "text": "일일", "fontSize": 7, "color": "FFFFFF"},
{"type": "rect", "x": 2.3, "y": 2.1, "w": 0.7, "h": 0.25, "fill": "f1f5f9", "text": "주간", "fontSize": 7, "color": "64748b"},
{"type": "rect", "x": 3.0, "y": 2.1, "w": 0.7, "h": 0.25, "fill": "f1f5f9", "text": "월간", "fontSize": 7, "color": "64748b"},
{"type": "rect", "x": 3.7, "y": 2.1, "w": 0.7, "h": 0.25, "fill": "f1f5f9", "text": "2개월", "fontSize": 7, "color": "64748b"},
{"type": "rect", "x": 5.0, "y": 2.1, "w": 1.0, "h": 0.25, "fill": "0d9488", "text": "+ 항목 추가", "fontSize": 7, "color": "FFFFFF"},
{"type": "rect", "x": 6.1, "y": 2.1, "w": 0.8, "h": 0.25, "fill": "64748b", "text": "주기 복사", "fontSize": 7, "color": "FFFFFF"},
{"type": "rect", "x": 1.6, "y": 2.5, "w": 5.3, "h": 0.3, "fill": "1e293b", "text": "No | 점검개소 | 점검항목 | 시기 | 점검방법 | 삭제", "fontSize": 7, "color": "FFFFFF", "bold": true},
{"type": "rect", "x": 1.6, "y": 2.8, "w": 5.3, "h": 0.3, "fill": "FFFFFF", "text": "1 | 유압부 | 유압 호스 상태 | 가동중 | 육안 확인 후 이상 시 교체 | X", "fontSize": 7, "color": "1e293b"},
{"type": "rect", "x": 1.6, "y": 3.1, "w": 5.3, "h": 0.3, "fill": "f8fafc", "text": "2 | 전기부 | 전원 케이블 | 정지중 | 절연 저항 측정 | X", "fontSize": 7, "color": "1e293b"},
{"type": "rect", "x": 1.6, "y": 3.4, "w": 5.3, "h": 0.3, "fill": "FFFFFF", "text": "3 | 구동부 | 벨트 장력 | 가동중 | 텐션게이지 측정 | X", "fontSize": 7, "color": "1e293b"},
{"type": "rect", "x": 1.6, "y": 3.7, "w": 5.3, "h": 0.3, "fill": "f8fafc", "text": "4 | 안전장치 | 비상정지 버튼 | 정지중 | 작동 테스트 | X", "fontSize": 7, "color": "1e293b"}
]
},
{
"taskName": "점검 관리",
"route": "/equipment/inspections",
"screenName": "점검 그리드",
"screenId": "EQP_006",
"descriptions": [
{
"title": "주기/기간 선택",
"content": "6개 주기 탭(일일~반년) 선택. 일일: 년-월 선택(1~31일 열), 그 외: 년 선택(주간:1~52주, 월간:1~12월 등)",
"markerX": 1.8,
"markerY": 1.7
},
{
"title": "점검 그리드",
"content": "행: 설비x점검항목, 열: 날짜/기간. 셀 클릭 시 결과 순환(빈칸->O->X->Triangle->빈칸). 색상으로 구분",
"markerX": 1.8,
"markerY": 2.8
},
{
"title": "종합판정/노트",
"content": "설비별 종합판정(OK/NG), 수리내역, 이상내용 편집 가능. 인라인 수정 지원",
"markerX": 5.5,
"markerY": 2.8
},
{
"title": "생산라인 필터",
"content": "생산라인별 필터로 해당 라인 설비만 표시. 전체/스라트/스크린/절곡/기타",
"markerX": 5.0,
"markerY": 1.7
}
],
"wireframeElements": [
{"type": "rect", "x": 1.6, "y": 1.2, "w": 5.3, "h": 0.4, "text": "설비 점검", "fontSize": 14, "bold": true, "color": "1e293b", "fill": "f8fafc"},
{"type": "rect", "x": 1.6, "y": 1.65, "w": 0.55, "h": 0.25, "fill": "0d9488", "text": "일일", "fontSize": 7, "color": "FFFFFF", "bold": true},
{"type": "rect", "x": 2.15, "y": 1.65, "w": 0.55, "h": 0.25, "fill": "f1f5f9", "text": "주간", "fontSize": 7, "color": "64748b"},
{"type": "rect", "x": 2.7, "y": 1.65, "w": 0.55, "h": 0.25, "fill": "f1f5f9", "text": "월간", "fontSize": 7, "color": "64748b"},
{"type": "rect", "x": 3.25, "y": 1.65, "w": 0.55, "h": 0.25, "fill": "f1f5f9", "text": "2개월", "fontSize": 7, "color": "64748b"},
{"type": "rect", "x": 3.8, "y": 1.65, "w": 0.55, "h": 0.25, "fill": "f1f5f9", "text": "분기", "fontSize": 7, "color": "64748b"},
{"type": "rect", "x": 4.35, "y": 1.65, "w": 0.55, "h": 0.25, "fill": "f1f5f9", "text": "반년", "fontSize": 7, "color": "64748b"},
{"type": "rect", "x": 5.0, "y": 1.65, "w": 1.0, "h": 0.25, "fill": "FFFFFF", "text": "2026-03 ▼", "fontSize": 7, "color": "1e293b"},
{"type": "rect", "x": 6.1, "y": 1.65, "w": 0.8, "h": 0.25, "fill": "FFFFFF", "text": "전체 ▼", "fontSize": 7, "color": "1e293b"},
{"type": "rect", "x": 1.6, "y": 2.0, "w": 5.3, "h": 0.35, "fill": "1e293b", "text": "설비 | 항목 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | ... | 판정", "fontSize": 6, "color": "FFFFFF", "bold": true},
{"type": "rect", "x": 1.6, "y": 2.35, "w": 5.3, "h": 0.55, "fill": "FFFFFF", "text": "포밍기 유압호스 O O O - - O X △ ... OK\n1호 벨트장력 O O O - - O O O ... OK", "fontSize": 6, "color": "1e293b"},
{"type": "rect", "x": 1.6, "y": 2.9, "w": 5.3, "h": 0.55, "fill": "f8fafc", "text": "미싱기 전원케이블 O O X - - △ O O ... NG\n3호 안전장치 O O O - - O O O ... OK", "fontSize": 6, "color": "1e293b"},
{"type": "rect", "x": 1.6, "y": 3.45, "w": 5.3, "h": 0.55, "fill": "FFFFFF", "text": "샤링기 유압압력 O O O - - O O O ... OK\n2호 칼날마모 O X △ - - O O O ... OK", "fontSize": 6, "color": "1e293b"},
{"type": "rect", "x": 1.6, "y": 4.1, "w": 5.3, "h": 0.5, "fill": "f1f5f9", "text": "범례: O = 양호(good) X = 불량(bad) △ = 수리(repaired) - = 휴일/주말\n셀 클릭 시: 빈칸 -> O -> X -> △ -> 빈칸 순환", "fontSize": 7, "color": "64748b"}
]
},
{
"taskName": "수리이력",
"route": "/equipment/repairs",
"screenName": "수리이력 목록",
"screenId": "EQP_007",
"descriptions": [
{
"title": "필터 영역",
"content": "설비 선택(드롭다운), 보전구분(사내/외주), 날짜 범위(시작일~종료일), 텍스트 검색(수리내용)",
"markerX": 1.8,
"markerY": 1.7
},
{
"title": "수리이력 테이블",
"content": "수리일, 설비명, 보전구분, 수리내용, 수리시간, 비용, 수리자/업체 컬럼. 행 클릭 시 수정 모달",
"markerX": 1.8,
"markerY": 2.6
},
{
"title": "수리이력 등록",
"content": "수리이력 등록 버튼 클릭 시 등록 폼(모달 또는 별도 페이지)으로 이동",
"markerX": 5.8,
"markerY": 1.3
},
{
"title": "비용 집계",
"content": "조회된 수리이력의 총 비용, 사내/외주 비용 비율 등 하단 요약 표시",
"markerX": 1.8,
"markerY": 4.5
}
],
"wireframeElements": [
{"type": "rect", "x": 1.6, "y": 1.2, "w": 5.3, "h": 0.4, "text": "수리이력", "fontSize": 14, "bold": true, "color": "1e293b", "fill": "f8fafc"},
{"type": "rect", "x": 5.8, "y": 1.25, "w": 1.0, "h": 0.3, "fill": "0d9488", "text": "+ 수리 등록", "fontSize": 8, "color": "FFFFFF", "bold": true},
{"type": "rect", "x": 1.6, "y": 1.7, "w": 1.5, "h": 0.3, "fill": "FFFFFF", "text": "설비 선택 ▼", "fontSize": 8, "color": "64748b"},
{"type": "rect", "x": 3.2, "y": 1.7, "w": 1.0, "h": 0.3, "fill": "FFFFFF", "text": "보전구분 ▼", "fontSize": 8, "color": "64748b"},
{"type": "rect", "x": 4.3, "y": 1.7, "w": 1.2, "h": 0.3, "fill": "FFFFFF", "text": "2026-01 ~ 2026-03", "fontSize": 7, "color": "64748b"},
{"type": "rect", "x": 5.6, "y": 1.7, "w": 1.2, "h": 0.3, "fill": "FFFFFF", "text": "🔍 검색", "fontSize": 8, "color": "94a3b8"},
{"type": "rect", "x": 1.6, "y": 2.15, "w": 5.3, "h": 0.35, "fill": "1e293b", "text": "수리일 | 설비명 | 보전구분 | 수리내용 | 시간 | 비용 | 수리자/업체", "fontSize": 7, "color": "FFFFFF", "bold": true},
{"type": "rect", "x": 1.6, "y": 2.5, "w": 5.3, "h": 0.3, "fill": "FFFFFF", "text": "2026-03-10 | 포밍기 1호 | 사내 | 유압호스 교체 | 2.0h | 150,000원 | 김철수", "fontSize": 7, "color": "1e293b"},
{"type": "rect", "x": 1.6, "y": 2.8, "w": 5.3, "h": 0.3, "fill": "f8fafc", "text": "2026-03-08 | 미싱기 3호 | 외주 | 모터 오버홀 | 8.0h | 2,500,000원 | ABC기계", "fontSize": 7, "color": "1e293b"},
{"type": "rect", "x": 1.6, "y": 3.1, "w": 5.3, "h": 0.3, "fill": "FFFFFF", "text": "2026-03-05 | 샤링기 2호 | 사내 | 칼날 교체 | 1.5h | 85,000원 | 이민수", "fontSize": 7, "color": "1e293b"},
{"type": "rect", "x": 1.6, "y": 3.4, "w": 5.3, "h": 0.3, "fill": "f8fafc", "text": "2026-02-28 | 절곡기 1호 | 외주 | 유압실린더 교체 | 4.0h | 1,200,000원 | XYZ설비", "fontSize": 7, "color": "1e293b"},
{"type": "rect", "x": 3.0, "y": 3.9, "w": 2.0, "h": 0.3, "text": "< 1 2 3 >", "fontSize": 8, "color": "64748b"},
{"type": "rect", "x": 1.6, "y": 4.3, "w": 5.3, "h": 0.4, "fill": "f1f5f9", "text": "총 수리비용: 3,935,000원 | 사내: 235,000원 (6%) | 외주: 3,700,000원 (94%)", "fontSize": 8, "color": "1e293b", "bold": true}
]
},
{
"taskName": "수리이력",
"route": "/equipment/repairs/create",
"screenName": "수리이력 등록",
"screenId": "EQP_008",
"descriptions": [
{
"title": "설비 선택",
"content": "수리 대상 설비를 드롭다운에서 선택. 설비코드+설비명 표시. 필수 입력",
"markerX": 1.8,
"markerY": 1.7
},
{
"title": "수리 정보",
"content": "수리일(DatePicker), 보전구분(사내/외주 라디오), 수리시간(시간 단위), 비용(원)",
"markerX": 1.8,
"markerY": 2.3
},
{
"title": "수리 상세",
"content": "수리내용(textarea), 수리자(사내 선택) 또는 외주업체명(텍스트 입력). 보전구분에 따라 전환",
"markerX": 1.8,
"markerY": 3.3
}
],
"wireframeElements": [
{"type": "rect", "x": 1.6, "y": 1.2, "w": 5.3, "h": 0.4, "text": "수리이력 등록", "fontSize": 14, "bold": true, "color": "1e293b", "fill": "f8fafc"},
{"type": "rect", "x": 1.6, "y": 1.7, "w": 5.3, "h": 0.35, "fill": "FFFFFF", "text": "설비 * FM-001 포밍기 1호 ▼", "fontSize": 8, "color": "1e293b"},
{"type": "rect", "x": 1.6, "y": 2.15, "w": 2.5, "h": 0.35, "fill": "FFFFFF", "text": "수리일 * 2026-03-12", "fontSize": 8, "color": "1e293b"},
{"type": "rect", "x": 4.3, "y": 2.15, "w": 2.5, "h": 0.35, "fill": "FFFFFF", "text": "보전구분 * ● 사내 ○ 외주", "fontSize": 8, "color": "1e293b"},
{"type": "rect", "x": 1.6, "y": 2.6, "w": 2.5, "h": 0.35, "fill": "FFFFFF", "text": "수리시간 2.0 시간", "fontSize": 8, "color": "1e293b"},
{"type": "rect", "x": 4.3, "y": 2.6, "w": 2.5, "h": 0.35, "fill": "FFFFFF", "text": "수리비용 150,000 원", "fontSize": 8, "color": "1e293b"},
{"type": "rect", "x": 1.6, "y": 3.05, "w": 2.5, "h": 0.35, "fill": "FFFFFF", "text": "수리자 김철수 ▼", "fontSize": 8, "color": "1e293b"},
{"type": "rect", "x": 1.6, "y": 3.5, "w": 5.3, "h": 1.0, "fill": "FFFFFF", "text": "수리내용\n유압호스 노후로 인한 교체 작업.\n기존 호스 균열 발견, 동일 규격 신품으로 교체 완료.\n압력 테스트 정상 확인.", "fontSize": 8, "color": "1e293b"},
{"type": "rect", "x": 5.4, "y": 4.7, "w": 0.7, "h": 0.3, "fill": "0d9488", "text": "저장", "fontSize": 9, "color": "FFFFFF", "bold": true},
{"type": "rect", "x": 6.2, "y": 4.7, "w": 0.7, "h": 0.3, "fill": "64748b", "text": "취소", "fontSize": 9, "color": "FFFFFF"}
]
},
{
"taskName": "Import",
"route": "/equipment/import",
"screenName": "엑셀 Import",
"screenId": "EQP_009",
"descriptions": [
{
"title": "파일 업로드",
"content": "엑셀 파일(.xlsx) 드래그&드롭 또는 파일 선택. 업로드 후 자동으로 미리보기 단계로 전환",
"markerX": 1.8,
"markerY": 1.8
},
{
"title": "미리보기 테이블",
"content": "파싱된 데이터를 테이블로 표시. 한글/영문 헤더 자동 매핑. 오류 행 빨간색 표시. 이미지(Drawing) 자동 추출 표시",
"markerX": 1.8,
"markerY": 2.7
},
{
"title": "중복 처리 옵션",
"content": "동일 설비코드 존재 시: 건너뜀(skip) 또는 덮어쓰기(overwrite) 선택. 라디오 버튼",
"markerX": 1.8,
"markerY": 4.2
},
{
"title": "Import 실행",
"content": "Import 실행 버튼 클릭 시 일괄 등록. 결과 요약(성공/실패/건너뜀 건수) 표시",
"markerX": 5.8,
"markerY": 4.2
}
],
"wireframeElements": [
{"type": "rect", "x": 1.6, "y": 1.2, "w": 5.3, "h": 0.4, "text": "엑셀 Import", "fontSize": 14, "bold": true, "color": "1e293b", "fill": "f8fafc"},
{"type": "rect", "x": 1.6, "y": 1.7, "w": 5.3, "h": 0.8, "fill": "f1f5f9", "text": "📁 엑셀 파일을 드래그하거나 클릭하여 선택하세요\n(.xlsx 형식, 최대 10MB)", "fontSize": 9, "color": "64748b"},
{"type": "rect", "x": 1.6, "y": 2.6, "w": 5.3, "h": 0.3, "fill": "1e293b", "text": "설비코드 | 설비명 | 유형 | 라인 | 상태 | 구입일 | 이미지", "fontSize": 7, "color": "FFFFFF", "bold": true},
{"type": "rect", "x": 1.6, "y": 2.9, "w": 5.3, "h": 0.3, "fill": "FFFFFF", "text": "FM-006 | 포밍기 6호 | 포밍기 | 스라트 | 가동 | 2026-01 | [img]", "fontSize": 7, "color": "1e293b"},
{"type": "rect", "x": 1.6, "y": 3.2, "w": 5.3, "h": 0.3, "fill": "f8fafc", "text": "MS-005 | 미싱기 5호 | 미싱기 | 스크린 | 가동 | 2025-11 | [img]", "fontSize": 7, "color": "1e293b"},
{"type": "rect", "x": 1.6, "y": 3.5, "w": 5.3, "h": 0.3, "fill": "fef2f2", "text": "FM-001 | 포밍기 1호 | 포밍기 | 스라트 | 가동 | 2023-05 | - (중복!)", "fontSize": 7, "color": "dc2626"},
{"type": "rect", "x": 1.6, "y": 3.9, "w": 3.0, "h": 0.35, "fill": "f1f5f9", "text": "중복 처리: ● 건너뜀(skip) ○ 덮어쓰기(overwrite)", "fontSize": 8, "color": "1e293b"},
{"type": "rect", "x": 1.6, "y": 4.35, "w": 3.0, "h": 0.3, "text": "총 3건 | 신규: 2건 | 중복: 1건 | 오류: 0건", "fontSize": 8, "color": "64748b"},
{"type": "rect", "x": 5.8, "y": 4.35, "w": 1.0, "h": 0.3, "fill": "0d9488", "text": "Import 실행", "fontSize": 8, "color": "FFFFFF", "bold": true}
]
}
]
}
{
"projectName": "SAM 설비관리 (Equipment Management)",
"company": "(주)코드브릿지엑스",
"author": "R&D실",
"date": "2026.03.12",
"version": "1.0",
"purpose": "생산 설비의 등록, 점검, 수리이력을 체계적으로 관리하는 설비관리 시스템의 화면 설계 기획서",
"features": [
"설비 대시보드 (현황 통계, 유형별 분포, 최근 수리이력)",
"설비 대장 CRUD (등록/조회/수정/삭제/복원)",
"6주기 점검 그리드 (일일/주간/월간/2개월/분기/반년)",
"점검 템플릿 관리 (설비별 점검항목 정의, 주기간 복사)",
"수리이력 관리 (사내/외주, 비용, 시간, 업체)",
"설비 사진 관리 (GCS 업로드, 자동 압축, 최대 10장)",
"엑셀 Import (미리보기 + 일괄등록, 이미지 포함)"
],
"effects": [
{ "icon": "📊", "title": "설비 현황 가시화", "desc": "대시보드를 통한 전체 설비 상태 실시간 파악" },
{ "icon": "🔧", "title": "정기 점검 체계화", "desc": "6주기 점검 그리드로 누락 없는 예방보전 관리" },
{ "icon": "📋", "title": "이력 추적성", "desc": "수리이력과 점검기록의 체계적 관리로 감사 대응" },
{ "icon": "📱", "title": "모바일 점검", "desc": "QR 스캔 기반 현장 모바일 점검 지원" }
],
"tocItems": [
{ "num": "01", "title": "프로젝트 개요", "desc": "설비관리 시스템 목적 및 주요 기능" },
{ "num": "02", "title": "메뉴 구조 (IA)", "desc": "Information Architecture" },
{ "num": "03", "title": "설비 대시보드", "desc": "현황 통계 및 유형별 분포" },
{ "num": "04", "title": "설비 대장 목록", "desc": "설비 목록 조회 및 필터링" },
{ "num": "05", "title": "설비 등록", "desc": "신규 설비 등록 폼" },
{ "num": "06", "title": "설비 상세", "desc": "설비 정보, 점검항목, 수리이력, 사진 탭" },
{ "num": "07", "title": "점검 그리드", "desc": "6주기 점검 현황 그리드" },
{ "num": "08", "title": "수리이력", "desc": "수리이력 목록 및 등록" },
{ "num": "09", "title": "엑셀 Import", "desc": "엑셀 파일 업로드 및 일괄 등록" }
],
"mainMenus": [
{
"title": "설비 대시보드",
"children": ["현황 통계", "유형별 분포", "최근 수리"]
},
{
"title": "설비 대장",
"children": ["목록", "등록", "상세/수정"]
},
{
"title": "점검 관리",
"children": ["점검 그리드", "점검항목 설정"]
},
{
"title": "수리이력",
"children": ["목록", "등록/수정"]
},
{
"title": "Import",
"children": ["엑셀 업로드"]
}
],
"screens": [
{
"taskName": "설비 대시보드",
"route": "/equipment",
"screenName": "설비 현황 대시보드",
"screenId": "EQP_001",
"descriptions": [
{
"title": "현황 통계 카드",
"content": "전체/가동/유휴/폐기 설비 수를 카드 형태로 표시. 각 카드 클릭 시 해당 상태 필터 적용된 목록으로 이동",
"markerX": 1.8,
"markerY": 1.5
},
{
"title": "유형별 분포 차트",
"content": "포밍기/미싱기/샤링기/V컷팅기/절곡기/프레스/드릴/기타별 설비 수를 PieChart로 시각화",
"markerX": 1.8,
"markerY": 2.8
},
{
"title": "최근 수리이력",
"content": "최근 5건의 수리이력을 테이블로 표시. 설비명, 수리일, 보전구분(사내/외주), 수리내용 포함",
"markerX": 4.2,
"markerY": 2.8
},
{
"title": "이번 달 점검 현황",
"content": "당월 점검 완료율, 미점검 설비 수 등 점검 진행 상황 요약",
"markerX": 4.2,
"markerY": 4.2
}
],
"wireframeElements": [
{"type": "rect", "x": 1.6, "y": 1.2, "w": 5.3, "h": 0.4, "text": "설비 현황 대시보드", "fontSize": 14, "bold": true, "color": "1e293b", "fill": "f8fafc"},
{"type": "rect", "x": 1.6, "y": 1.7, "w": 1.2, "h": 0.7, "fill": "0d9488", "text": "전체\n128대", "fontSize": 9, "color": "FFFFFF", "bold": true},
{"type": "rect", "x": 2.9, "y": 1.7, "w": 1.2, "h": 0.7, "fill": "22c55e", "text": "가동\n95대", "fontSize": 9, "color": "FFFFFF", "bold": true},
{"type": "rect", "x": 4.2, "y": 1.7, "w": 1.2, "h": 0.7, "fill": "f59e0b", "text": "유휴\n25대", "fontSize": 9, "color": "FFFFFF", "bold": true},
{"type": "rect", "x": 5.5, "y": 1.7, "w": 1.2, "h": 0.7, "fill": "dc2626", "text": "폐기\n8대", "fontSize": 9, "color": "FFFFFF", "bold": true},
{"type": "rect", "x": 1.6, "y": 2.6, "w": 2.5, "h": 2.2, "fill": "FFFFFF", "text": "[유형별 분포 PieChart]\n포밍기 32%\n미싱기 25%\n절곡기 18%\n기타 25%", "fontSize": 8, "color": "64748b"},
{"type": "rect", "x": 4.2, "y": 2.6, "w": 2.5, "h": 1.3, "fill": "FFFFFF", "text": "최근 수리이력\n───────────────\n포밍기-01 | 03.10 | 사내\n미싱기-03 | 03.08 | 외주\n절곡기-02 | 03.05 | 사내", "fontSize": 7, "color": "1e293b"},
{"type": "rect", "x": 4.2, "y": 4.0, "w": 2.5, "h": 0.8, "fill": "FFFFFF", "text": "이번 달 점검 현황\n완료율: 78% (94/120)\n미점검: 26건", "fontSize": 7, "color": "1e293b"}
]
},
{
"taskName": "설비 대장",
"route": "/equipment/registry",
"screenName": "설비 대장 목록",
"screenId": "EQP_002",
"descriptions": [
{
"title": "상태 필터 탭",
"content": "전체/가동(active)/유휴(idle)/폐기(disposed) 탭으로 상태별 필터링. 각 탭에 해당 건수 표시",
"markerX": 1.8,
"markerY": 1.5
},
{
"title": "검색 및 필터",
"content": "설비코드, 설비명으로 텍스트 검색. 생산라인(스라트/스크린/절곡/기타), 설비유형 드롭다운 필터",
"markerX": 1.8,
"markerY": 2.0
},
{
"title": "설비 목록 테이블",
"content": "설비코드, 설비명, 유형, 생산라인, 상태, 담당자, 구입일 컬럼. 행 클릭 시 상세 페이지로 이동",
"markerX": 1.8,
"markerY": 2.8
},
{
"title": "액션 버튼",
"content": "설비 등록 버튼, 엑셀 다운로드 버튼. UniversalListPage 템플릿 적용",
"markerX": 5.8,
"markerY": 1.5
}
],
"wireframeElements": [
{"type": "rect", "x": 1.6, "y": 1.2, "w": 5.3, "h": 0.4, "text": "설비 대장", "fontSize": 14, "bold": true, "color": "1e293b", "fill": "f8fafc"},
{"type": "rect", "x": 1.6, "y": 1.65, "w": 0.9, "h": 0.3, "fill": "0d9488", "text": "전체 128", "fontSize": 8, "color": "FFFFFF", "bold": true},
{"type": "rect", "x": 2.55, "y": 1.65, "w": 0.9, "h": 0.3, "fill": "e2e8f0", "text": "가동 95", "fontSize": 8, "color": "64748b"},
{"type": "rect", "x": 3.5, "y": 1.65, "w": 0.9, "h": 0.3, "fill": "e2e8f0", "text": "유휴 25", "fontSize": 8, "color": "64748b"},
{"type": "rect", "x": 4.45, "y": 1.65, "w": 0.9, "h": 0.3, "fill": "e2e8f0", "text": "폐기 8", "fontSize": 8, "color": "64748b"},
{"type": "rect", "x": 5.8, "y": 1.65, "w": 1.0, "h": 0.3, "fill": "0d9488", "text": "+ 설비 등록", "fontSize": 8, "color": "FFFFFF", "bold": true},
{"type": "rect", "x": 1.6, "y": 2.05, "w": 2.0, "h": 0.3, "fill": "FFFFFF", "text": "🔍 설비코드/설비명 검색", "fontSize": 8, "color": "94a3b8"},
{"type": "rect", "x": 3.7, "y": 2.05, "w": 1.2, "h": 0.3, "fill": "FFFFFF", "text": "생산라인 ▼", "fontSize": 8, "color": "64748b"},
{"type": "rect", "x": 5.0, "y": 2.05, "w": 1.2, "h": 0.3, "fill": "FFFFFF", "text": "설비유형 ▼", "fontSize": 8, "color": "64748b"},
{"type": "rect", "x": 1.6, "y": 2.5, "w": 5.3, "h": 0.35, "fill": "1e293b", "text": "설비코드 | 설비명 | 유형 | 생산라인 | 상태 | 담당자 | 구입일", "fontSize": 7, "color": "FFFFFF", "bold": true},
{"type": "rect", "x": 1.6, "y": 2.85, "w": 5.3, "h": 0.3, "fill": "FFFFFF", "text": "FM-001 | 포밍기 1호 | 포밍기 | 스라트 | 가동 | 김철수 | 2023-05-10", "fontSize": 7, "color": "1e293b"},
{"type": "rect", "x": 1.6, "y": 3.15, "w": 5.3, "h": 0.3, "fill": "f8fafc", "text": "MS-003 | 미싱기 3호 | 미싱기 | 스크린 | 가동 | 박영희 | 2024-01-15", "fontSize": 7, "color": "1e293b"},
{"type": "rect", "x": 1.6, "y": 3.45, "w": 5.3, "h": 0.3, "fill": "FFFFFF", "text": "SH-002 | 샤링기 2호 | 샤링기 | 절곡 | 유휴 | 이민수 | 2022-11-20", "fontSize": 7, "color": "1e293b"},
{"type": "rect", "x": 1.6, "y": 3.75, "w": 5.3, "h": 0.3, "fill": "f8fafc", "text": "VC-001 | V컷팅기 1호 | V컷팅기 | 스라트 | 가동 | 김철수 | 2024-06-01", "fontSize": 7, "color": "1e293b"},
{"type": "rect", "x": 1.6, "y": 4.05, "w": 5.3, "h": 0.3, "fill": "FFFFFF", "text": "PR-004 | 프레스 4호 | 프레스 | 기타 | 폐기 | - | 2019-03-22", "fontSize": 7, "color": "1e293b"},
{"type": "rect", "x": 3.0, "y": 4.5, "w": 2.0, "h": 0.3, "text": "< 1 2 3 4 5 >", "fontSize": 8, "color": "64748b"}
]
},
{
"taskName": "설비 대장",
"route": "/equipment/registry/create",
"screenName": "설비 등록",
"screenId": "EQP_003",
"descriptions": [
{
"title": "기본 정보 입력",
"content": "설비코드(tenant 내 unique), 설비명, 설비유형(드롭다운 8종), 생산라인(드롭다운 4종), 상태(active/idle/disposed)",
"markerX": 1.8,
"markerY": 1.7
},
{
"title": "담당자 지정",
"content": "정 담당자(manager_id), 부 담당자(sub_manager_id) 선택. 사용자 목록에서 검색 선택",
"markerX": 1.8,
"markerY": 2.8
},
{
"title": "구입/설치 정보",
"content": "구입일, 설치일(DatePicker), 구입가격(decimal), 내용연수(년), 메모(textarea)",
"markerX": 1.8,
"markerY": 3.6
},
{
"title": "공정 매핑",
"content": "설비가 소속된 공정을 N:N으로 선택. 주 설비 여부(is_primary) 체크박스",
"markerX": 4.5,
"markerY": 3.6
}
],
"wireframeElements": [
{"type": "rect", "x": 1.6, "y": 1.2, "w": 5.3, "h": 0.4, "text": "설비 등록", "fontSize": 14, "bold": true, "color": "1e293b", "fill": "f8fafc"},
{"type": "rect", "x": 1.6, "y": 1.7, "w": 2.5, "h": 0.35, "fill": "FFFFFF", "text": "설비코드 * FM-005", "fontSize": 8, "color": "1e293b"},
{"type": "rect", "x": 4.3, "y": 1.7, "w": 2.5, "h": 0.35, "fill": "FFFFFF", "text": "설비명 * 포밍기 5호", "fontSize": 8, "color": "1e293b"},
{"type": "rect", "x": 1.6, "y": 2.15, "w": 2.5, "h": 0.35, "fill": "FFFFFF", "text": "설비유형 포밍기 ▼", "fontSize": 8, "color": "1e293b"},
{"type": "rect", "x": 4.3, "y": 2.15, "w": 2.5, "h": 0.35, "fill": "FFFFFF", "text": "생산라인 스라트 ▼", "fontSize": 8, "color": "1e293b"},
{"type": "rect", "x": 1.6, "y": 2.6, "w": 2.5, "h": 0.35, "fill": "FFFFFF", "text": "상태 가동 ▼", "fontSize": 8, "color": "1e293b"},
{"type": "rect", "x": 1.6, "y": 3.05, "w": 2.5, "h": 0.35, "fill": "FFFFFF", "text": "정 담당자 김철수 ▼", "fontSize": 8, "color": "1e293b"},
{"type": "rect", "x": 4.3, "y": 3.05, "w": 2.5, "h": 0.35, "fill": "FFFFFF", "text": "부 담당자 박영희 ▼", "fontSize": 8, "color": "1e293b"},
{"type": "rect", "x": 1.6, "y": 3.5, "w": 1.6, "h": 0.35, "fill": "FFFFFF", "text": "구입일 2026-03-01", "fontSize": 8, "color": "1e293b"},
{"type": "rect", "x": 3.3, "y": 3.5, "w": 1.6, "h": 0.35, "fill": "FFFFFF", "text": "설치일 2026-03-10", "fontSize": 8, "color": "1e293b"},
{"type": "rect", "x": 1.6, "y": 3.95, "w": 1.6, "h": 0.35, "fill": "FFFFFF", "text": "구입가격 35,000,000", "fontSize": 8, "color": "1e293b"},
{"type": "rect", "x": 3.3, "y": 3.95, "w": 1.6, "h": 0.35, "fill": "FFFFFF", "text": "내용연수 10년", "fontSize": 8, "color": "1e293b"},
{"type": "rect", "x": 5.0, "y": 3.5, "w": 1.8, "h": 0.8, "fill": "f1f5f9", "text": "공정 매핑\n☑ 절곡공정 (주)\n☐ 포장공정\n☑ 조립공정", "fontSize": 7, "color": "1e293b"},
{"type": "rect", "x": 1.6, "y": 4.4, "w": 5.3, "h": 0.5, "fill": "FFFFFF", "text": "메모\n특이사항 입력...", "fontSize": 8, "color": "94a3b8"},
{"type": "rect", "x": 5.4, "y": 5.0, "w": 0.7, "h": 0.3, "fill": "0d9488", "text": "저장", "fontSize": 9, "color": "FFFFFF", "bold": true},
{"type": "rect", "x": 6.2, "y": 5.0, "w": 0.7, "h": 0.3, "fill": "64748b", "text": "취소", "fontSize": 9, "color": "FFFFFF"}
]
},
{
"taskName": "설비 대장",
"route": "/equipment/registry/{id}",
"screenName": "설비 상세 (기본정보 탭)",
"screenId": "EQP_004",
"descriptions": [
{
"title": "탭 구조",
"content": "기본정보 | 점검항목 | 수리이력 | 사진 4개 탭. 현재 활성 탭 하이라이트 표시",
"markerX": 1.8,
"markerY": 1.7
},
{
"title": "기본정보 그리드",
"content": "설비 기본 정보를 라벨:값 그리드로 표시. 수정 버튼 클릭 시 수정 페이지로 이동",
"markerX": 1.8,
"markerY": 2.3
},
{
"title": "상태 배지",
"content": "가동(녹색)/유휴(주황)/폐기(적색) 상태를 컬러 배지로 표시",
"markerX": 5.5,
"markerY": 1.5
},
{
"title": "액션 버튼",
"content": "수정, 삭제(SoftDelete), 복원 버튼. 삭제된 설비는 복원 버튼 표시",
"markerX": 5.5,
"markerY": 5.0
}
],
"wireframeElements": [
{"type": "rect", "x": 1.6, "y": 1.2, "w": 4.0, "h": 0.4, "text": "포밍기 1호 (FM-001)", "fontSize": 14, "bold": true, "color": "1e293b", "fill": "f8fafc"},
{"type": "rect", "x": 5.8, "y": 1.25, "w": 0.6, "h": 0.25, "fill": "22c55e", "text": "가동", "fontSize": 8, "color": "FFFFFF", "bold": true},
{"type": "rect", "x": 1.6, "y": 1.7, "w": 1.2, "h": 0.3, "fill": "0d9488", "text": "기본정보", "fontSize": 8, "color": "FFFFFF", "bold": true},
{"type": "rect", "x": 2.8, "y": 1.7, "w": 1.2, "h": 0.3, "fill": "e2e8f0", "text": "점검항목", "fontSize": 8, "color": "64748b"},
{"type": "rect", "x": 4.0, "y": 1.7, "w": 1.2, "h": 0.3, "fill": "e2e8f0", "text": "수리이력", "fontSize": 8, "color": "64748b"},
{"type": "rect", "x": 5.2, "y": 1.7, "w": 1.0, "h": 0.3, "fill": "e2e8f0", "text": "사진", "fontSize": 8, "color": "64748b"},
{"type": "rect", "x": 1.6, "y": 2.1, "w": 5.3, "h": 2.8, "fill": "FFFFFF"},
{"type": "rect", "x": 1.8, "y": 2.2, "w": 1.0, "h": 0.25, "text": "설비코드", "fontSize": 7, "color": "64748b", "bold": true},
{"type": "rect", "x": 2.8, "y": 2.2, "w": 1.5, "h": 0.25, "text": "FM-001", "fontSize": 7, "color": "1e293b"},
{"type": "rect", "x": 4.5, "y": 2.2, "w": 1.0, "h": 0.25, "text": "설비명", "fontSize": 7, "color": "64748b", "bold": true},
{"type": "rect", "x": 5.5, "y": 2.2, "w": 1.3, "h": 0.25, "text": "포밍기 1호", "fontSize": 7, "color": "1e293b"},
{"type": "rect", "x": 1.8, "y": 2.55, "w": 1.0, "h": 0.25, "text": "설비유형", "fontSize": 7, "color": "64748b", "bold": true},
{"type": "rect", "x": 2.8, "y": 2.55, "w": 1.5, "h": 0.25, "text": "포밍기", "fontSize": 7, "color": "1e293b"},
{"type": "rect", "x": 4.5, "y": 2.55, "w": 1.0, "h": 0.25, "text": "생산라인", "fontSize": 7, "color": "64748b", "bold": true},
{"type": "rect", "x": 5.5, "y": 2.55, "w": 1.3, "h": 0.25, "text": "스라트", "fontSize": 7, "color": "1e293b"},
{"type": "rect", "x": 1.8, "y": 2.9, "w": 1.0, "h": 0.25, "text": "정 담당자", "fontSize": 7, "color": "64748b", "bold": true},
{"type": "rect", "x": 2.8, "y": 2.9, "w": 1.5, "h": 0.25, "text": "김철수", "fontSize": 7, "color": "1e293b"},
{"type": "rect", "x": 4.5, "y": 2.9, "w": 1.0, "h": 0.25, "text": "부 담당자", "fontSize": 7, "color": "64748b", "bold": true},
{"type": "rect", "x": 5.5, "y": 2.9, "w": 1.3, "h": 0.25, "text": "박영희", "fontSize": 7, "color": "1e293b"},
{"type": "rect", "x": 1.8, "y": 3.25, "w": 1.0, "h": 0.25, "text": "구입일", "fontSize": 7, "color": "64748b", "bold": true},
{"type": "rect", "x": 2.8, "y": 3.25, "w": 1.5, "h": 0.25, "text": "2023-05-10", "fontSize": 7, "color": "1e293b"},
{"type": "rect", "x": 4.5, "y": 3.25, "w": 1.0, "h": 0.25, "text": "설치일", "fontSize": 7, "color": "64748b", "bold": true},
{"type": "rect", "x": 5.5, "y": 3.25, "w": 1.3, "h": 0.25, "text": "2023-06-01", "fontSize": 7, "color": "1e293b"},
{"type": "rect", "x": 1.8, "y": 3.6, "w": 1.0, "h": 0.25, "text": "구입가격", "fontSize": 7, "color": "64748b", "bold": true},
{"type": "rect", "x": 2.8, "y": 3.6, "w": 1.5, "h": 0.25, "text": "35,000,000원", "fontSize": 7, "color": "1e293b"},
{"type": "rect", "x": 4.5, "y": 3.6, "w": 1.0, "h": 0.25, "text": "내용연수", "fontSize": 7, "color": "64748b", "bold": true},
{"type": "rect", "x": 5.5, "y": 3.6, "w": 1.3, "h": 0.25, "text": "10년", "fontSize": 7, "color": "1e293b"},
{"type": "rect", "x": 5.5, "y": 4.95, "w": 0.7, "h": 0.3, "fill": "0d9488", "text": "수정", "fontSize": 9, "color": "FFFFFF", "bold": true},
{"type": "rect", "x": 6.3, "y": 4.95, "w": 0.7, "h": 0.3, "fill": "dc2626", "text": "삭제", "fontSize": 9, "color": "FFFFFF"}
]
},
{
"taskName": "설비 대장",
"route": "/equipment/registry/{id}#inspection-items",
"screenName": "설비 상세 (점검항목 탭)",
"screenId": "EQP_005",
"descriptions": [
{
"title": "주기 선택 탭",
"content": "일일/주간/월간/2개월/분기/반년 6개 주기 탭. 선택한 주기의 점검항목 표시",
"markerX": 1.8,
"markerY": 2.2
},
{
"title": "점검항목 목록",
"content": "항목번호, 점검개소, 점검항목, 시기(가동중/정지중), 점검방법 컬럼. 인라인 수정 지원",
"markerX": 1.8,
"markerY": 2.9
},
{
"title": "항목 추가/복사",
"content": "점검항목 추가 버튼으로 새 항목 생성. 주기간 복사 기능으로 다른 주기의 항목을 일괄 복사",
"markerX": 5.0,
"markerY": 2.2
},
{
"title": "항목 삭제",
"content": "각 행의 삭제 버튼으로 개별 항목 삭제. 삭제 시 확인 다이얼로그 표시",
"markerX": 6.5,
"markerY": 2.9
}
],
"wireframeElements": [
{"type": "rect", "x": 1.6, "y": 1.2, "w": 4.0, "h": 0.4, "text": "포밍기 1호 (FM-001)", "fontSize": 14, "bold": true, "color": "1e293b", "fill": "f8fafc"},
{"type": "rect", "x": 1.6, "y": 1.7, "w": 1.2, "h": 0.3, "fill": "e2e8f0", "text": "기본정보", "fontSize": 8, "color": "64748b"},
{"type": "rect", "x": 2.8, "y": 1.7, "w": 1.2, "h": 0.3, "fill": "0d9488", "text": "점검항목", "fontSize": 8, "color": "FFFFFF", "bold": true},
{"type": "rect", "x": 4.0, "y": 1.7, "w": 1.2, "h": 0.3, "fill": "e2e8f0", "text": "수리이력", "fontSize": 8, "color": "64748b"},
{"type": "rect", "x": 5.2, "y": 1.7, "w": 1.0, "h": 0.3, "fill": "e2e8f0", "text": "사진", "fontSize": 8, "color": "64748b"},
{"type": "rect", "x": 1.6, "y": 2.1, "w": 0.7, "h": 0.25, "fill": "0d9488", "text": "일일", "fontSize": 7, "color": "FFFFFF"},
{"type": "rect", "x": 2.3, "y": 2.1, "w": 0.7, "h": 0.25, "fill": "f1f5f9", "text": "주간", "fontSize": 7, "color": "64748b"},
{"type": "rect", "x": 3.0, "y": 2.1, "w": 0.7, "h": 0.25, "fill": "f1f5f9", "text": "월간", "fontSize": 7, "color": "64748b"},
{"type": "rect", "x": 3.7, "y": 2.1, "w": 0.7, "h": 0.25, "fill": "f1f5f9", "text": "2개월", "fontSize": 7, "color": "64748b"},
{"type": "rect", "x": 5.0, "y": 2.1, "w": 1.0, "h": 0.25, "fill": "0d9488", "text": "+ 항목 추가", "fontSize": 7, "color": "FFFFFF"},
{"type": "rect", "x": 6.1, "y": 2.1, "w": 0.8, "h": 0.25, "fill": "64748b", "text": "주기 복사", "fontSize": 7, "color": "FFFFFF"},
{"type": "rect", "x": 1.6, "y": 2.5, "w": 5.3, "h": 0.3, "fill": "1e293b", "text": "No | 점검개소 | 점검항목 | 시기 | 점검방법 | 삭제", "fontSize": 7, "color": "FFFFFF", "bold": true},
{"type": "rect", "x": 1.6, "y": 2.8, "w": 5.3, "h": 0.3, "fill": "FFFFFF", "text": "1 | 유압부 | 유압 호스 상태 | 가동중 | 육안 확인 후 이상 시 교체 | X", "fontSize": 7, "color": "1e293b"},
{"type": "rect", "x": 1.6, "y": 3.1, "w": 5.3, "h": 0.3, "fill": "f8fafc", "text": "2 | 전기부 | 전원 케이블 | 정지중 | 절연 저항 측정 | X", "fontSize": 7, "color": "1e293b"},
{"type": "rect", "x": 1.6, "y": 3.4, "w": 5.3, "h": 0.3, "fill": "FFFFFF", "text": "3 | 구동부 | 벨트 장력 | 가동중 | 텐션게이지 측정 | X", "fontSize": 7, "color": "1e293b"},
{"type": "rect", "x": 1.6, "y": 3.7, "w": 5.3, "h": 0.3, "fill": "f8fafc", "text": "4 | 안전장치 | 비상정지 버튼 | 정지중 | 작동 테스트 | X", "fontSize": 7, "color": "1e293b"}
]
},
{
"taskName": "점검 관리",
"route": "/equipment/inspections",
"screenName": "점검 그리드",
"screenId": "EQP_006",
"descriptions": [
{
"title": "주기/기간 선택",
"content": "6개 주기 탭(일일~반년) 선택. 일일: 년-월 선택(1~31일 열), 그 외: 년 선택(주간:1~52주, 월간:1~12월 등)",
"markerX": 1.8,
"markerY": 1.7
},
{
"title": "점검 그리드",
"content": "행: 설비x점검항목, 열: 날짜/기간. 셀 클릭 시 결과 순환(빈칸->O->X->Triangle->빈칸). 색상으로 구분",
"markerX": 1.8,
"markerY": 2.8
},
{
"title": "종합판정/노트",
"content": "설비별 종합판정(OK/NG), 수리내역, 이상내용 편집 가능. 인라인 수정 지원",
"markerX": 5.5,
"markerY": 2.8
},
{
"title": "생산라인 필터",
"content": "생산라인별 필터로 해당 라인 설비만 표시. 전체/스라트/스크린/절곡/기타",
"markerX": 5.0,
"markerY": 1.7
}
],
"wireframeElements": [
{"type": "rect", "x": 1.6, "y": 1.2, "w": 5.3, "h": 0.4, "text": "설비 점검", "fontSize": 14, "bold": true, "color": "1e293b", "fill": "f8fafc"},
{"type": "rect", "x": 1.6, "y": 1.65, "w": 0.55, "h": 0.25, "fill": "0d9488", "text": "일일", "fontSize": 7, "color": "FFFFFF", "bold": true},
{"type": "rect", "x": 2.15, "y": 1.65, "w": 0.55, "h": 0.25, "fill": "f1f5f9", "text": "주간", "fontSize": 7, "color": "64748b"},
{"type": "rect", "x": 2.7, "y": 1.65, "w": 0.55, "h": 0.25, "fill": "f1f5f9", "text": "월간", "fontSize": 7, "color": "64748b"},
{"type": "rect", "x": 3.25, "y": 1.65, "w": 0.55, "h": 0.25, "fill": "f1f5f9", "text": "2개월", "fontSize": 7, "color": "64748b"},
{"type": "rect", "x": 3.8, "y": 1.65, "w": 0.55, "h": 0.25, "fill": "f1f5f9", "text": "분기", "fontSize": 7, "color": "64748b"},
{"type": "rect", "x": 4.35, "y": 1.65, "w": 0.55, "h": 0.25, "fill": "f1f5f9", "text": "반년", "fontSize": 7, "color": "64748b"},
{"type": "rect", "x": 5.0, "y": 1.65, "w": 1.0, "h": 0.25, "fill": "FFFFFF", "text": "2026-03 ▼", "fontSize": 7, "color": "1e293b"},
{"type": "rect", "x": 6.1, "y": 1.65, "w": 0.8, "h": 0.25, "fill": "FFFFFF", "text": "전체 ▼", "fontSize": 7, "color": "1e293b"},
{"type": "rect", "x": 1.6, "y": 2.0, "w": 5.3, "h": 0.35, "fill": "1e293b", "text": "설비 | 항목 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | ... | 판정", "fontSize": 6, "color": "FFFFFF", "bold": true},
{"type": "rect", "x": 1.6, "y": 2.35, "w": 5.3, "h": 0.55, "fill": "FFFFFF", "text": "포밍기 유압호스 O O O - - O X △ ... OK\n1호 벨트장력 O O O - - O O O ... OK", "fontSize": 6, "color": "1e293b"},
{"type": "rect", "x": 1.6, "y": 2.9, "w": 5.3, "h": 0.55, "fill": "f8fafc", "text": "미싱기 전원케이블 O O X - - △ O O ... NG\n3호 안전장치 O O O - - O O O ... OK", "fontSize": 6, "color": "1e293b"},
{"type": "rect", "x": 1.6, "y": 3.45, "w": 5.3, "h": 0.55, "fill": "FFFFFF", "text": "샤링기 유압압력 O O O - - O O O ... OK\n2호 칼날마모 O X △ - - O O O ... OK", "fontSize": 6, "color": "1e293b"},
{"type": "rect", "x": 1.6, "y": 4.1, "w": 5.3, "h": 0.5, "fill": "f1f5f9", "text": "범례: O = 양호(good) X = 불량(bad) △ = 수리(repaired) - = 휴일/주말\n셀 클릭 시: 빈칸 -> O -> X -> △ -> 빈칸 순환", "fontSize": 7, "color": "64748b"}
]
},
{
"taskName": "수리이력",
"route": "/equipment/repairs",
"screenName": "수리이력 목록",
"screenId": "EQP_007",
"descriptions": [
{
"title": "필터 영역",
"content": "설비 선택(드롭다운), 보전구분(사내/외주), 날짜 범위(시작일~종료일), 텍스트 검색(수리내용)",
"markerX": 1.8,
"markerY": 1.7
},
{
"title": "수리이력 테이블",
"content": "수리일, 설비명, 보전구분, 수리내용, 수리시간, 비용, 수리자/업체 컬럼. 행 클릭 시 수정 모달",
"markerX": 1.8,
"markerY": 2.6
},
{
"title": "수리이력 등록",
"content": "수리이력 등록 버튼 클릭 시 등록 폼(모달 또는 별도 페이지)으로 이동",
"markerX": 5.8,
"markerY": 1.3
},
{
"title": "비용 집계",
"content": "조회된 수리이력의 총 비용, 사내/외주 비용 비율 등 하단 요약 표시",
"markerX": 1.8,
"markerY": 4.5
}
],
"wireframeElements": [
{"type": "rect", "x": 1.6, "y": 1.2, "w": 5.3, "h": 0.4, "text": "수리이력", "fontSize": 14, "bold": true, "color": "1e293b", "fill": "f8fafc"},
{"type": "rect", "x": 5.8, "y": 1.25, "w": 1.0, "h": 0.3, "fill": "0d9488", "text": "+ 수리 등록", "fontSize": 8, "color": "FFFFFF", "bold": true},
{"type": "rect", "x": 1.6, "y": 1.7, "w": 1.5, "h": 0.3, "fill": "FFFFFF", "text": "설비 선택 ▼", "fontSize": 8, "color": "64748b"},
{"type": "rect", "x": 3.2, "y": 1.7, "w": 1.0, "h": 0.3, "fill": "FFFFFF", "text": "보전구분 ▼", "fontSize": 8, "color": "64748b"},
{"type": "rect", "x": 4.3, "y": 1.7, "w": 1.2, "h": 0.3, "fill": "FFFFFF", "text": "2026-01 ~ 2026-03", "fontSize": 7, "color": "64748b"},
{"type": "rect", "x": 5.6, "y": 1.7, "w": 1.2, "h": 0.3, "fill": "FFFFFF", "text": "🔍 검색", "fontSize": 8, "color": "94a3b8"},
{"type": "rect", "x": 1.6, "y": 2.15, "w": 5.3, "h": 0.35, "fill": "1e293b", "text": "수리일 | 설비명 | 보전구분 | 수리내용 | 시간 | 비용 | 수리자/업체", "fontSize": 7, "color": "FFFFFF", "bold": true},
{"type": "rect", "x": 1.6, "y": 2.5, "w": 5.3, "h": 0.3, "fill": "FFFFFF", "text": "2026-03-10 | 포밍기 1호 | 사내 | 유압호스 교체 | 2.0h | 150,000원 | 김철수", "fontSize": 7, "color": "1e293b"},
{"type": "rect", "x": 1.6, "y": 2.8, "w": 5.3, "h": 0.3, "fill": "f8fafc", "text": "2026-03-08 | 미싱기 3호 | 외주 | 모터 오버홀 | 8.0h | 2,500,000원 | ABC기계", "fontSize": 7, "color": "1e293b"},
{"type": "rect", "x": 1.6, "y": 3.1, "w": 5.3, "h": 0.3, "fill": "FFFFFF", "text": "2026-03-05 | 샤링기 2호 | 사내 | 칼날 교체 | 1.5h | 85,000원 | 이민수", "fontSize": 7, "color": "1e293b"},
{"type": "rect", "x": 1.6, "y": 3.4, "w": 5.3, "h": 0.3, "fill": "f8fafc", "text": "2026-02-28 | 절곡기 1호 | 외주 | 유압실린더 교체 | 4.0h | 1,200,000원 | XYZ설비", "fontSize": 7, "color": "1e293b"},
{"type": "rect", "x": 3.0, "y": 3.9, "w": 2.0, "h": 0.3, "text": "< 1 2 3 >", "fontSize": 8, "color": "64748b"},
{"type": "rect", "x": 1.6, "y": 4.3, "w": 5.3, "h": 0.4, "fill": "f1f5f9", "text": "총 수리비용: 3,935,000원 | 사내: 235,000원 (6%) | 외주: 3,700,000원 (94%)", "fontSize": 8, "color": "1e293b", "bold": true}
]
},
{
"taskName": "수리이력",
"route": "/equipment/repairs/create",
"screenName": "수리이력 등록",
"screenId": "EQP_008",
"descriptions": [
{
"title": "설비 선택",
"content": "수리 대상 설비를 드롭다운에서 선택. 설비코드+설비명 표시. 필수 입력",
"markerX": 1.8,
"markerY": 1.7
},
{
"title": "수리 정보",
"content": "수리일(DatePicker), 보전구분(사내/외주 라디오), 수리시간(시간 단위), 비용(원)",
"markerX": 1.8,
"markerY": 2.3
},
{
"title": "수리 상세",
"content": "수리내용(textarea), 수리자(사내 선택) 또는 외주업체명(텍스트 입력). 보전구분에 따라 전환",
"markerX": 1.8,
"markerY": 3.3
}
],
"wireframeElements": [
{"type": "rect", "x": 1.6, "y": 1.2, "w": 5.3, "h": 0.4, "text": "수리이력 등록", "fontSize": 14, "bold": true, "color": "1e293b", "fill": "f8fafc"},
{"type": "rect", "x": 1.6, "y": 1.7, "w": 5.3, "h": 0.35, "fill": "FFFFFF", "text": "설비 * FM-001 포밍기 1호 ▼", "fontSize": 8, "color": "1e293b"},
{"type": "rect", "x": 1.6, "y": 2.15, "w": 2.5, "h": 0.35, "fill": "FFFFFF", "text": "수리일 * 2026-03-12", "fontSize": 8, "color": "1e293b"},
{"type": "rect", "x": 4.3, "y": 2.15, "w": 2.5, "h": 0.35, "fill": "FFFFFF", "text": "보전구분 * ● 사내 ○ 외주", "fontSize": 8, "color": "1e293b"},
{"type": "rect", "x": 1.6, "y": 2.6, "w": 2.5, "h": 0.35, "fill": "FFFFFF", "text": "수리시간 2.0 시간", "fontSize": 8, "color": "1e293b"},
{"type": "rect", "x": 4.3, "y": 2.6, "w": 2.5, "h": 0.35, "fill": "FFFFFF", "text": "수리비용 150,000 원", "fontSize": 8, "color": "1e293b"},
{"type": "rect", "x": 1.6, "y": 3.05, "w": 2.5, "h": 0.35, "fill": "FFFFFF", "text": "수리자 김철수 ▼", "fontSize": 8, "color": "1e293b"},
{"type": "rect", "x": 1.6, "y": 3.5, "w": 5.3, "h": 1.0, "fill": "FFFFFF", "text": "수리내용\n유압호스 노후로 인한 교체 작업.\n기존 호스 균열 발견, 동일 규격 신품으로 교체 완료.\n압력 테스트 정상 확인.", "fontSize": 8, "color": "1e293b"},
{"type": "rect", "x": 5.4, "y": 4.7, "w": 0.7, "h": 0.3, "fill": "0d9488", "text": "저장", "fontSize": 9, "color": "FFFFFF", "bold": true},
{"type": "rect", "x": 6.2, "y": 4.7, "w": 0.7, "h": 0.3, "fill": "64748b", "text": "취소", "fontSize": 9, "color": "FFFFFF"}
]
},
{
"taskName": "Import",
"route": "/equipment/import",
"screenName": "엑셀 Import",
"screenId": "EQP_009",
"descriptions": [
{
"title": "파일 업로드",
"content": "엑셀 파일(.xlsx) 드래그&드롭 또는 파일 선택. 업로드 후 자동으로 미리보기 단계로 전환",
"markerX": 1.8,
"markerY": 1.8
},
{
"title": "미리보기 테이블",
"content": "파싱된 데이터를 테이블로 표시. 한글/영문 헤더 자동 매핑. 오류 행 빨간색 표시. 이미지(Drawing) 자동 추출 표시",
"markerX": 1.8,
"markerY": 2.7
},
{
"title": "중복 처리 옵션",
"content": "동일 설비코드 존재 시: 건너뜀(skip) 또는 덮어쓰기(overwrite) 선택. 라디오 버튼",
"markerX": 1.8,
"markerY": 4.2
},
{
"title": "Import 실행",
"content": "Import 실행 버튼 클릭 시 일괄 등록. 결과 요약(성공/실패/건너뜀 건수) 표시",
"markerX": 5.8,
"markerY": 4.2
}
],
"wireframeElements": [
{"type": "rect", "x": 1.6, "y": 1.2, "w": 5.3, "h": 0.4, "text": "엑셀 Import", "fontSize": 14, "bold": true, "color": "1e293b", "fill": "f8fafc"},
{"type": "rect", "x": 1.6, "y": 1.7, "w": 5.3, "h": 0.8, "fill": "f1f5f9", "text": "📁 엑셀 파일을 드래그하거나 클릭하여 선택하세요\n(.xlsx 형식, 최대 10MB)", "fontSize": 9, "color": "64748b"},
{"type": "rect", "x": 1.6, "y": 2.6, "w": 5.3, "h": 0.3, "fill": "1e293b", "text": "설비코드 | 설비명 | 유형 | 라인 | 상태 | 구입일 | 이미지", "fontSize": 7, "color": "FFFFFF", "bold": true},
{"type": "rect", "x": 1.6, "y": 2.9, "w": 5.3, "h": 0.3, "fill": "FFFFFF", "text": "FM-006 | 포밍기 6호 | 포밍기 | 스라트 | 가동 | 2026-01 | [img]", "fontSize": 7, "color": "1e293b"},
{"type": "rect", "x": 1.6, "y": 3.2, "w": 5.3, "h": 0.3, "fill": "f8fafc", "text": "MS-005 | 미싱기 5호 | 미싱기 | 스크린 | 가동 | 2025-11 | [img]", "fontSize": 7, "color": "1e293b"},
{"type": "rect", "x": 1.6, "y": 3.5, "w": 5.3, "h": 0.3, "fill": "fef2f2", "text": "FM-001 | 포밍기 1호 | 포밍기 | 스라트 | 가동 | 2023-05 | - (중복!)", "fontSize": 7, "color": "dc2626"},
{"type": "rect", "x": 1.6, "y": 3.9, "w": 3.0, "h": 0.35, "fill": "f1f5f9", "text": "중복 처리: ● 건너뜀(skip) ○ 덮어쓰기(overwrite)", "fontSize": 8, "color": "1e293b"},
{"type": "rect", "x": 1.6, "y": 4.35, "w": 3.0, "h": 0.3, "text": "총 3건 | 신규: 2건 | 중복: 1건 | 오류: 0건", "fontSize": 8, "color": "64748b"},
{"type": "rect", "x": 5.8, "y": 4.35, "w": 1.0, "h": 0.3, "fill": "0d9488", "text": "Import 실행", "fontSize": 8, "color": "FFFFFF", "bold": true}
]
}
]
}

View File

@@ -1,369 +1,369 @@
# 영업파트너 데모 테넌트 정책
> **작성일**: 2026-03-13
> **상태**: 설계 확정
---
## 1. 개요
### 1.1 목적
영업파트너가 SAM 시스템을 직접 체험하고, 잠재 고객에게 실제 화면을 시연하여 계약 전환율을 높인다.
### 1.2 핵심 원칙
- 영업파트너에게 "보여줄 수 있는 무기"를 제공한다
- 고객이 직접 체험하여 의사결정을 촉진한다
- 체험 데이터를 정식 테넌트로 전환하여 Lock-in 효과를 만든다
### 1.3 현황 및 문제점
| 항목 | 현재 상태 | 문제 |
|------|----------|------|
| 파트너 영업 도구 | 수당 시뮬레이터(`/price/`)만 존재 | 고객에게 실제 화면을 보여줄 수 없음 |
| Trial 상태 | `subscriptions` 모델에 정의만 됨 | 활성화 로직 미구현 |
| 데모 환경 | 없음 | 파트너가 SAM을 직접 체험하지 못하고 영업함 |
| 고객 설득 | 제안서 + 가격표만 제공 | "보여줄 수 없는 2천만원짜리 솔루션" → 전환율 저하 |
---
## 2. 데모 테넌트 전략 (3-Tier)
### 2.1 티어 구조
```
┌─────────────────────────────────────────────────────────────────────┐
│ SAM 데모 프로그램 3-Tier │
├──────────────┬──────────────────┬───────────────────────────────────┤
│ Tier 1 │ Tier 2 │ Tier 3 │
│ 쇼케이스 │ 파트너 데모 │ 고객 체험 │
│ (공용) │ (파트너별 1개) │ (영업건별) │
├──────────────┼──────────────────┼───────────────────────────────────┤
│ 읽기 전용 │ 풀 기능 체험 │ 고객 맞춤 데모 │
│ 샘플 데이터 │ 샘플+직접 입력 │ 고객 업종 데이터 │
│ 기간 제한 X │ 파트너 활동 중 │ 30일 제한 │
│ URL 1개 공유 │ 파트너 로그인 │ 고객 직접 로그인 │
└──────────────┴──────────────────┴───────────────────────────────────┘
```
### 2.2 Tier 1: 쇼케이스 (공용 데모)
**목적**: 누구나 SAM이 어떤 시스템인지 3분 안에 파악
| 항목 | 내용 |
|------|------|
| **대상** | 모든 방문자, 파트너 후보, 잠재 고객 |
| **접근** | 공개 URL (예: `demo.codebridge-x.com`) |
| **계정** | 게스트 계정 자동 로그인 (ID/PW 없음) |
| **데이터** | 제조업 샘플 데이터 (가상 회사 "데모제조") |
| **기능** | 읽기 전용 — 조회, 검색, 리포트 확인만 가능 |
| **리셋** | 매일 자정 자동 리셋 (Scheduler) |
| **기간** | 무제한 |
| **비용** | 없음 (마케팅 비용) |
**포함 샘플 데이터**:
- 품목 50개, 거래처 20개, 견적 10건, 수주 15건
- 생산계획 5건, 출하 10건
- 직원 10명, 부서 3개
- 최근 3개월 매출/생산 데이터 (차트용)
**활용 시나리오**:
```
파트너: "SAM이 어떤 시스템인지 보여드리겠습니다"
→ 스마트폰/태블릿으로 demo.codebridge-x.com 접속
→ 실시간 화면 시연 (3~5분)
→ "이런 시스템을 귀사 맞춤으로 구축해드립니다"
```
### 2.3 Tier 2: 파트너 데모 테넌트 (파트너별 전용)
**목적**: 파트너가 SAM을 직접 사용해보고, 고객 영업 시 맞춤 시연 가능
| 항목 | 내용 |
|------|------|
| **대상** | 승인된 영업파트너 (status=`active`) |
| **생성 시점** | 파트너 승인 시 자동 생성 |
| **계정** | 파트너 본인 계정으로 로그인 |
| **데이터** | 업종별 샘플 데이터 프리셋 + 직접 입력 가능 |
| **기능** | 전체 기능 사용 가능 (일부 제한) |
| **리셋** | 월 1회 자동 리셋 또는 파트너 요청 시 수동 리셋 |
| **기간** | 파트너 활동 기간 동안 유지 |
| **비용** | 없음 (파트너 지원) |
**기능 제한**:
| 기능 | 사용 가능 | 제한 사항 |
|------|:---------:|----------|
| 품목/거래처 관리 | ✅ | 최대 100개 |
| 견적/수주/출하 | ✅ | 최대 50건 |
| 생산관리 | ✅ | 최대 30건 |
| 사용자 초대 | ✅ | 최대 5명 |
| 리포트/통계 | ✅ | 제한 없음 |
| 바로빌 연동 | ❌ | 실제 금융 연동 차단 |
| 파일 저장 | ✅ | 최대 1GB |
| AI 토큰 | ✅ | 월 10만 토큰 |
**업종별 샘플 데이터 프리셋**:
| 프리셋 | 포함 데이터 | 대상 고객 |
|--------|-----------|----------|
| 제조업 기본 | 원자재→생산→출하 흐름 | 일반 제조업체 |
| 블라인드/스크린 | 커튼/블라인드 품목 + 시공 | 인테리어 업체 |
| 시공/건설 | 공사관리 + 자재 | 건설/시공 업체 |
| 유통/도소매 | 입출고 + 재고 | 유통 업체 |
### 2.4 Tier 3: 고객 체험 테넌트 (영업건별)
**목적**: 계약 직전 고객이 자기 데이터로 직접 체험하여 의사결정 촉진
| 항목 | 내용 |
|------|------|
| **대상** | 계약 검토 단계의 잠재 고객 |
| **생성** | 파트너가 Sales 시스템에서 요청 → 본사 승인 |
| **계정** | 고객 담당자 이메일로 초대 |
| **데이터** | 고객이 직접 입력하거나 CSV 임포트 |
| **기능** | Tier 2와 동일한 제한 |
| **기간** | 30일 (1회 연장 가능, 최대 60일) |
| **비용** | 없음 (영업 비용) |
| **전환** | 계약 시 → 데모 데이터를 정식 테넌트로 마이그레이션 가능 |
**핵심 가치 — "체험 데이터 → 정식 전환" 마이그레이션**:
```
고객 체험 (30일)
├── 품목 등록, 거래처 등록, 견적 작성 체험
├── "이미 입력한 데이터가 있으니 계약하면 바로 쓸 수 있다"
└── 계약 전환 시 → 데모 데이터를 정식 테넌트로 이관
→ Lock-in 효과 + 온보딩 시간 단축
```
---
## 3. 기술 구현 방안
### 3.1 데이터 모델 변경
```sql
-- tenants 테이블 확장
ALTER TABLE tenants ADD COLUMN tenant_type ENUM('production', 'demo_showcase', 'demo_partner', 'demo_trial') DEFAULT 'production';
ALTER TABLE tenants ADD COLUMN demo_expires_at DATETIME NULL;
ALTER TABLE tenants ADD COLUMN demo_source_partner_id BIGINT UNSIGNED NULL;
ALTER TABLE tenants ADD COLUMN demo_preset VARCHAR(50) NULL;
ALTER TABLE tenants ADD COLUMN demo_limits JSON NULL;
```
### 3.2 구독 모델 활용
기존 `subscriptions.status``trial` 상태를 활성화:
```
demo_showcase → subscription 없음 (무료 공용)
demo_partner → subscription.status = 'trial', plan = 'demo_partner'
demo_trial → subscription.status = 'trial', plan = 'demo_trial'
expires_at = created_at + 30 days
```
### 3.3 제한 적용 미들웨어
```php
// DemoLimitMiddleware
class DemoLimitMiddleware
{
public function handle($request, Closure $next)
{
$tenant = currentTenant();
if ($tenant->isDemoTenant()) {
// 1. 기간 만료 체크
if ($tenant->demo_expires_at && now()->gt($tenant->demo_expires_at)) {
return response()->json(['error' => '체험 기간이 만료되었습니다.'], 403);
}
// 2. 수량 제한 체크
$limits = $tenant->demo_limits;
// 3. 금지 기능 체크 (바로빌 등 외부 연동)
if ($this->isBlockedFeature($request)) {
return response()->json(['error' => '데모에서 사용할 수 없는 기능입니다.'], 403);
}
}
return $next($request);
}
}
```
### 3.4 샘플 데이터 시더 (프리셋별)
```php
// DemoDataSeeder — 테넌트 생성 시 호출
class DemoDataSeeder
{
public function seed(Tenant $tenant, string $preset = 'manufacturing')
{
$presets = [
'manufacturing' => ManufacturingPreset::class,
'blinds' => BlindsPreset::class,
'construction' => ConstructionPreset::class,
'distribution' => DistributionPreset::class,
];
$presets[$preset]::seed($tenant);
}
}
```
### 3.5 데모 → 정식 전환 프로세스
```
[Tier 3 체험 테넌트]
↓ 계약 체결
[전환 프로세스]
1. tenant_type = 'production' 변경
2. demo_limits = NULL (제한 해제)
3. demo_expires_at = NULL
4. subscription → status='active', plan='starter'/'business'
5. 기존 데이터 유지 (마이그레이션 불필요)
6. 추가 기능 활성화 (바로빌 등 외부 연동)
```
---
## 4. 영업 지원 도구 연계
### 4.1 Sales 시스템 연동
| 기능 | 설명 | API |
|------|------|-----|
| 데모 테넌트 요청 | 파트너가 고객 체험 테넌트 생성 요청 | `POST /api/demo-tenants` |
| 데모 현황 조회 | 내가 생성한 데모 테넌트 목록 | `GET /api/demo-tenants` |
| 데모 리셋 | 파트너 데모 데이터 초기화 | `POST /api/demo-tenants/{id}/reset` |
| 체험 연장 | 고객 체험 기간 연장 요청 | `POST /api/demo-tenants/{id}/extend` |
| 전환 요청 | 체험 → 정식 전환 요청 | `POST /api/demo-tenants/{id}/convert` |
### 4.2 파트너 대시보드 지표
```
┌──────────────────────────────────────────────────────┐
│ 내 데모 현황 │
├──────────────┬──────────────┬────────────────────────┤
│ 파트너 데모 │ 고객 체험 │ 전환율 │
│ 1개 (활성) │ 3개 (진행중) │ 40% (2/5) │
│ │ 1개 (만료) │ │
├──────────────┴──────────────┴────────────────────────┤
│ 최근 체험 활동 │
│ - [데모제조A] 3시간 전 견적서 3건 작성 │
│ - [시공업체B] 1일 전 품목 45개 등록 │
│ - [유통사C] 5일 전 마지막 접속 (비활성 경고) │
└──────────────────────────────────────────────────────┘
```
---
## 5. 영업 프로세스 통합
### 5.1 데모 활용 영업 플로우
```
1단계: 초기 접촉
└── Tier 1 쇼케이스 URL 공유 (3분 시연)
└── "이런 시스템입니다" — 관심 유발
2단계: 심층 상담
└── 파트너 Tier 2 데모로 고객 업종 맞춤 시연 (30분)
└── 프리셋 데이터로 실제 업무 흐름 보여주기
└── 가격 시뮬레이터로 견적 제시
3단계: 고객 체험 (의사결정 촉진)
└── Tier 3 고객 체험 테넌트 생성 (30일)
└── 고객이 직접 데이터 입력하며 체험
└── 파트너가 체험 활동 모니터링
└── "이미 입력한 데이터 살려드립니다" — 전환 유도
4단계: 계약 전환
└── 체험 데이터 → 정식 테넌트로 전환
└── 온보딩 기간 단축 (이미 익숙함)
└── 수당 정산 시작
```
### 5.2 KPI 및 전환 추적
| 지표 | 측정 대상 | 목표 |
|------|----------|------|
| 데모 요청 수 | 파트너별 월간 Tier 3 생성 수 | 파트너당 3건/월 |
| 체험 활성도 | 고객 로그인 횟수, 데이터 입력량 | 주 3회 이상 접속 |
| 체험→계약 전환율 | Tier 3 → 정식 계약 비율 | 30% 이상 |
| 평균 전환 기간 | 체험 시작 → 계약 체결 일수 | 21일 이내 |
| 데모 비활성 알림 | 7일 미접속 고객 자동 알림 | 파트너에게 팔로업 유도 |
---
## 6. 비용 및 리소스
### 6.1 인프라 비용
| 항목 | Tier 1 (1개) | Tier 2 (파트너 N개) | Tier 3 (건별) |
|------|:-----------:|:------------------:|:------------:|
| DB 용량 | ~50MB | ~100MB x N | ~100MB x 건 |
| 파일 저장 | 고정 | 1GB x N | 1GB x 건 |
| AI 토큰 | 없음 | 10만/월 x N | 10만/30일 x 건 |
| 월 예상 비용 | ~0원 | ~5천원 x N | ~5천원 x 건 |
### 6.2 개발 공수
| 작업 | 우선순위 | 규모 |
|------|:-------:|------|
| `tenant_type` 컬럼 + 마이그레이션 | 🔴 필수 | 소 |
| `DemoLimitMiddleware` | 🔴 필수 | 중 |
| 샘플 데이터 프리셋 (제조업 1종) | 🔴 필수 | 중 |
| Tier 1 쇼케이스 자동 리셋 스케줄러 | 🔴 필수 | 소 |
| 파트너 승인 시 Tier 2 자동 생성 | 🟡 중요 | 소 |
| Tier 3 생성/만료/전환 API | 🟡 중요 | 중 |
| Sales 대시보드 데모 현황 UI | 🟡 중요 | 중 |
| 추가 프리셋 (블라인드/시공/유통) | 🟢 권장 | 중 |
| 체험 활동 모니터링 + 알림 | 🟢 권장 | 중 |
| 데모 → 정식 데이터 전환 로직 | 🟢 권장 | 소 |
---
## 7. 단계별 실행 로드맵
```
Phase 1 (즉시) ─────────────────────────────────────
✅ Tier 1 쇼케이스: 공용 데모 테넌트 수동 생성
✅ 샘플 데이터 수동 입력 (제조업 기본)
✅ demo.codebridge-x.com 도메인 매핑
→ 파트너에게 즉시 공유 가능한 URL 확보
Phase 2 (자동화) ───────────────────────────────────
✅ tenant_type 컬럼 + DemoLimitMiddleware
✅ Tier 2 파트너 데모 자동 생성
✅ 샘플 데이터 시더 (프리셋 1종)
✅ 일일 리셋 스케줄러
Phase 3 (영업 연계) ────────────────────────────────
✅ Tier 3 고객 체험 생성/관리 API
✅ Sales 대시보드 연동
✅ 체험 → 정식 전환 프로세스
✅ 활동 모니터링 + 비활성 알림
Phase 4 (고도화) ───────────────────────────────────
✅ 추가 업종 프리셋
✅ 전환율 분석 대시보드
✅ A/B 테스트 (데모 제공 vs 미제공 전환율 비교)
```
---
## 관련 문서
- [features/sales/README.md](README.md) — 영업 관리 모듈 전체
- [features/sales/partners.md](partners.md) — 파트너 관리 기능
- [rules/customer-pricing.md](../../rules/customer-pricing.md) — 고객 요금표
- [rules/partner-commission.md](../../rules/partner-commission.md) — 영업파트너 수당 체계
- [features/settlement/subscriptions.md](../settlement/subscriptions.md) — 구독 관리
---
**최종 업데이트**: 2026-03-13
# 영업파트너 데모 테넌트 정책
> **작성일**: 2026-03-13
> **상태**: 설계 확정
---
## 1. 개요
### 1.1 목적
영업파트너가 SAM 시스템을 직접 체험하고, 잠재 고객에게 실제 화면을 시연하여 계약 전환율을 높인다.
### 1.2 핵심 원칙
- 영업파트너에게 "보여줄 수 있는 무기"를 제공한다
- 고객이 직접 체험하여 의사결정을 촉진한다
- 체험 데이터를 정식 테넌트로 전환하여 Lock-in 효과를 만든다
### 1.3 현황 및 문제점
| 항목 | 현재 상태 | 문제 |
|------|----------|------|
| 파트너 영업 도구 | 수당 시뮬레이터(`/price/`)만 존재 | 고객에게 실제 화면을 보여줄 수 없음 |
| Trial 상태 | `subscriptions` 모델에 정의만 됨 | 활성화 로직 미구현 |
| 데모 환경 | 없음 | 파트너가 SAM을 직접 체험하지 못하고 영업함 |
| 고객 설득 | 제안서 + 가격표만 제공 | "보여줄 수 없는 2천만원짜리 솔루션" → 전환율 저하 |
---
## 2. 데모 테넌트 전략 (3-Tier)
### 2.1 티어 구조
```
┌─────────────────────────────────────────────────────────────────────┐
│ SAM 데모 프로그램 3-Tier │
├──────────────┬──────────────────┬───────────────────────────────────┤
│ Tier 1 │ Tier 2 │ Tier 3 │
│ 쇼케이스 │ 파트너 데모 │ 고객 체험 │
│ (공용) │ (파트너별 1개) │ (영업건별) │
├──────────────┼──────────────────┼───────────────────────────────────┤
│ 읽기 전용 │ 풀 기능 체험 │ 고객 맞춤 데모 │
│ 샘플 데이터 │ 샘플+직접 입력 │ 고객 업종 데이터 │
│ 기간 제한 X │ 파트너 활동 중 │ 30일 제한 │
│ URL 1개 공유 │ 파트너 로그인 │ 고객 직접 로그인 │
└──────────────┴──────────────────┴───────────────────────────────────┘
```
### 2.2 Tier 1: 쇼케이스 (공용 데모)
**목적**: 누구나 SAM이 어떤 시스템인지 3분 안에 파악
| 항목 | 내용 |
|------|------|
| **대상** | 모든 방문자, 파트너 후보, 잠재 고객 |
| **접근** | 공개 URL (예: `demo.codebridge-x.com`) |
| **계정** | 게스트 계정 자동 로그인 (ID/PW 없음) |
| **데이터** | 제조업 샘플 데이터 (가상 회사 "데모제조") |
| **기능** | 읽기 전용 — 조회, 검색, 리포트 확인만 가능 |
| **리셋** | 매일 자정 자동 리셋 (Scheduler) |
| **기간** | 무제한 |
| **비용** | 없음 (마케팅 비용) |
**포함 샘플 데이터**:
- 품목 50개, 거래처 20개, 견적 10건, 수주 15건
- 생산계획 5건, 출하 10건
- 직원 10명, 부서 3개
- 최근 3개월 매출/생산 데이터 (차트용)
**활용 시나리오**:
```
파트너: "SAM이 어떤 시스템인지 보여드리겠습니다"
→ 스마트폰/태블릿으로 demo.codebridge-x.com 접속
→ 실시간 화면 시연 (3~5분)
→ "이런 시스템을 귀사 맞춤으로 구축해드립니다"
```
### 2.3 Tier 2: 파트너 데모 테넌트 (파트너별 전용)
**목적**: 파트너가 SAM을 직접 사용해보고, 고객 영업 시 맞춤 시연 가능
| 항목 | 내용 |
|------|------|
| **대상** | 승인된 영업파트너 (status=`active`) |
| **생성 시점** | 파트너 승인 시 자동 생성 |
| **계정** | 파트너 본인 계정으로 로그인 |
| **데이터** | 업종별 샘플 데이터 프리셋 + 직접 입력 가능 |
| **기능** | 전체 기능 사용 가능 (일부 제한) |
| **리셋** | 월 1회 자동 리셋 또는 파트너 요청 시 수동 리셋 |
| **기간** | 파트너 활동 기간 동안 유지 |
| **비용** | 없음 (파트너 지원) |
**기능 제한**:
| 기능 | 사용 가능 | 제한 사항 |
|------|:---------:|----------|
| 품목/거래처 관리 | ✅ | 최대 100개 |
| 견적/수주/출하 | ✅ | 최대 50건 |
| 생산관리 | ✅ | 최대 30건 |
| 사용자 초대 | ✅ | 최대 5명 |
| 리포트/통계 | ✅ | 제한 없음 |
| 바로빌 연동 | ❌ | 실제 금융 연동 차단 |
| 파일 저장 | ✅ | 최대 1GB |
| AI 토큰 | ✅ | 월 10만 토큰 |
**업종별 샘플 데이터 프리셋**:
| 프리셋 | 포함 데이터 | 대상 고객 |
|--------|-----------|----------|
| 제조업 기본 | 원자재→생산→출하 흐름 | 일반 제조업체 |
| 블라인드/스크린 | 커튼/블라인드 품목 + 시공 | 인테리어 업체 |
| 시공/건설 | 공사관리 + 자재 | 건설/시공 업체 |
| 유통/도소매 | 입출고 + 재고 | 유통 업체 |
### 2.4 Tier 3: 고객 체험 테넌트 (영업건별)
**목적**: 계약 직전 고객이 자기 데이터로 직접 체험하여 의사결정 촉진
| 항목 | 내용 |
|------|------|
| **대상** | 계약 검토 단계의 잠재 고객 |
| **생성** | 파트너가 Sales 시스템에서 요청 → 본사 승인 |
| **계정** | 고객 담당자 이메일로 초대 |
| **데이터** | 고객이 직접 입력하거나 CSV 임포트 |
| **기능** | Tier 2와 동일한 제한 |
| **기간** | 30일 (1회 연장 가능, 최대 60일) |
| **비용** | 없음 (영업 비용) |
| **전환** | 계약 시 → 데모 데이터를 정식 테넌트로 마이그레이션 가능 |
**핵심 가치 — "체험 데이터 → 정식 전환" 마이그레이션**:
```
고객 체험 (30일)
├── 품목 등록, 거래처 등록, 견적 작성 체험
├── "이미 입력한 데이터가 있으니 계약하면 바로 쓸 수 있다"
└── 계약 전환 시 → 데모 데이터를 정식 테넌트로 이관
→ Lock-in 효과 + 온보딩 시간 단축
```
---
## 3. 기술 구현 방안
### 3.1 데이터 모델 변경
```sql
-- tenants 테이블 확장
ALTER TABLE tenants ADD COLUMN tenant_type ENUM('production', 'demo_showcase', 'demo_partner', 'demo_trial') DEFAULT 'production';
ALTER TABLE tenants ADD COLUMN demo_expires_at DATETIME NULL;
ALTER TABLE tenants ADD COLUMN demo_source_partner_id BIGINT UNSIGNED NULL;
ALTER TABLE tenants ADD COLUMN demo_preset VARCHAR(50) NULL;
ALTER TABLE tenants ADD COLUMN demo_limits JSON NULL;
```
### 3.2 구독 모델 활용
기존 `subscriptions.status``trial` 상태를 활성화:
```
demo_showcase → subscription 없음 (무료 공용)
demo_partner → subscription.status = 'trial', plan = 'demo_partner'
demo_trial → subscription.status = 'trial', plan = 'demo_trial'
expires_at = created_at + 30 days
```
### 3.3 제한 적용 미들웨어
```php
// DemoLimitMiddleware
class DemoLimitMiddleware
{
public function handle($request, Closure $next)
{
$tenant = currentTenant();
if ($tenant->isDemoTenant()) {
// 1. 기간 만료 체크
if ($tenant->demo_expires_at && now()->gt($tenant->demo_expires_at)) {
return response()->json(['error' => '체험 기간이 만료되었습니다.'], 403);
}
// 2. 수량 제한 체크
$limits = $tenant->demo_limits;
// 3. 금지 기능 체크 (바로빌 등 외부 연동)
if ($this->isBlockedFeature($request)) {
return response()->json(['error' => '데모에서 사용할 수 없는 기능입니다.'], 403);
}
}
return $next($request);
}
}
```
### 3.4 샘플 데이터 시더 (프리셋별)
```php
// DemoDataSeeder — 테넌트 생성 시 호출
class DemoDataSeeder
{
public function seed(Tenant $tenant, string $preset = 'manufacturing')
{
$presets = [
'manufacturing' => ManufacturingPreset::class,
'blinds' => BlindsPreset::class,
'construction' => ConstructionPreset::class,
'distribution' => DistributionPreset::class,
];
$presets[$preset]::seed($tenant);
}
}
```
### 3.5 데모 → 정식 전환 프로세스
```
[Tier 3 체험 테넌트]
↓ 계약 체결
[전환 프로세스]
1. tenant_type = 'production' 변경
2. demo_limits = NULL (제한 해제)
3. demo_expires_at = NULL
4. subscription → status='active', plan='starter'/'business'
5. 기존 데이터 유지 (마이그레이션 불필요)
6. 추가 기능 활성화 (바로빌 등 외부 연동)
```
---
## 4. 영업 지원 도구 연계
### 4.1 Sales 시스템 연동
| 기능 | 설명 | API |
|------|------|-----|
| 데모 테넌트 요청 | 파트너가 고객 체험 테넌트 생성 요청 | `POST /api/demo-tenants` |
| 데모 현황 조회 | 내가 생성한 데모 테넌트 목록 | `GET /api/demo-tenants` |
| 데모 리셋 | 파트너 데모 데이터 초기화 | `POST /api/demo-tenants/{id}/reset` |
| 체험 연장 | 고객 체험 기간 연장 요청 | `POST /api/demo-tenants/{id}/extend` |
| 전환 요청 | 체험 → 정식 전환 요청 | `POST /api/demo-tenants/{id}/convert` |
### 4.2 파트너 대시보드 지표
```
┌──────────────────────────────────────────────────────┐
│ 내 데모 현황 │
├──────────────┬──────────────┬────────────────────────┤
│ 파트너 데모 │ 고객 체험 │ 전환율 │
│ 1개 (활성) │ 3개 (진행중) │ 40% (2/5) │
│ │ 1개 (만료) │ │
├──────────────┴──────────────┴────────────────────────┤
│ 최근 체험 활동 │
│ - [데모제조A] 3시간 전 견적서 3건 작성 │
│ - [시공업체B] 1일 전 품목 45개 등록 │
│ - [유통사C] 5일 전 마지막 접속 (비활성 경고) │
└──────────────────────────────────────────────────────┘
```
---
## 5. 영업 프로세스 통합
### 5.1 데모 활용 영업 플로우
```
1단계: 초기 접촉
└── Tier 1 쇼케이스 URL 공유 (3분 시연)
└── "이런 시스템입니다" — 관심 유발
2단계: 심층 상담
└── 파트너 Tier 2 데모로 고객 업종 맞춤 시연 (30분)
└── 프리셋 데이터로 실제 업무 흐름 보여주기
└── 가격 시뮬레이터로 견적 제시
3단계: 고객 체험 (의사결정 촉진)
└── Tier 3 고객 체험 테넌트 생성 (30일)
└── 고객이 직접 데이터 입력하며 체험
└── 파트너가 체험 활동 모니터링
└── "이미 입력한 데이터 살려드립니다" — 전환 유도
4단계: 계약 전환
└── 체험 데이터 → 정식 테넌트로 전환
└── 온보딩 기간 단축 (이미 익숙함)
└── 수당 정산 시작
```
### 5.2 KPI 및 전환 추적
| 지표 | 측정 대상 | 목표 |
|------|----------|------|
| 데모 요청 수 | 파트너별 월간 Tier 3 생성 수 | 파트너당 3건/월 |
| 체험 활성도 | 고객 로그인 횟수, 데이터 입력량 | 주 3회 이상 접속 |
| 체험→계약 전환율 | Tier 3 → 정식 계약 비율 | 30% 이상 |
| 평균 전환 기간 | 체험 시작 → 계약 체결 일수 | 21일 이내 |
| 데모 비활성 알림 | 7일 미접속 고객 자동 알림 | 파트너에게 팔로업 유도 |
---
## 6. 비용 및 리소스
### 6.1 인프라 비용
| 항목 | Tier 1 (1개) | Tier 2 (파트너 N개) | Tier 3 (건별) |
|------|:-----------:|:------------------:|:------------:|
| DB 용량 | ~50MB | ~100MB x N | ~100MB x 건 |
| 파일 저장 | 고정 | 1GB x N | 1GB x 건 |
| AI 토큰 | 없음 | 10만/월 x N | 10만/30일 x 건 |
| 월 예상 비용 | ~0원 | ~5천원 x N | ~5천원 x 건 |
### 6.2 개발 공수
| 작업 | 우선순위 | 규모 |
|------|:-------:|------|
| `tenant_type` 컬럼 + 마이그레이션 | 🔴 필수 | 소 |
| `DemoLimitMiddleware` | 🔴 필수 | 중 |
| 샘플 데이터 프리셋 (제조업 1종) | 🔴 필수 | 중 |
| Tier 1 쇼케이스 자동 리셋 스케줄러 | 🔴 필수 | 소 |
| 파트너 승인 시 Tier 2 자동 생성 | 🟡 중요 | 소 |
| Tier 3 생성/만료/전환 API | 🟡 중요 | 중 |
| Sales 대시보드 데모 현황 UI | 🟡 중요 | 중 |
| 추가 프리셋 (블라인드/시공/유통) | 🟢 권장 | 중 |
| 체험 활동 모니터링 + 알림 | 🟢 권장 | 중 |
| 데모 → 정식 데이터 전환 로직 | 🟢 권장 | 소 |
---
## 7. 단계별 실행 로드맵
```
Phase 1 (즉시) ─────────────────────────────────────
✅ Tier 1 쇼케이스: 공용 데모 테넌트 수동 생성
✅ 샘플 데이터 수동 입력 (제조업 기본)
✅ demo.codebridge-x.com 도메인 매핑
→ 파트너에게 즉시 공유 가능한 URL 확보
Phase 2 (자동화) ───────────────────────────────────
✅ tenant_type 컬럼 + DemoLimitMiddleware
✅ Tier 2 파트너 데모 자동 생성
✅ 샘플 데이터 시더 (프리셋 1종)
✅ 일일 리셋 스케줄러
Phase 3 (영업 연계) ────────────────────────────────
✅ Tier 3 고객 체험 생성/관리 API
✅ Sales 대시보드 연동
✅ 체험 → 정식 전환 프로세스
✅ 활동 모니터링 + 비활성 알림
Phase 4 (고도화) ───────────────────────────────────
✅ 추가 업종 프리셋
✅ 전환율 분석 대시보드
✅ A/B 테스트 (데모 제공 vs 미제공 전환율 비교)
```
---
## 관련 문서
- [features/sales/README.md](README.md) — 영업 관리 모듈 전체
- [features/sales/partners.md](partners.md) — 파트너 관리 기능
- [rules/customer-pricing.md](../../rules/customer-pricing.md) — 고객 요금표
- [rules/partner-commission.md](../../rules/partner-commission.md) — 영업파트너 수당 체계
- [features/settlement/subscriptions.md](../settlement/subscriptions.md) — 구독 관리
---
**최종 업데이트**: 2026-03-13

View File

@@ -1,340 +1,340 @@
# 데모 테넌트 사용 가이드
> **작성일**: 2026-03-13
> **상태**: 운영 중
> **대상**: 영업파트너, 관리자
---
## 1. 개요
### 1.1 목적
영업파트너가 고객에게 SAM 시스템을 직접 체험할 수 있는 데모 환경을 제공하고 관리하는 방법을 안내한다.
### 1.2 데모 유형 (3-Tier)
| 티어 | 유형 | 대상 | 기간 | 특징 |
|------|------|------|------|------|
| Tier 1 | 쇼케이스 | 전체 공유 | 무제한 | 읽기 전용, 매일 자동 리셋 |
| Tier 2 | 파트너 데모 | 파트너별 1개 | 파트너 활동 중 | 전체 기능 체험 가능 |
| Tier 3 | 고객 체험 | 영업건별 생성 | 30일 (연장 가능) | 고객 직접 로그인, 정식 전환 가능 |
> **Tier 3 (고객 체험)**이 가장 자주 사용하는 기능이다. 이 문서는 Tier 3 중심으로 설명한다.
---
## 2. 고객 체험 테넌트 생성
### 2.1 Sales 앱에서 생성
Sales 앱의 데모 관리 화면에서 다음 정보를 입력하여 생성한다:
| 항목 | 필수 | 설명 |
|------|:----:|------|
| 회사명 | O | 고객사 이름 (예: "테스트블라인드") |
| 이메일 | O | 고객 담당자 이메일 |
| 체험 기간 | - | 7~60일, 기본 30일 |
| 프리셋 | - | `manufacturing` 선택 시 샘플 데이터 자동 생성 |
### 2.2 프리셋 데이터 (manufacturing)
프리셋을 선택하면 고객이 빈 화면이 아닌 실제 데이터가 입력된 상태에서 체험을 시작한다:
| 데이터 | 건수 | 내용 |
|--------|------|------|
| 부서 | 6개 | 경영지원, 영업, 생산, 품질, 구매, 물류 |
| 거래처 | 10개 | 다양한 업종의 샘플 거래처 |
| 품목 | 20개 | 제품 10 + 자재 10 |
| 견적 | 5건 | 다양한 상태의 견적서 |
| 수주 | 8건 | 확정/진행 중/완료 수주 |
| 대시보드 통계 | 90일 | 매출/생산 차트용 일간 통계 |
### 2.3 API 직접 호출 (개발자용)
```
POST /api/v1/demo-tenants
```
```json
{
"company_name": "테스트블라인드",
"email": "customer@example.com",
"duration_days": 30,
"preset": "manufacturing"
}
```
**응답 예시:**
```json
{
"success": true,
"message": "데모 테넌트가 생성되었습니다.",
"data": {
"tenant_id": 292,
"company_name": "테스트블라인드",
"tenant_type": "DEMO_TRIAL",
"demo_expires_at": "2026-04-12",
"admin_email": "customer@example.com"
}
}
```
---
## 3. 데모 테넌트 관리
### 3.1 목록 조회
내가 생성한 데모 테넌트 목록을 확인한다.
```
GET /api/v1/demo-tenants
```
### 3.2 상세 조회
특정 데모 테넌트의 상세 정보를 확인한다.
```
GET /api/v1/demo-tenants/{id}
```
### 3.3 데이터 리셋
고객이 데이터를 지저분하게 만들었을 때 초기 상태로 복원한다. 프리셋 데이터가 다시 생성된다.
```
POST /api/v1/demo-tenants/{id}/reset
```
> 리셋은 기존 데이터를 모두 삭제하고 프리셋을 다시 시딩한다. 고객이 직접 입력한 데이터도 삭제된다.
### 3.4 체험 기간 연장
고객이 추가 체험을 원할 때 기간을 연장한다.
```
POST /api/v1/demo-tenants/{id}/extend
```
```json
{
"days": 14
}
```
> 기본 14일 연장. 연장은 1회만 가능하다.
### 3.5 정식 전환
고객이 계약을 결정하면 데모 테넌트를 정식 테넌트로 전환한다.
```
POST /api/v1/demo-tenants/{id}/convert
```
**전환 시 변경 사항:**
| 항목 | 전환 전 | 전환 후 |
|------|---------|---------|
| 테넌트 유형 | `DEMO_TRIAL` | `STD` (정식) |
| 만료일 | 30일 제한 | 제한 없음 |
| 기능 제한 | 바로빌 등 외부 연동 차단 | 전체 기능 사용 |
| 데이터 | 그대로 유지 | 그대로 유지 |
> 고객이 체험 중 입력한 데이터가 정식 환경에 그대로 이어진다. 데이터 재입력이 불필요하다.
---
## 4. 현황 분석 (관리자용)
### 4.1 대시보드 요약
전체 데모 현황을 한눈에 확인한다.
```
GET /api/v1/demo-analytics/summary
```
**제공 정보:**
- 전환율 퍼널 (체험 → 활성 → 만료 → 전환)
- 전체 전환율 (%)
- 평균 전환 기간 (일)
- 비활성 테넌트 수 (7일 이상 활동 없음)
- 유형별 데모 수 (쇼케이스/파트너/체험)
### 4.2 전환율 퍼널
전체 또는 파트너별 전환율을 분석한다.
```
GET /api/v1/demo-analytics/conversion-funnel
GET /api/v1/demo-analytics/conversion-funnel?partner_id=5
```
**응답 예시:**
```json
{
"funnel": {
"total_trials": 15,
"active_trials": 8,
"expired_trials": 3,
"converted": 4
},
"conversion_rate": 26.7,
"avg_conversion_days": 18
}
```
### 4.3 파트너별 성과
각 파트너의 데모 생성 수, 전환 수, 전환율을 비교한다.
```
GET /api/v1/demo-analytics/partner-performance
```
> 전환율 내림차순으로 정렬되어 우수 파트너를 빠르게 파악할 수 있다.
### 4.4 활동 현황 리포트
각 데모 테넌트의 실제 사용 현황을 확인한다.
```
GET /api/v1/demo-analytics/activity-report
GET /api/v1/demo-analytics/activity-report?partner_id=5
```
**활동 상태 분류:**
| 상태 | 기준 | 의미 |
|------|------|------|
| `active` | 1일 이내 활동 | 적극 사용 중 |
| `normal` | 3일 이내 활동 | 정상 사용 중 |
| `low` | 7일 이내 활동 | 관심 저하, 후속 조치 필요 |
| `inactive` | 7일 초과 | 비활성, 즉시 연락 필요 |
| `no_data` | 데이터 없음 | 아직 사용하지 않음 |
---
## 5. 자동 스케줄
시스템이 자동으로 처리하는 작업이다. 별도 조치 불필요.
| 시간 | 작업 | 설명 |
|------|------|------|
| 매일 00:00 | 쇼케이스 리셋 | Tier 1 데모 데이터를 매일 초기화 |
| 매일 04:20 | 만료 체크 | 만료 테넌트 비활성 처리 + D-7 경고 로그 |
| 매일 09:30 | 비활성 알림 | 7일 이상 활동 없는 테넌트 경고 로그 |
---
## 6. Artisan 커맨드 (서버 관리자용)
### 6.1 쇼케이스 리셋
```bash
# 쇼케이스 데이터 삭제 + 샘플 재시딩
php artisan demo:reset-showcase --seed
# 데이터 삭제만 (재시딩 없이)
php artisan demo:reset-showcase
```
### 6.2 만료 테넌트 체크
```bash
# 만료 처리 실행
php artisan demo:check-expired
# 대상만 확인 (변경 없음)
php artisan demo:check-expired --dry-run
```
### 6.3 비활성 테넌트 탐지
```bash
# 기본 7일 기준
php artisan demo:check-inactive
# 기준일 변경 (예: 3일)
php artisan demo:check-inactive --days=3
```
---
## 7. 영업 시나리오별 가이드
### 7.1 고객 방문 영업
```
1. 방문 전: 데모 테넌트 생성 (preset: manufacturing)
2. 방문 시: 고객에게 로그인 정보 전달, 함께 화면 시연
3. 방문 후: 고객이 직접 사용해보도록 안내 (30일 체험)
```
### 7.2 관심 고객 후속 조치
```
1. 활동 리포트 확인 → active/normal이면 전환 제안
2. low/inactive이면 전화 또는 방문하여 추가 시연
3. 데이터가 지저분하면 리셋 후 재시연
```
### 7.3 계약 결정 시
```
1. POST /{id}/convert 로 정식 전환
2. 고객 데이터는 그대로 유지됨 (재입력 불필요)
3. 바로빌 등 외부 연동 기능 활성화
```
### 7.4 체험 기간 부족 시
```
1. POST /{id}/extend 로 14일 연장 (1회 제한)
2. 추가 연장 필요 시 관리자에게 요청
```
---
## 8. API 전체 엔드포인트
### 8.1 데모 관리
| Method | Path | 설명 |
|--------|------|------|
| `GET` | `/api/v1/demo-tenants` | 내 데모 목록 |
| `POST` | `/api/v1/demo-tenants` | 체험 테넌트 생성 |
| `GET` | `/api/v1/demo-tenants/stats` | 간단 통계 |
| `GET` | `/api/v1/demo-tenants/{id}` | 상세 조회 |
| `POST` | `/api/v1/demo-tenants/{id}/reset` | 데이터 리셋 |
| `POST` | `/api/v1/demo-tenants/{id}/extend` | 기간 연장 |
| `POST` | `/api/v1/demo-tenants/{id}/convert` | 정식 전환 |
### 8.2 분석
| Method | Path | 설명 |
|--------|------|------|
| `GET` | `/api/v1/demo-analytics/summary` | 대시보드 요약 |
| `GET` | `/api/v1/demo-analytics/conversion-funnel` | 전환율 퍼널 |
| `GET` | `/api/v1/demo-analytics/partner-performance` | 파트너별 성과 |
| `GET` | `/api/v1/demo-analytics/activity-report` | 활동 현황 |
---
## 관련 문서
| 문서 | 설명 |
|------|------|
| [demo-tenant-policy.md](demo-tenant-policy.md) | 3-Tier 데모 전략 설계 문서 |
| [partners.md](partners.md) | 영업파트너 관리 |
| [README.md](README.md) | 영업 관리 기능 개요 |
---
**최종 업데이트**: 2026-03-13
# 데모 테넌트 사용 가이드
> **작성일**: 2026-03-13
> **상태**: 운영 중
> **대상**: 영업파트너, 관리자
---
## 1. 개요
### 1.1 목적
영업파트너가 고객에게 SAM 시스템을 직접 체험할 수 있는 데모 환경을 제공하고 관리하는 방법을 안내한다.
### 1.2 데모 유형 (3-Tier)
| 티어 | 유형 | 대상 | 기간 | 특징 |
|------|------|------|------|------|
| Tier 1 | 쇼케이스 | 전체 공유 | 무제한 | 읽기 전용, 매일 자동 리셋 |
| Tier 2 | 파트너 데모 | 파트너별 1개 | 파트너 활동 중 | 전체 기능 체험 가능 |
| Tier 3 | 고객 체험 | 영업건별 생성 | 30일 (연장 가능) | 고객 직접 로그인, 정식 전환 가능 |
> **Tier 3 (고객 체험)**이 가장 자주 사용하는 기능이다. 이 문서는 Tier 3 중심으로 설명한다.
---
## 2. 고객 체험 테넌트 생성
### 2.1 Sales 앱에서 생성
Sales 앱의 데모 관리 화면에서 다음 정보를 입력하여 생성한다:
| 항목 | 필수 | 설명 |
|------|:----:|------|
| 회사명 | O | 고객사 이름 (예: "테스트블라인드") |
| 이메일 | O | 고객 담당자 이메일 |
| 체험 기간 | - | 7~60일, 기본 30일 |
| 프리셋 | - | `manufacturing` 선택 시 샘플 데이터 자동 생성 |
### 2.2 프리셋 데이터 (manufacturing)
프리셋을 선택하면 고객이 빈 화면이 아닌 실제 데이터가 입력된 상태에서 체험을 시작한다:
| 데이터 | 건수 | 내용 |
|--------|------|------|
| 부서 | 6개 | 경영지원, 영업, 생산, 품질, 구매, 물류 |
| 거래처 | 10개 | 다양한 업종의 샘플 거래처 |
| 품목 | 20개 | 제품 10 + 자재 10 |
| 견적 | 5건 | 다양한 상태의 견적서 |
| 수주 | 8건 | 확정/진행 중/완료 수주 |
| 대시보드 통계 | 90일 | 매출/생산 차트용 일간 통계 |
### 2.3 API 직접 호출 (개발자용)
```
POST /api/v1/demo-tenants
```
```json
{
"company_name": "테스트블라인드",
"email": "customer@example.com",
"duration_days": 30,
"preset": "manufacturing"
}
```
**응답 예시:**
```json
{
"success": true,
"message": "데모 테넌트가 생성되었습니다.",
"data": {
"tenant_id": 292,
"company_name": "테스트블라인드",
"tenant_type": "DEMO_TRIAL",
"demo_expires_at": "2026-04-12",
"admin_email": "customer@example.com"
}
}
```
---
## 3. 데모 테넌트 관리
### 3.1 목록 조회
내가 생성한 데모 테넌트 목록을 확인한다.
```
GET /api/v1/demo-tenants
```
### 3.2 상세 조회
특정 데모 테넌트의 상세 정보를 확인한다.
```
GET /api/v1/demo-tenants/{id}
```
### 3.3 데이터 리셋
고객이 데이터를 지저분하게 만들었을 때 초기 상태로 복원한다. 프리셋 데이터가 다시 생성된다.
```
POST /api/v1/demo-tenants/{id}/reset
```
> 리셋은 기존 데이터를 모두 삭제하고 프리셋을 다시 시딩한다. 고객이 직접 입력한 데이터도 삭제된다.
### 3.4 체험 기간 연장
고객이 추가 체험을 원할 때 기간을 연장한다.
```
POST /api/v1/demo-tenants/{id}/extend
```
```json
{
"days": 14
}
```
> 기본 14일 연장. 연장은 1회만 가능하다.
### 3.5 정식 전환
고객이 계약을 결정하면 데모 테넌트를 정식 테넌트로 전환한다.
```
POST /api/v1/demo-tenants/{id}/convert
```
**전환 시 변경 사항:**
| 항목 | 전환 전 | 전환 후 |
|------|---------|---------|
| 테넌트 유형 | `DEMO_TRIAL` | `STD` (정식) |
| 만료일 | 30일 제한 | 제한 없음 |
| 기능 제한 | 바로빌 등 외부 연동 차단 | 전체 기능 사용 |
| 데이터 | 그대로 유지 | 그대로 유지 |
> 고객이 체험 중 입력한 데이터가 정식 환경에 그대로 이어진다. 데이터 재입력이 불필요하다.
---
## 4. 현황 분석 (관리자용)
### 4.1 대시보드 요약
전체 데모 현황을 한눈에 확인한다.
```
GET /api/v1/demo-analytics/summary
```
**제공 정보:**
- 전환율 퍼널 (체험 → 활성 → 만료 → 전환)
- 전체 전환율 (%)
- 평균 전환 기간 (일)
- 비활성 테넌트 수 (7일 이상 활동 없음)
- 유형별 데모 수 (쇼케이스/파트너/체험)
### 4.2 전환율 퍼널
전체 또는 파트너별 전환율을 분석한다.
```
GET /api/v1/demo-analytics/conversion-funnel
GET /api/v1/demo-analytics/conversion-funnel?partner_id=5
```
**응답 예시:**
```json
{
"funnel": {
"total_trials": 15,
"active_trials": 8,
"expired_trials": 3,
"converted": 4
},
"conversion_rate": 26.7,
"avg_conversion_days": 18
}
```
### 4.3 파트너별 성과
각 파트너의 데모 생성 수, 전환 수, 전환율을 비교한다.
```
GET /api/v1/demo-analytics/partner-performance
```
> 전환율 내림차순으로 정렬되어 우수 파트너를 빠르게 파악할 수 있다.
### 4.4 활동 현황 리포트
각 데모 테넌트의 실제 사용 현황을 확인한다.
```
GET /api/v1/demo-analytics/activity-report
GET /api/v1/demo-analytics/activity-report?partner_id=5
```
**활동 상태 분류:**
| 상태 | 기준 | 의미 |
|------|------|------|
| `active` | 1일 이내 활동 | 적극 사용 중 |
| `normal` | 3일 이내 활동 | 정상 사용 중 |
| `low` | 7일 이내 활동 | 관심 저하, 후속 조치 필요 |
| `inactive` | 7일 초과 | 비활성, 즉시 연락 필요 |
| `no_data` | 데이터 없음 | 아직 사용하지 않음 |
---
## 5. 자동 스케줄
시스템이 자동으로 처리하는 작업이다. 별도 조치 불필요.
| 시간 | 작업 | 설명 |
|------|------|------|
| 매일 00:00 | 쇼케이스 리셋 | Tier 1 데모 데이터를 매일 초기화 |
| 매일 04:20 | 만료 체크 | 만료 테넌트 비활성 처리 + D-7 경고 로그 |
| 매일 09:30 | 비활성 알림 | 7일 이상 활동 없는 테넌트 경고 로그 |
---
## 6. Artisan 커맨드 (서버 관리자용)
### 6.1 쇼케이스 리셋
```bash
# 쇼케이스 데이터 삭제 + 샘플 재시딩
php artisan demo:reset-showcase --seed
# 데이터 삭제만 (재시딩 없이)
php artisan demo:reset-showcase
```
### 6.2 만료 테넌트 체크
```bash
# 만료 처리 실행
php artisan demo:check-expired
# 대상만 확인 (변경 없음)
php artisan demo:check-expired --dry-run
```
### 6.3 비활성 테넌트 탐지
```bash
# 기본 7일 기준
php artisan demo:check-inactive
# 기준일 변경 (예: 3일)
php artisan demo:check-inactive --days=3
```
---
## 7. 영업 시나리오별 가이드
### 7.1 고객 방문 영업
```
1. 방문 전: 데모 테넌트 생성 (preset: manufacturing)
2. 방문 시: 고객에게 로그인 정보 전달, 함께 화면 시연
3. 방문 후: 고객이 직접 사용해보도록 안내 (30일 체험)
```
### 7.2 관심 고객 후속 조치
```
1. 활동 리포트 확인 → active/normal이면 전환 제안
2. low/inactive이면 전화 또는 방문하여 추가 시연
3. 데이터가 지저분하면 리셋 후 재시연
```
### 7.3 계약 결정 시
```
1. POST /{id}/convert 로 정식 전환
2. 고객 데이터는 그대로 유지됨 (재입력 불필요)
3. 바로빌 등 외부 연동 기능 활성화
```
### 7.4 체험 기간 부족 시
```
1. POST /{id}/extend 로 14일 연장 (1회 제한)
2. 추가 연장 필요 시 관리자에게 요청
```
---
## 8. API 전체 엔드포인트
### 8.1 데모 관리
| Method | Path | 설명 |
|--------|------|------|
| `GET` | `/api/v1/demo-tenants` | 내 데모 목록 |
| `POST` | `/api/v1/demo-tenants` | 체험 테넌트 생성 |
| `GET` | `/api/v1/demo-tenants/stats` | 간단 통계 |
| `GET` | `/api/v1/demo-tenants/{id}` | 상세 조회 |
| `POST` | `/api/v1/demo-tenants/{id}/reset` | 데이터 리셋 |
| `POST` | `/api/v1/demo-tenants/{id}/extend` | 기간 연장 |
| `POST` | `/api/v1/demo-tenants/{id}/convert` | 정식 전환 |
### 8.2 분석
| Method | Path | 설명 |
|--------|------|------|
| `GET` | `/api/v1/demo-analytics/summary` | 대시보드 요약 |
| `GET` | `/api/v1/demo-analytics/conversion-funnel` | 전환율 퍼널 |
| `GET` | `/api/v1/demo-analytics/partner-performance` | 파트너별 성과 |
| `GET` | `/api/v1/demo-analytics/activity-report` | 활동 현황 |
---
## 관련 문서
| 문서 | 설명 |
|------|------|
| [demo-tenant-policy.md](demo-tenant-policy.md) | 3-Tier 데모 전략 설계 문서 |
| [partners.md](partners.md) | 영업파트너 관리 |
| [README.md](README.md) | 영업 관리 기능 개요 |
---
**최종 업데이트**: 2026-03-13