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:
File diff suppressed because it is too large
Load Diff
@@ -1,242 +1,242 @@
|
||||
# 바로빌 서비스 출시 단계별 준비 계획
|
||||
|
||||
> **작성일**: 2026-03-17
|
||||
> **상태**: 계획 수립
|
||||
> **담당**: R&D실
|
||||
|
||||
---
|
||||
|
||||
## 1. 개요
|
||||
|
||||
### 1.1 목적
|
||||
|
||||
MNG에서 운영 중인 바로빌 연동 시스템을 서비스(API+React)로 이관하여, 멀티테넌트 고객이 직접 사용할 수 있는 SaaS 형태로 출시한다.
|
||||
|
||||
### 1.2 현재 상태
|
||||
|
||||
- **MNG (백오피스)**: 바로빌 SOAP 연동 완료, tenant_id=1 (코드브릿지엑스)에서 실무 운영 중
|
||||
- **API**: DB 모델 15개 + REST API 42개 엔드포인트 구현 완료 (데이터 조회/분개용)
|
||||
- **React**: 바로빌 설정 페이지 기본 구현
|
||||
|
||||
### 1.3 목표
|
||||
|
||||
고객(테넌트)이 SAM 서비스에서 바로빌 기능을 직접 설정하고 사용할 수 있도록 한다:
|
||||
- 계좌조회, 카드내역, 홈택스 세금계산서 자동 수집
|
||||
- 전자세금계산서 발행
|
||||
- 카카오톡/SMS 알림
|
||||
|
||||
---
|
||||
|
||||
## 2. 단계별 로드맵
|
||||
|
||||
```
|
||||
Phase 1 Phase 2 Phase 3 Phase 4
|
||||
SOAP 이관 UI 구현 베타테스트 정식 출시
|
||||
(API 개발) (React 개발) (내부→외부) (온보딩 가동)
|
||||
───────────── → ───────────── → ───────────── → ─────────────
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. Phase 1: SOAP 연동 이관 (API 개발)
|
||||
|
||||
> **핵심**: MNG의 BarobillService를 API로 이관하여 멀티테넌트 지원
|
||||
|
||||
### 3.1 작업 목록
|
||||
|
||||
| # | 작업 | 상세 | 난이도 |
|
||||
|---|------|------|--------|
|
||||
| 1-1 | BarobillService 이관 | MNG 1,761줄 → API로 이동, 멀티테넌트 리팩토링 | 상 |
|
||||
| 1-2 | 회원사 관리 API | 등록/수정/조회/상태확인 엔드포인트 | 중 |
|
||||
| 1-3 | 인증서 관리 API | 등록URL/유효성/만료일 조회 엔드포인트 | 중 |
|
||||
| 1-4 | 계좌 관리 API | 등록/목록/입출금 조회 엔드포인트 | 중 |
|
||||
| 1-5 | 카드 관리 API | 등록/수정/해지/사용내역 조회 엔드포인트 | 중 |
|
||||
| 1-6 | 세금계산서 발행 API | 작성/발행/조회 엔드포인트 | 상 |
|
||||
| 1-7 | 동기화 스케줄러 | 은행/카드/홈택스 자동 수집 (Queue Job) | 중 |
|
||||
| 1-8 | 테스트/운영 모드 전환 API | 회원사별 server_mode 전환 | 하 |
|
||||
|
||||
### 3.2 기술 과제
|
||||
|
||||
| 과제 | 설명 | 대응 방안 |
|
||||
|------|------|----------|
|
||||
| CERTKEY 관리 | 현재 전역 1개 → 멀티테넌트 대응 필요 | 바로빌 파트너 계약 구조 확인 후 결정 |
|
||||
| PHP SOAP 확장 | API 서버에 `php-soap` 설치 필요 | Docker/서버 환경 확인 |
|
||||
| 암호화 키 공유 | MNG/API 간 `APP_KEY` 동일해야 복호화 가능 | 현재 동일 키 사용 중 (확인 필요) |
|
||||
| 동기화 부하 | 테넌트 수 증가 시 SOAP 호출량 증가 | Queue 분산, 호출 간격 조절 |
|
||||
|
||||
### 3.3 환경 준비
|
||||
|
||||
```bash
|
||||
# API 서버에 PHP SOAP 확장 확인
|
||||
php -m | grep soap
|
||||
|
||||
# 없으면 설치 (개발 서버 Level 2)
|
||||
sudo apt install php8.4-soap
|
||||
sudo systemctl restart php8.4-fpm
|
||||
|
||||
# .env 설정 추가
|
||||
BAROBILL_CERT_KEY_TEST=<테스트 인증키>
|
||||
BAROBILL_CERT_KEY_PROD=<운영 인증키>
|
||||
BAROBILL_CORP_NUM=<파트너 사업자번호>
|
||||
BAROBILL_TEST_MODE=true
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. Phase 2: UI 구현 (React 개발)
|
||||
|
||||
> **핵심**: 고객이 직접 바로빌을 설정하고 데이터를 조회할 수 있는 화면
|
||||
|
||||
### 4.1 작업 목록
|
||||
|
||||
| # | 작업 | 상세 | 난이도 |
|
||||
|---|------|------|--------|
|
||||
| 2-1 | 바로빌 설정 페이지 | 회원사 등록/수정, 서버 모드 표시 | 중 |
|
||||
| 2-2 | 인증서 관리 화면 | 등록 URL 안내, 유효기간 표시, 갱신 알림 | 중 |
|
||||
| 2-3 | 계좌 관리 화면 | 등록 계좌 목록, 등록 URL 안내 | 중 |
|
||||
| 2-4 | 카드 관리 화면 | 등록 카드 목록, 추가/해지 | 중 |
|
||||
| 2-5 | 카드 거래내역 조회 | 기간별 조회, 분개 연동, 숨김/분할 | 상 |
|
||||
| 2-6 | 은행 거래내역 조회 | 기간별 조회, 분개 연동, 오버라이드/분할 | 상 |
|
||||
| 2-7 | 홈택스 세금계산서 | 매출/매입 조회, 분개 연동 | 중 |
|
||||
| 2-8 | 세금계산서 발행 화면 | 작성/발행 폼, 미리보기 | 상 |
|
||||
|
||||
### 4.2 화면 구성 (메뉴 구조)
|
||||
|
||||
```
|
||||
재무관리
|
||||
├─ 계좌관리
|
||||
│ ├─ 보유계좌 관리 (바로빌 계좌 등록 포함)
|
||||
│ └─ 계좌 입출금 내역
|
||||
├─ 카드관리
|
||||
│ ├─ 법인카드 관리 (바로빌 카드 등록 포함)
|
||||
│ └─ 카드 사용내역
|
||||
├─ 세금계산서
|
||||
│ ├─ 매출 세금계산서
|
||||
│ ├─ 매입 세금계산서
|
||||
│ └─ 세금계산서 발행
|
||||
└─ 설정
|
||||
└─ 바로빌 연동 설정 (인증서, 모드, 충전잔액)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. Phase 3: 베타테스트
|
||||
|
||||
> **핵심**: 내부 → 외부 순서로 검증, 테스트 모드 사용
|
||||
|
||||
### 5.1 내부 베타테스트
|
||||
|
||||
| 항목 | 내용 |
|
||||
|------|------|
|
||||
| **대상** | tenant_id=1 (코드브릿지엑스 본사) |
|
||||
| **기간** | 2주 |
|
||||
| **모드** | 테스트 모드 |
|
||||
| **검증 항목** | 전체 기능 동작, UI/UX, 데이터 정합성 |
|
||||
| **비교 기준** | MNG 운영 데이터와 서비스 데이터 일치 확인 |
|
||||
|
||||
**내부 베타 체크리스트**:
|
||||
|
||||
- [ ] 회원사 등록/수정 정상 동작
|
||||
- [ ] 인증서 등록 URL 정상 접근
|
||||
- [ ] 계좌 등록 및 입출금 내역 조회
|
||||
- [ ] 카드 등록 및 사용내역 조회
|
||||
- [ ] 홈택스 매출/매입 세금계산서 수집
|
||||
- [ ] 세금계산서 발행 (테스트 서버)
|
||||
- [ ] 분개 연동 정상 동작
|
||||
- [ ] 동기화 스케줄러 자동 수집 확인
|
||||
- [ ] MNG 데이터와 서비스 데이터 일치
|
||||
|
||||
### 5.2 외부 베타테스트
|
||||
|
||||
| 항목 | 내용 |
|
||||
|------|------|
|
||||
| **대상** | 선별 고객사 2~3곳 |
|
||||
| **기간** | 2~4주 |
|
||||
| **모드** | 테스트 모드 |
|
||||
| **검증 항목** | 실사용 시나리오, 다양한 사업자 유형, 피드백 수집 |
|
||||
|
||||
**외부 베타 체크리스트**:
|
||||
|
||||
- [ ] 다양한 사업자번호로 회원 등록
|
||||
- [ ] 다양한 은행/카드사 연동 확인
|
||||
- [ ] 고객 직접 인증서/계좌/카드 등록 가능 확인
|
||||
- [ ] 고객 피드백 수집 및 반영
|
||||
- [ ] 성능 (다수 테넌트 동시 동기화)
|
||||
|
||||
---
|
||||
|
||||
## 6. Phase 4: 정식 출시
|
||||
|
||||
> **핵심**: 운영 모드 전환, 과금 시작, 온보딩 프로세스 가동
|
||||
|
||||
### 6.1 출시 준비 체크리스트
|
||||
|
||||
**인프라**:
|
||||
- [ ] API 서버 `php-soap` 확장 설치 확인
|
||||
- [ ] 운영 `.env`에 `BAROBILL_CERT_KEY_PROD`, `BAROBILL_CORP_NUM` 설정
|
||||
- [ ] `BAROBILL_TEST_MODE=false` 설정
|
||||
- [ ] 동기화 스케줄러 Supervisor 등록
|
||||
- [ ] 바로빌 운영 CERTKEY 충전잔액 확보
|
||||
|
||||
**과금**:
|
||||
- [ ] `barobill_pricing_policies` 요금 정책 데이터 입력
|
||||
- [ ] 월정액 구독 자동 과금 배치 등록 (매월 1일)
|
||||
- [ ] 과금 내역 고객 조회 화면 (선택)
|
||||
|
||||
**운영**:
|
||||
- [ ] 인증서 만료 알림 (이메일/카카오톡)
|
||||
- [ ] 충전잔액 부족 알림
|
||||
- [ ] 동기화 실패 알림 및 재시도 로직
|
||||
- [ ] 바로빌 장애 시 대응 매뉴얼
|
||||
|
||||
### 6.2 온보딩 프로세스 정립
|
||||
|
||||
정식 출시 후 신규 고객 가입 시:
|
||||
|
||||
```
|
||||
계약 → 테넌트 생성 → 회원등록(테스트) → 인증서/계좌/카드 → 검증 → 운영전환 → 실무사용
|
||||
```
|
||||
|
||||
> 상세 프로세스: `features/barobill/tenant-onboarding.md` 참조
|
||||
|
||||
---
|
||||
|
||||
## 7. 바로빌 파트너 정책 확인 필요 사항
|
||||
|
||||
> **경고: 개발 착수 전 바로빌 측에 확인해야 할 사항**
|
||||
|
||||
| # | 확인 사항 | 이유 | 현재 상태 |
|
||||
|---|----------|------|----------|
|
||||
| 1 | 멀티테넌트 CERTKEY 구조 | 파트너 1개 키로 다수 회원사 관리 가능한지 | 미확인 |
|
||||
| 2 | 테스트 서버 제한 | 테스트 API 호출 횟수/기간 제한 | 미확인 |
|
||||
| 3 | 과금 구조 | 파트너 단가표 (건당/월정액) | 미확인 |
|
||||
| 4 | SLA | 바로빌 API 가용성 보장 수준 | 미확인 |
|
||||
| 5 | 회원사 대량 등록 | 일괄 등록 API 또는 제한 | 미확인 |
|
||||
| 6 | 인증서 대리 등록 | 고객 대신 등록 가능 여부 | 미확인 |
|
||||
|
||||
---
|
||||
|
||||
## 8. 리스크 및 대응
|
||||
|
||||
| 리스크 | 영향 | 대응 |
|
||||
|--------|------|------|
|
||||
| 바로빌 API 장애 | 거래 데이터 수집 중단 | 재시도 로직 + 장애 알림 |
|
||||
| 인증서 만료 | 계좌/세금계산서 조회 불가 | 만료 30일 전 알림 |
|
||||
| SOAP 호출 지연 | 페이지 응답 지연 | 비동기 Queue 처리 |
|
||||
| 테넌트 급증 | 동기화 부하 | 호출 간격 분산, 우선순위 큐 |
|
||||
| 충전잔액 부족 | API 호출 실패 | 잔액 모니터링 + 자동 알림 |
|
||||
|
||||
---
|
||||
|
||||
## 관련 문서
|
||||
|
||||
| 문서 | 설명 |
|
||||
|------|------|
|
||||
| [바로빌 연동 시스템](../../features/barobill/README.md) | 전체 구조, 모드, 과금 |
|
||||
| [테넌트 온보딩](../../features/barobill/tenant-onboarding.md) | 온보딩 6단계 프로세스 |
|
||||
| [바로빌 API 명세](../../frontend/api-specs/barobill-api.md) | REST API 42개 엔드포인트 |
|
||||
| [이관 현황](../../system/migration-status.md) | MNG→API+React 전체 이관 현황 |
|
||||
|
||||
---
|
||||
|
||||
**최종 업데이트**: 2026-03-17
|
||||
# 바로빌 서비스 출시 단계별 준비 계획
|
||||
|
||||
> **작성일**: 2026-03-17
|
||||
> **상태**: 계획 수립
|
||||
> **담당**: R&D실
|
||||
|
||||
---
|
||||
|
||||
## 1. 개요
|
||||
|
||||
### 1.1 목적
|
||||
|
||||
MNG에서 운영 중인 바로빌 연동 시스템을 서비스(API+React)로 이관하여, 멀티테넌트 고객이 직접 사용할 수 있는 SaaS 형태로 출시한다.
|
||||
|
||||
### 1.2 현재 상태
|
||||
|
||||
- **MNG (백오피스)**: 바로빌 SOAP 연동 완료, tenant_id=1 (코드브릿지엑스)에서 실무 운영 중
|
||||
- **API**: DB 모델 15개 + REST API 42개 엔드포인트 구현 완료 (데이터 조회/분개용)
|
||||
- **React**: 바로빌 설정 페이지 기본 구현
|
||||
|
||||
### 1.3 목표
|
||||
|
||||
고객(테넌트)이 SAM 서비스에서 바로빌 기능을 직접 설정하고 사용할 수 있도록 한다:
|
||||
- 계좌조회, 카드내역, 홈택스 세금계산서 자동 수집
|
||||
- 전자세금계산서 발행
|
||||
- 카카오톡/SMS 알림
|
||||
|
||||
---
|
||||
|
||||
## 2. 단계별 로드맵
|
||||
|
||||
```
|
||||
Phase 1 Phase 2 Phase 3 Phase 4
|
||||
SOAP 이관 UI 구현 베타테스트 정식 출시
|
||||
(API 개발) (React 개발) (내부→외부) (온보딩 가동)
|
||||
───────────── → ───────────── → ───────────── → ─────────────
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. Phase 1: SOAP 연동 이관 (API 개발)
|
||||
|
||||
> **핵심**: MNG의 BarobillService를 API로 이관하여 멀티테넌트 지원
|
||||
|
||||
### 3.1 작업 목록
|
||||
|
||||
| # | 작업 | 상세 | 난이도 |
|
||||
|---|------|------|--------|
|
||||
| 1-1 | BarobillService 이관 | MNG 1,761줄 → API로 이동, 멀티테넌트 리팩토링 | 상 |
|
||||
| 1-2 | 회원사 관리 API | 등록/수정/조회/상태확인 엔드포인트 | 중 |
|
||||
| 1-3 | 인증서 관리 API | 등록URL/유효성/만료일 조회 엔드포인트 | 중 |
|
||||
| 1-4 | 계좌 관리 API | 등록/목록/입출금 조회 엔드포인트 | 중 |
|
||||
| 1-5 | 카드 관리 API | 등록/수정/해지/사용내역 조회 엔드포인트 | 중 |
|
||||
| 1-6 | 세금계산서 발행 API | 작성/발행/조회 엔드포인트 | 상 |
|
||||
| 1-7 | 동기화 스케줄러 | 은행/카드/홈택스 자동 수집 (Queue Job) | 중 |
|
||||
| 1-8 | 테스트/운영 모드 전환 API | 회원사별 server_mode 전환 | 하 |
|
||||
|
||||
### 3.2 기술 과제
|
||||
|
||||
| 과제 | 설명 | 대응 방안 |
|
||||
|------|------|----------|
|
||||
| CERTKEY 관리 | 현재 전역 1개 → 멀티테넌트 대응 필요 | 바로빌 파트너 계약 구조 확인 후 결정 |
|
||||
| PHP SOAP 확장 | API 서버에 `php-soap` 설치 필요 | Docker/서버 환경 확인 |
|
||||
| 암호화 키 공유 | MNG/API 간 `APP_KEY` 동일해야 복호화 가능 | 현재 동일 키 사용 중 (확인 필요) |
|
||||
| 동기화 부하 | 테넌트 수 증가 시 SOAP 호출량 증가 | Queue 분산, 호출 간격 조절 |
|
||||
|
||||
### 3.3 환경 준비
|
||||
|
||||
```bash
|
||||
# API 서버에 PHP SOAP 확장 확인
|
||||
php -m | grep soap
|
||||
|
||||
# 없으면 설치 (개발 서버 Level 2)
|
||||
sudo apt install php8.4-soap
|
||||
sudo systemctl restart php8.4-fpm
|
||||
|
||||
# .env 설정 추가
|
||||
BAROBILL_CERT_KEY_TEST=<테스트 인증키>
|
||||
BAROBILL_CERT_KEY_PROD=<운영 인증키>
|
||||
BAROBILL_CORP_NUM=<파트너 사업자번호>
|
||||
BAROBILL_TEST_MODE=true
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. Phase 2: UI 구현 (React 개발)
|
||||
|
||||
> **핵심**: 고객이 직접 바로빌을 설정하고 데이터를 조회할 수 있는 화면
|
||||
|
||||
### 4.1 작업 목록
|
||||
|
||||
| # | 작업 | 상세 | 난이도 |
|
||||
|---|------|------|--------|
|
||||
| 2-1 | 바로빌 설정 페이지 | 회원사 등록/수정, 서버 모드 표시 | 중 |
|
||||
| 2-2 | 인증서 관리 화면 | 등록 URL 안내, 유효기간 표시, 갱신 알림 | 중 |
|
||||
| 2-3 | 계좌 관리 화면 | 등록 계좌 목록, 등록 URL 안내 | 중 |
|
||||
| 2-4 | 카드 관리 화면 | 등록 카드 목록, 추가/해지 | 중 |
|
||||
| 2-5 | 카드 거래내역 조회 | 기간별 조회, 분개 연동, 숨김/분할 | 상 |
|
||||
| 2-6 | 은행 거래내역 조회 | 기간별 조회, 분개 연동, 오버라이드/분할 | 상 |
|
||||
| 2-7 | 홈택스 세금계산서 | 매출/매입 조회, 분개 연동 | 중 |
|
||||
| 2-8 | 세금계산서 발행 화면 | 작성/발행 폼, 미리보기 | 상 |
|
||||
|
||||
### 4.2 화면 구성 (메뉴 구조)
|
||||
|
||||
```
|
||||
재무관리
|
||||
├─ 계좌관리
|
||||
│ ├─ 보유계좌 관리 (바로빌 계좌 등록 포함)
|
||||
│ └─ 계좌 입출금 내역
|
||||
├─ 카드관리
|
||||
│ ├─ 법인카드 관리 (바로빌 카드 등록 포함)
|
||||
│ └─ 카드 사용내역
|
||||
├─ 세금계산서
|
||||
│ ├─ 매출 세금계산서
|
||||
│ ├─ 매입 세금계산서
|
||||
│ └─ 세금계산서 발행
|
||||
└─ 설정
|
||||
└─ 바로빌 연동 설정 (인증서, 모드, 충전잔액)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. Phase 3: 베타테스트
|
||||
|
||||
> **핵심**: 내부 → 외부 순서로 검증, 테스트 모드 사용
|
||||
|
||||
### 5.1 내부 베타테스트
|
||||
|
||||
| 항목 | 내용 |
|
||||
|------|------|
|
||||
| **대상** | tenant_id=1 (코드브릿지엑스 본사) |
|
||||
| **기간** | 2주 |
|
||||
| **모드** | 테스트 모드 |
|
||||
| **검증 항목** | 전체 기능 동작, UI/UX, 데이터 정합성 |
|
||||
| **비교 기준** | MNG 운영 데이터와 서비스 데이터 일치 확인 |
|
||||
|
||||
**내부 베타 체크리스트**:
|
||||
|
||||
- [ ] 회원사 등록/수정 정상 동작
|
||||
- [ ] 인증서 등록 URL 정상 접근
|
||||
- [ ] 계좌 등록 및 입출금 내역 조회
|
||||
- [ ] 카드 등록 및 사용내역 조회
|
||||
- [ ] 홈택스 매출/매입 세금계산서 수집
|
||||
- [ ] 세금계산서 발행 (테스트 서버)
|
||||
- [ ] 분개 연동 정상 동작
|
||||
- [ ] 동기화 스케줄러 자동 수집 확인
|
||||
- [ ] MNG 데이터와 서비스 데이터 일치
|
||||
|
||||
### 5.2 외부 베타테스트
|
||||
|
||||
| 항목 | 내용 |
|
||||
|------|------|
|
||||
| **대상** | 선별 고객사 2~3곳 |
|
||||
| **기간** | 2~4주 |
|
||||
| **모드** | 테스트 모드 |
|
||||
| **검증 항목** | 실사용 시나리오, 다양한 사업자 유형, 피드백 수집 |
|
||||
|
||||
**외부 베타 체크리스트**:
|
||||
|
||||
- [ ] 다양한 사업자번호로 회원 등록
|
||||
- [ ] 다양한 은행/카드사 연동 확인
|
||||
- [ ] 고객 직접 인증서/계좌/카드 등록 가능 확인
|
||||
- [ ] 고객 피드백 수집 및 반영
|
||||
- [ ] 성능 (다수 테넌트 동시 동기화)
|
||||
|
||||
---
|
||||
|
||||
## 6. Phase 4: 정식 출시
|
||||
|
||||
> **핵심**: 운영 모드 전환, 과금 시작, 온보딩 프로세스 가동
|
||||
|
||||
### 6.1 출시 준비 체크리스트
|
||||
|
||||
**인프라**:
|
||||
- [ ] API 서버 `php-soap` 확장 설치 확인
|
||||
- [ ] 운영 `.env`에 `BAROBILL_CERT_KEY_PROD`, `BAROBILL_CORP_NUM` 설정
|
||||
- [ ] `BAROBILL_TEST_MODE=false` 설정
|
||||
- [ ] 동기화 스케줄러 Supervisor 등록
|
||||
- [ ] 바로빌 운영 CERTKEY 충전잔액 확보
|
||||
|
||||
**과금**:
|
||||
- [ ] `barobill_pricing_policies` 요금 정책 데이터 입력
|
||||
- [ ] 월정액 구독 자동 과금 배치 등록 (매월 1일)
|
||||
- [ ] 과금 내역 고객 조회 화면 (선택)
|
||||
|
||||
**운영**:
|
||||
- [ ] 인증서 만료 알림 (이메일/카카오톡)
|
||||
- [ ] 충전잔액 부족 알림
|
||||
- [ ] 동기화 실패 알림 및 재시도 로직
|
||||
- [ ] 바로빌 장애 시 대응 매뉴얼
|
||||
|
||||
### 6.2 온보딩 프로세스 정립
|
||||
|
||||
정식 출시 후 신규 고객 가입 시:
|
||||
|
||||
```
|
||||
계약 → 테넌트 생성 → 회원등록(테스트) → 인증서/계좌/카드 → 검증 → 운영전환 → 실무사용
|
||||
```
|
||||
|
||||
> 상세 프로세스: `features/barobill/tenant-onboarding.md` 참조
|
||||
|
||||
---
|
||||
|
||||
## 7. 바로빌 파트너 정책 확인 필요 사항
|
||||
|
||||
> **경고: 개발 착수 전 바로빌 측에 확인해야 할 사항**
|
||||
|
||||
| # | 확인 사항 | 이유 | 현재 상태 |
|
||||
|---|----------|------|----------|
|
||||
| 1 | 멀티테넌트 CERTKEY 구조 | 파트너 1개 키로 다수 회원사 관리 가능한지 | 미확인 |
|
||||
| 2 | 테스트 서버 제한 | 테스트 API 호출 횟수/기간 제한 | 미확인 |
|
||||
| 3 | 과금 구조 | 파트너 단가표 (건당/월정액) | 미확인 |
|
||||
| 4 | SLA | 바로빌 API 가용성 보장 수준 | 미확인 |
|
||||
| 5 | 회원사 대량 등록 | 일괄 등록 API 또는 제한 | 미확인 |
|
||||
| 6 | 인증서 대리 등록 | 고객 대신 등록 가능 여부 | 미확인 |
|
||||
|
||||
---
|
||||
|
||||
## 8. 리스크 및 대응
|
||||
|
||||
| 리스크 | 영향 | 대응 |
|
||||
|--------|------|------|
|
||||
| 바로빌 API 장애 | 거래 데이터 수집 중단 | 재시도 로직 + 장애 알림 |
|
||||
| 인증서 만료 | 계좌/세금계산서 조회 불가 | 만료 30일 전 알림 |
|
||||
| SOAP 호출 지연 | 페이지 응답 지연 | 비동기 Queue 처리 |
|
||||
| 테넌트 급증 | 동기화 부하 | 호출 간격 분산, 우선순위 큐 |
|
||||
| 충전잔액 부족 | API 호출 실패 | 잔액 모니터링 + 자동 알림 |
|
||||
|
||||
---
|
||||
|
||||
## 관련 문서
|
||||
|
||||
| 문서 | 설명 |
|
||||
|------|------|
|
||||
| [바로빌 연동 시스템](../../features/barobill/README.md) | 전체 구조, 모드, 과금 |
|
||||
| [테넌트 온보딩](../../features/barobill/tenant-onboarding.md) | 온보딩 6단계 프로세스 |
|
||||
| [바로빌 API 명세](../../frontend/api-specs/barobill-api.md) | REST API 42개 엔드포인트 |
|
||||
| [이관 현황](../../system/migration-status.md) | MNG→API+React 전체 이관 현황 |
|
||||
|
||||
---
|
||||
|
||||
**최종 업데이트**: 2026-03-17
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
> **시작일**: 2026-03-16
|
||||
> **위치**: MNG 생산관리 > 절곡품 관리 (신규 메뉴)
|
||||
> **목표**: 경동기업(5130) 수준의 절곡품 마스터 관리 + 전개도 데이터 + 이미지 관리
|
||||
> **원칙**: 기존 BendingInfoBuilder/PrefixResolver 보존, items.options 확장 방식
|
||||
> **원칙**: 기존 BendingInfoBuilder/PrefixResolver 보존, **전용 테이블 분리 방식**
|
||||
> **최종수정**: 2026-03-19 (테이블 분리 완료, 데이터 이관 완료)
|
||||
|
||||
---
|
||||
|
||||
@@ -16,6 +17,340 @@ SAM은 절곡품의 "계산과 조합"(BendingInfoBuilder/PrefixResolver)은 잘
|
||||
|
||||
---
|
||||
|
||||
## ⚠️ 아키텍처 변경: items → 전용 테이블 분리 (2026-03-19)
|
||||
|
||||
### 변경 결정 배경
|
||||
|
||||
기존에는 `items` 테이블(`item_category='BENDING'`)에 `options` JSON으로 절곡 속성을 저장했으나,
|
||||
다음 문제로 **전용 테이블 분리**로 방향 전환:
|
||||
|
||||
| 문제 | 설명 |
|
||||
|------|------|
|
||||
| **검색 불가** | 레거시 5130에서 "하장바" 검색 시 5건+ 나오지만 MNG2 기초관리에서 0건 |
|
||||
| **options 누락** | BD-LEGACY-* 210건 중 상당수가 `options.item_name` 미채워짐 → 검색 불가 |
|
||||
| **JSON 비정규화** | 20+개 절곡 속성이 options JSON 안에 있어 인덱싱/검색/정렬 불가 |
|
||||
| **코드 체계 불일치** | BD-LEGACY-*, BD-{품명}-* 혼재, LOT 코드 체계 적용 불가 |
|
||||
| **스키마 불명확** | options 키가 코드에만 정의(OPTION_KEYS), DB 레벨 제약 없음 |
|
||||
|
||||
### 하장바 검색 문제 — ✅ 해결됨
|
||||
|
||||
```
|
||||
[레거시 5130] chandj.bending WHERE item_name LIKE '%하장바%'
|
||||
→ 13건 (삭제 3건 제외 = 유효 10건)
|
||||
|
||||
[이전 MNG2 — items 방식] items WHERE item_category='BENDING' AND name LIKE '%하장바%'
|
||||
→ 2건만 (options.item_name 누락 → 검색 불가)
|
||||
|
||||
[현재 MNG2 — bending_items 전용 테이블] bending_items WHERE item_name LIKE '%하장바%'
|
||||
→ 10건 ✅ (정규 컬럼 item_name에 인덱스, chandj 유효건과 일치)
|
||||
|
||||
[해결 방법]
|
||||
테이블 분리(bending_items) + bending:clean-reimport로 chandj.bending 직접 이관
|
||||
→ item_name이 정규 컬럼으로 승격되어 검색 정상 동작
|
||||
```
|
||||
|
||||
### 새 테이블 구조: `bending_items`
|
||||
|
||||
```sql
|
||||
CREATE TABLE bending_items (
|
||||
id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
|
||||
tenant_id BIGINT UNSIGNED NOT NULL,
|
||||
|
||||
-- 코드 체계 (LOT 코드 = 제품Code + 종류Code + YYMMDD)
|
||||
code VARCHAR(50) NOT NULL, -- LOT: {제품}{종류}{YYMMDD} (예: CP260319 = 케이스 점검구)
|
||||
legacy_code VARCHAR(50) NULL, -- 이전 BD-LEGACY-* / BD-{품명}-* 코드
|
||||
legacy_bending_id INT UNSIGNED NULL, -- chandj.bending.id 참조
|
||||
|
||||
-- 기본 정보 (기존 options에서 정규 컬럼으로 승격)
|
||||
item_name VARCHAR(100) NOT NULL, -- 품명 (검색 가능!)
|
||||
item_sep VARCHAR(20) NULL, -- 대분류: 스크린/철재
|
||||
item_bending VARCHAR(50) NULL, -- 중분류: 가이드레일/케이스/하단마감재/...
|
||||
material VARCHAR(50) NULL, -- 재질: SUS 1.2T / EGI 1.55T
|
||||
item_spec VARCHAR(100) NULL, -- 규격: 120*70
|
||||
model_name VARCHAR(50) NULL, -- 소속 모델: KSS01
|
||||
model_UA VARCHAR(20) NULL, -- 인정여부: 인정/비인정
|
||||
|
||||
-- 절곡 전용 속성
|
||||
rail_width DECIMAL(10,2) NULL, -- 레일폭
|
||||
exit_direction VARCHAR(20) NULL, -- 출구방향 (케이스 전용)
|
||||
box_width DECIMAL(10,2) NULL, -- 박스폭 (케이스 전용)
|
||||
box_height DECIMAL(10,2) NULL, -- 박스높이 (케이스 전용)
|
||||
front_bottom DECIMAL(10,2) NULL, -- 전면밑 (케이스 전용)
|
||||
inspection_door VARCHAR(20) NULL, -- 점검구 (케이스 전용)
|
||||
|
||||
-- 메타 (비정형 속성만 — 검색/필터 대상 아닌 것)
|
||||
options JSON NULL, -- memo, author, search_keyword, modified_by 등
|
||||
is_active BOOLEAN NOT NULL DEFAULT TRUE,
|
||||
created_by BIGINT UNSIGNED NULL,
|
||||
updated_by BIGINT UNSIGNED NULL,
|
||||
deleted_by BIGINT UNSIGNED NULL,
|
||||
created_at TIMESTAMP NULL,
|
||||
updated_at TIMESTAMP NULL,
|
||||
deleted_at TIMESTAMP NULL,
|
||||
|
||||
-- 인덱스
|
||||
INDEX idx_tenant (tenant_id),
|
||||
INDEX idx_item_name (item_name),
|
||||
INDEX idx_item_sep (item_sep),
|
||||
INDEX idx_item_bending (item_bending),
|
||||
INDEX idx_material (material),
|
||||
INDEX idx_model_name (model_name),
|
||||
INDEX idx_code (code),
|
||||
INDEX idx_legacy_code (legacy_code),
|
||||
UNIQUE KEY uk_tenant_code (tenant_id, code, deleted_at)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
```
|
||||
|
||||
### 전개도 데이터: `bending_items.bending_data` (JSON 컬럼)
|
||||
|
||||
> **변경 이력**: 초기 설계는 별도 `bending_data` 테이블이었으나, JSON 통합으로 최종 결정.
|
||||
> 마이그레이션 `100007_move_bending_data_back_to_json`으로 `bending_data` 테이블 DROP 완료.
|
||||
|
||||
```json
|
||||
// bending_items.bending_data JSON 구조
|
||||
[
|
||||
{ "no": 1, "input": 10, "rate": "", "sum": 10, "color": true, "aAngle": false },
|
||||
{ "no": 2, "input": 11, "rate": "", "sum": 21, "color": false, "aAngle": false },
|
||||
{ "no": 3, "input": 110, "rate": "-1", "sum": 130, "color": false, "aAngle": false }
|
||||
]
|
||||
```
|
||||
|
||||
### 테이블 관계도 (최종)
|
||||
|
||||
```
|
||||
┌──────────────────────────┐ ┌──────────────────────┐
|
||||
│ bending_items (266건) │ │ bending_models (62건) │
|
||||
│ ──────────────────────── │ │ ──────────────────── │
|
||||
│ 기초관리 마스터 │ │ 가이드레일/케이스/ │
|
||||
│ 품명/재질/규격 (정규컬럼) │◄···│ 하단마감재 모델 │
|
||||
│ bending_data: JSON (내장) │ │ components JSON │
|
||||
│ code: RM260319 등 │ │ (sam_item_id 참조) │
|
||||
└──────────┬───────────────┘ └──────────────────────┘
|
||||
│
|
||||
│ 코드 매핑 (FK 없음)
|
||||
│ code 앞 2자리로 items.code 패턴 매칭
|
||||
▼
|
||||
┌──────────────────────┐
|
||||
│ items (기존 무변경) │
|
||||
│ ──────────────────── │
|
||||
│ BD-{PREFIX}-{LENGTH} │
|
||||
│ 재고/BOM/작업지시서 │
|
||||
│ BendingInfoBuilder │
|
||||
└──────────────────────┘
|
||||
```
|
||||
|
||||
### items 테이블과의 관계 — FK 없음, 코드 매핑
|
||||
|
||||
```
|
||||
┌──────────────────────────┐ ┌──────────────────────────┐
|
||||
│ bending_items (신규) │ │ items (기존 유지) │
|
||||
│ ──────────────────────── │ │ ──────────────────────── │
|
||||
│ 기초관리 마스터 전용 │ 코드 │ BD-{prod}{spec}-{length} │
|
||||
│ 품명/재질/규격 정규 컬럼 │ ·····→ │ 재고/BOM/작업지시서 연결 │
|
||||
│ 전개도 데이터 │ 매핑 │ item_category='BENDING' │
|
||||
│ code: CP260319 등 │ │ 재고관리용 (무변경) │
|
||||
│ bending_item_mappings 흡수│ │ │
|
||||
└──────────────────────────┘ └──────────────────────────┘
|
||||
|
||||
연결 방식: FK 없음
|
||||
- 재고 조회 필요 시: code 앞 2자리(제품+종류)로 items.code 패턴 매칭
|
||||
- items 테이블의 재고/BOM 기능은 완전히 독립 유지
|
||||
- BendingInfoBuilder는 items 테이블 계속 참조 (무변경)
|
||||
- bending_item_mappings 테이블 → 제거 (code에 흡수)
|
||||
```
|
||||
|
||||
### 영향도 분석 — 변경 / 무변경 구분
|
||||
|
||||
| 컴포넌트 | 변경 여부 | 설명 |
|
||||
|----------|----------|------|
|
||||
| `bending_items` 테이블 | **신규 생성** | 전용 테이블 + mappings 흡수 |
|
||||
| `bending_item_mappings` 테이블 | **제거** | bending_items에 컬럼 흡수 |
|
||||
| `BendingItemService` | **수정** | Item::where(BENDING) → BendingItem 모델 |
|
||||
| `BendingItemResource` | **수정** | getOption() → 정규 컬럼 직접 참조 |
|
||||
| `BendingItemController` (API) | 최소 수정 | 서비스만 바뀜, 라우트 동일 |
|
||||
| `BendingItemMapping` 모델 | **제거** | |
|
||||
| `BendingBaseController` (MNG) | 무변경 | API 클라이언트, URL 동일 |
|
||||
| `BendingProductController` (MNG) | 무변경 | API 클라이언트 |
|
||||
| `BendingInfoBuilder` | **무변경** | items 테이블 기반 (재고/BOM용) |
|
||||
| `Migrate5130BendingStock` | **무변경** | items 테이블 재고 생성용 |
|
||||
| `ValidateBendingItems` | **무변경** | items의 BD-* 재고 검증용 |
|
||||
| `files` (이미지) | **수정** | fileable_type='BendingItem' |
|
||||
| `work_order_items` | 무변경 | items.id 참조 유지 |
|
||||
|
||||
### 수정 대상 파일 및 완료 상태 (2026-03-19)
|
||||
|
||||
```
|
||||
[API 프로젝트] /home/kkk/sam/api/
|
||||
|
||||
✅ 기초관리 (bending_items):
|
||||
app/Models/BendingItem.php ← Eloquent (bending_data JSON, files)
|
||||
app/Services/BendingItemService.php ← BendingItem 모델, JSON 직접 저장
|
||||
app/Services/BendingCodeService.php ← BendingItem 조회 (LOT 코드)
|
||||
app/Http/Resources/Api/V1/BendingItemResource.php ← 정규 컬럼 + bending_data JSON + 수치 int 캐스팅
|
||||
app/Http/Requests/Api/V1/BendingItemStoreRequest.php ← unique → bending_items
|
||||
app/Swagger/v1/BendingItemApi.php ← Swagger 스키마
|
||||
|
||||
✅ 절곡품 모델 (bending_models):
|
||||
app/Models/BendingModel.php ← Eloquent (components JSON, files)
|
||||
app/Services/GuiderailModelService.php ← BendingModel + component 이미지 자동 복사
|
||||
app/Http/Resources/Api/V1/GuiderailModelResource.php ← 정규 컬럼 + 수치 int 캐스팅
|
||||
|
||||
✅ 파일 처리:
|
||||
app/Http/Controllers/Api/V1/ItemsFileController.php ← items → bending_items → bending_models 폴백
|
||||
|
||||
✅ 이관 커맨드:
|
||||
app/Console/Commands/BendingCleanReimport.php ← 기초관리 클린 재이관 + 이미지 (1커맨드)
|
||||
app/Console/Commands/BendingModelImport.php ← 모델 이관 + 조립도 JSON 업로드 + component 이미지 복사 (1커맨드)
|
||||
|
||||
✅ 마이그레이션:
|
||||
2026_03_19_100000_create_bending_items_table.php
|
||||
2026_03_19_100001~100003 (bending_data 테이블 → JSON 통합 과정)
|
||||
2026_03_19_100004_drop_bending_item_mappings_table.php
|
||||
2026_03_19_100005_add_length_columns_to_bending_items.php
|
||||
2026_03_19_100006_create_bending_models_table.php
|
||||
2026_03_19_100007_move_bending_data_back_to_json.php
|
||||
|
||||
✅ 제거:
|
||||
app/Models/Production/BendingItemMapping.php ← 삭제됨
|
||||
app/Models/BendingDataRow.php ← 삭제됨 (JSON 통합)
|
||||
bending_item_mappings 테이블 ← DROP
|
||||
bending_data 테이블 ← DROP (JSON 통합)
|
||||
|
||||
무변경:
|
||||
app/Http/Controllers/Api/V1/BendingItemController.php ← 서비스 주입 (변경 불필요)
|
||||
app/Http/Controllers/Api/V1/GuiderailModelController.php ← 서비스 주입
|
||||
app/Services/Production/BendingInfoBuilder.php ← items 직접 사용 (재고/BOM)
|
||||
app/Console/Commands/Migrate5130BendingStock.php ← items 재고용
|
||||
app/Console/Commands/ValidateBendingItems.php ← items 재고 검증용
|
||||
```
|
||||
|
||||
### 전체 복원 커맨드
|
||||
|
||||
```bash
|
||||
# Step 1: 기초관리 (265건 + bending_data JSON + 이미지 265건)
|
||||
php artisan bending:clean-reimport --legacy-img-path=/tmp/bending_img
|
||||
|
||||
# Step 2: 절곡품 모델 (61건 + 조립도 61건 + 부품이미지 276건 + sam_item_id)
|
||||
php artisan bending:model-import --legacy-path=/tmp/legacy_5130
|
||||
|
||||
# 사전 준비 (docker 컨테이너에 레거시 파일 복사):
|
||||
docker cp /home/kkk/sam/5130/bending/img docker-api-1:/tmp/bending_img
|
||||
docker compose exec -T api mkdir -p /tmp/legacy_5130
|
||||
docker cp /home/kkk/sam/5130/guiderail docker-api-1:/tmp/legacy_5130/guiderail
|
||||
docker cp /home/kkk/sam/5130/shutterbox docker-api-1:/tmp/legacy_5130/shutterbox
|
||||
docker cp /home/kkk/sam/5130/bottombar docker-api-1:/tmp/legacy_5130/bottombar
|
||||
```
|
||||
|
||||
### 데이터 현황 (2026-03-19 DB 검증 완료)
|
||||
|
||||
| 테이블 | 건수 | 소스 | 상태 |
|
||||
|--------|------|------|------|
|
||||
| bending_items | **266건** | chandj.bending 직접 (bending_data JSON 포함) | ✅ 이관 완료 |
|
||||
| bending_models | **62건** | chandj guiderail 21 + shutterbox 30 + bottombar 11 | ✅ 이관 완료 |
|
||||
| bending_item_mappings | 0건 | **DROP 완료** | ✅ 제거됨 |
|
||||
| items (BENDING) | 215건 | 기존 재고/BOM용 — **무변경 유지** | ✅ 독립 |
|
||||
|
||||
| 파일 (R2 업로드) | 예정 건수 | 현재 | 비고 |
|
||||
|------------------|----------|------|------|
|
||||
| bending_item / bending_diagram | 266건 | ⬜ 미업로드 | `bending:clean-reimport --legacy-img-path` 필요 |
|
||||
| bending_model / assembly_image | 62건 | ⬜ 미업로드 | `bending:model-import --legacy-path` 필요 |
|
||||
| bending_model / component_image | ~280건 | ⬜ 미업로드 | 부품별 독립 복사본 (스냅샷) |
|
||||
|
||||
| 레거시 대비 | chandj | bending_models | 상태 |
|
||||
|-------------|--------|----------------|------|
|
||||
| 가이드레일 | 20건 | 21건 | ✅ |
|
||||
| 케이스 | 30건 | 30건 | ✅ |
|
||||
| 하단마감재(스크린) | 8건 | 8건 | ✅ |
|
||||
| 하단마감재(철재) | 3건 | 3건 | ✅ |
|
||||
|
||||
| 검색 검증 | 이전(items) | 현재(bending_items) | 상태 |
|
||||
|----------|------------|-------------------|------|
|
||||
| 하장바 | 2건 | **10건** (chandj 유효건 일치) | ✅ 해결 |
|
||||
|
||||
> **이미지 업로드 안내**: 레거시 이미지 파일을 docker 컨테이너에 복사 후 artisan 커맨드 실행 필요 (위 "전체 복원 커맨드" 참조)
|
||||
|
||||
### 이미지 스냅샷 정책
|
||||
|
||||
```
|
||||
기초관리 이미지 수정 → 모델 component에 영향 없음 (독립 복사본)
|
||||
|
||||
구조:
|
||||
bending_items → files (bending_diagram) ← 원본 (수정 가능)
|
||||
bending_models → components[].image_file_id ← 복사본 (독립)
|
||||
→ files (assembly_image) ← 조립도 (별도)
|
||||
|
||||
신규 부품 추가 시:
|
||||
API(GuiderailModelService)에서 image_file_id 자동 복사 예정
|
||||
MNG2 editPartOriginal() → sam_item_id로 기초관리 편집 페이지 연결
|
||||
```
|
||||
|
||||
### LOT 코드 체계
|
||||
|
||||
```
|
||||
형식: {제품Code}{종류Code}{YYMMDD}
|
||||
유니크: (tenant_id, code, length_code, deleted_at)
|
||||
|
||||
예시:
|
||||
RS260319 + length_code=30 → 가이드레일(벽면) SUS마감 3000mm
|
||||
CF260319 → 케이스 전면부
|
||||
BS260319 + length_code=40 → 하단마감재(스크린) SUS 4000mm
|
||||
|
||||
변환 완료: BD-PREFIX-LEN 112건 → LOT 코드
|
||||
미변환: BD-한글 58건, BD-LEGACY 40건 (legacy_code 유지, 향후 변환)
|
||||
```
|
||||
|
||||
### LOT 코드 체계 (레거시 형태 유지)
|
||||
|
||||
```
|
||||
형식: {제품Code}{종류Code}{YYMMDD}
|
||||
|
||||
예시:
|
||||
RM260319 → 가이드레일(벽면형) 본체, 2026-03-19
|
||||
RS260319 → 가이드레일(벽면형) SUS마감재, 2026-03-19
|
||||
CF260319 → 케이스 전면부, 2026-03-19
|
||||
BS260319 → 하단마감재(스크린) SUS, 2026-03-19
|
||||
```
|
||||
|
||||
**LOT 코드 테이블 (정본)**:
|
||||
|
||||
| 제품 | 제품Code | 종류명 | 종류Code |
|
||||
|------|----------|--------|----------|
|
||||
| 가이드레일(벽면형) | R | 본체 | M |
|
||||
| | | 본체(철재) | T |
|
||||
| | | C형 | C |
|
||||
| | | D형 | D |
|
||||
| | | SUS 마감재 | S |
|
||||
| 가이드레일(측면형) | S | 본체디딤 | M |
|
||||
| | | 본체(철재) | T |
|
||||
| | | C형 | C |
|
||||
| | | D형 | D |
|
||||
| | | SUS 마감재1 | S |
|
||||
| | | SUS 마감재2 | U |
|
||||
| 케이스 | C | 전면부 | F |
|
||||
| | | 점검구 | P |
|
||||
| | | 린텔부 | L |
|
||||
| | | 후면코너부 | B |
|
||||
| 하단마감재(스크린) | B | SUS | S |
|
||||
| | | EGI | E |
|
||||
| 하단마감재(철재) | T | SUS | S |
|
||||
| | | EGI | E |
|
||||
| L-Bar | L | 스크린용 | A |
|
||||
| 연기차단재 | G | 화이바원단(W50) | I |
|
||||
| | | 화이바원단(W80) | I |
|
||||
|
||||
### 데이터 현황 (2026-03-19 DB 검증 완료)
|
||||
|
||||
| 항목 | 건수 | 비고 |
|
||||
|------|------|------|
|
||||
| **bending_items** (전용 테이블) | **266건** | ✅ 전건 bending_data JSON 포함 |
|
||||
| **bending_models** (전용 테이블) | **62건** | ✅ guiderail 21 + shutterbox 30 + bottombar 11 |
|
||||
| items BENDING (기존, 무변경) | 215건 | 재고/BOM용 독립 유지 |
|
||||
| bending_item_mappings | **DROP 완료** | bending_items.code에 흡수 |
|
||||
| 하장바 (bending_items) | **10건** | ✅ chandj 유효건과 일치 |
|
||||
| 이미지 (R2) | **미업로드** | 레거시 파일 docker 복사 후 커맨드 실행 필요 |
|
||||
|
||||
---
|
||||
|
||||
## MNG 현재 구조
|
||||
|
||||
### 생산관리 메뉴 (sidebar-static.blade.php)
|
||||
@@ -47,6 +382,10 @@ SAM은 절곡품의 "계산과 조합"(BendingInfoBuilder/PrefixResolver)은 잘
|
||||
```
|
||||
Step 1 (DB분석) → Step 2 (API) → Step 3 (MNG 화면) → Step 4 (React 연동)
|
||||
✅ 완료 ✅ 완료 ✅ 완료 (샘플용) ⬜ 미착수
|
||||
|
||||
테이블 분리: ✅ 완료 (bending_items + bending_models 전용 테이블)
|
||||
데이터 이관: ✅ 완료 (266건 기초관리 + 62건 모델)
|
||||
이미지 업로드: ⬜ 미완료 (레거시 파일 docker 복사 후 커맨드 실행 필요)
|
||||
```
|
||||
|
||||
| 문서 | 내용 | 상태 |
|
||||
@@ -55,19 +394,23 @@ Step 1 (DB분석) → Step 2 (API) → Step 3 (MNG 화면) → Step 4 (React
|
||||
| `step2-API.md` | API 엔드포인트 + 컨트롤러 설계 | ✅ 완료 |
|
||||
| `step3-MNG화면.md` | Blade 뷰 + HTMX + 메뉴 등록 | ✅ 완료 |
|
||||
| `step4-React연동.md` | React 운영 화면 구현 | ⬜ 미착수 |
|
||||
| `legacy-guiderail-analysis.md` | 레거시 guiderail 모듈 상세 분석 | ✅ 완료 |
|
||||
|
||||
### 완료된 작업 (2026-03-16~17)
|
||||
### 완료된 작업 (2026-03-16~19)
|
||||
|
||||
**Step 1 완료:**
|
||||
- `bending:fill-options` — BD-* prefix/분류 속성 자동 보강 (170건)
|
||||
- `bending:import-legacy` — chandj 전개도(bendingData) 임포트 (139/170건)
|
||||
- `guiderail:import-legacy` — chandj guiderail 20건 임포트
|
||||
- `bending-product:import-legacy` — chandj shutterbox 30건 + bottombar 10건 임포트
|
||||
**Step 1 완료 (DB 분석 + 테이블 분리):**
|
||||
- `bending_items` 전용 테이블 생성 — 정규 컬럼 승격 (item_name, item_sep, material 등 인덱스)
|
||||
- `bending_models` 전용 테이블 생성 — 가이드레일/케이스/하단마감재 3개 타입 통합
|
||||
- `bending_data` 테이블 → JSON 통합 → `bending_items.bending_data` 컬럼
|
||||
- `bending_item_mappings` 테이블 DROP — `bending_items.code`에 흡수
|
||||
- `bending:clean-reimport` — chandj.bending 266건 직접 이관 (bending_data JSON 포함)
|
||||
- `bending:model-import` — chandj guiderail 21 + shutterbox 30 + bottombar 11 = 62건 이관
|
||||
- ~~`bending:fill-options`~~ / ~~`bending:import-legacy`~~ — 구 items 방식 커맨드 (대체됨)
|
||||
|
||||
**Step 2 완료:**
|
||||
**Step 2 완료 (API):**
|
||||
- `BendingItemController` — CRUD + filters + pagination (6 엔드포인트)
|
||||
- `GuiderailModelController` — CRUD + filters (6 엔드포인트, 3개 카테고리 통합)
|
||||
- `BendingItemResource` / `GuiderailModelResource` — API 응답 포맷
|
||||
- `BendingItemResource` / `GuiderailModelResource` — API 응답 포맷 (정규 컬럼 직접 참조)
|
||||
- `FormRequest` — Index/Store/Update 유효성 검증
|
||||
- `ApiKeyMiddleware` — bending/guiderail/files 화이트리스트
|
||||
|
||||
@@ -79,6 +422,10 @@ Step 1 (DB분석) → Step 2 (API) → Step 3 (MNG 화면) → Step 4 (React
|
||||
- 파일: FileViewController (API R2 프록시) + 이미지 업로드/표시
|
||||
- DB 메뉴: 기초관리 + 절곡품 + 케이스 + 하단마감재 (4개)
|
||||
|
||||
**미완료:**
|
||||
- ⬜ 이미지 R2 업로드 — 레거시 파일 docker 복사 후 커맨드 재실행 필요
|
||||
- ⬜ Step 4 React 연동 — 미착수
|
||||
|
||||
---
|
||||
|
||||
## 참조 문서
|
||||
@@ -121,11 +468,13 @@ Step 1 (DB분석) → Step 2 (API) → Step 3 (MNG 화면) → Step 4 (React
|
||||
│ │ Blade │ │ Laravel │ │ Next.js │ │
|
||||
│ └──────────┘ └─────┬────┘ └──────────┘ │
|
||||
│ │ │
|
||||
│ ┌────┴────┐ │
|
||||
│ │ samdb │ │
|
||||
│ │ items │ ← item_category = 'BENDING' │
|
||||
│ │ files │ ← field_key = 'bending_diagram' │
|
||||
│ └─────────┘ │
|
||||
│ ┌─────────────┐ │
|
||||
│ │ samdb │ │
|
||||
│ │bending_items│ ← 기초관리 마스터 (전용, bending_data JSON 포함) │
|
||||
│ │bending_models│ ← 절곡품 모델 (가이드레일/케이스/하단마감재) │
|
||||
│ │ items │ ← 재고/BOM용 (기존 무변경) │
|
||||
│ │ files │ ← bending_diagram 이미지 │
|
||||
│ └─────────────┘ │
|
||||
│ │ │
|
||||
│ ┌────┴────┐ │
|
||||
│ │ R2 │ ← Cloudflare (이미지 저장) │
|
||||
@@ -136,37 +485,34 @@ Step 1 (DB분석) → Step 2 (API) → Step 3 (MNG 화면) → Step 4 (React
|
||||
|
||||
---
|
||||
|
||||
## 2. 데이터 구조 (2계층)
|
||||
## 2. 데이터 구조 (2계층 — 전용 테이블 + JSON)
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ │
|
||||
│ [1계층] 기초관리 — 개별 부품 (items 테이블) │
|
||||
│ ════════════════════════════════════════ │
|
||||
│ [1계층] 기초관리 — 개별 부품 (bending_items 전용 테이블) │
|
||||
│ ══════════════════════════════════════════════ │
|
||||
│ │
|
||||
│ items (item_category = 'BENDING') │
|
||||
│ bending_items (266건) │
|
||||
│ ┌──────────────────────────────────────────────────┐ │
|
||||
│ │ id: 100 │ │
|
||||
│ │ code: BD-가이드레일-KSS01-SUS-120*70 │ │
|
||||
│ │ name: 가이드레일 KSS01 SUS 120*70 │ │
|
||||
│ │ options: { │ │
|
||||
│ │ item_name: "마감재" ← 부품 품명 │ │
|
||||
│ │ item_sep: "스크린" ← 대분류 │ │
|
||||
│ │ item_bending: "가이드레일" ← 중분류 │ │
|
||||
│ │ material: "SUS 1.2T" ← 재질 │ │
|
||||
│ │ model_name: "KSS01" ← 소속 모델 │ │
|
||||
│ │ model_UA: "인정" ← 인정여부 │ │
|
||||
│ │ item_spec: "120*70" ← 규격 │ │
|
||||
│ │ rail_width: 70 ← 레일폭 │ │
|
||||
│ │ bendingData: [ ← 전개도 데이터 │ │
|
||||
│ │ {no:1, input:10, rate:"", sum:10, ...}, │ │
|
||||
│ │ {no:2, input:11, rate:"", sum:21, ...}, │ │
|
||||
│ │ ... │ │
|
||||
│ │ ] │ │
|
||||
│ │ + 케이스전용: exit_direction, box_width, ... │ │
|
||||
│ │ } │ │
|
||||
│ │ code: RM260319 ← LOT 코드 (제품+종류+날짜)│ │
|
||||
│ │ legacy_code: BD-LEGACY-042 ← 이전 코드 보존 │ │
|
||||
│ │ item_name: "마감재" ← 정규 컬럼 (인덱스) │ │
|
||||
│ │ item_sep: "스크린" ← 정규 컬럼 (인덱스) │ │
|
||||
│ │ item_bending: "가이드레일" ← 정규 컬럼 (인덱스) │ │
|
||||
│ │ material: "SUS 1.2T" ← 정규 컬럼 (인덱스) │ │
|
||||
│ │ model_name: "KSS01" ← 정규 컬럼 │ │
|
||||
│ │ model_UA: "인정" ← 정규 컬럼 │ │
|
||||
│ │ item_spec: "120*70" ← 정규 컬럼 │ │
|
||||
│ │ rail_width: 70 ← 정규 컬럼 │ │
|
||||
│ │ + 케이스전용: exit_direction, box_width... 정규 │ │
|
||||
│ │ bending_data: JSON 배열 ← 전개도 데이터 (내장) │ │
|
||||
│ │ [{no:1, input:10, rate:"", sum:10, color:true}, │ │
|
||||
│ │ {no:2, input:11, rate:"", sum:21, color:false}, │ │
|
||||
│ │ {no:3, input:110, rate:"-1", sum:130}, ...] │ │
|
||||
│ └──────────────────────────────────────────────────┘ │
|
||||
│ ↑ 265건 (레거시) + α │
|
||||
│ ↑ 266건 (전건 bending_data JSON 포함) │
|
||||
│ │
|
||||
│ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ │
|
||||
│ │
|
||||
@@ -188,7 +534,7 @@ Step 1 (DB분석) → Step 2 (API) → Step 3 (MNG 화면) → Step 4 (React
|
||||
│ │ │ │
|
||||
│ │ 재질별 폭합: SUS 1.2T → 406 | EGI 1.55T → 398 │ │
|
||||
│ └────────────────────────────────────────────────────────┘ │
|
||||
│ ↑ 가이드레일 20건 + 케이스 + 하단마감재 │
|
||||
│ ↑ 가이드레일 21건 + 케이스 30건 + 하단마감재 11건 = 62건 │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
@@ -391,20 +737,28 @@ Step 1 Step 2 Step 3 Step 4
|
||||
## 9. 레거시 → SAM 대응표
|
||||
|
||||
```
|
||||
레거시 (5130) SAM
|
||||
━━━━━━━━━━━━━ ━━━━━
|
||||
chandj.bending (265건) → items (item_category='BENDING') + options
|
||||
chandj.guiderail (20건) → guiderail-models API (신규 저장 구조)
|
||||
레거시 (5130) SAM (테이블 분리 완료)
|
||||
━━━━━━━━━━━━━ ━━━━━━━━━━━━━━━━━━
|
||||
chandj.bending (265건) → bending_items (266건, 전용 테이블, 정규 컬럼)
|
||||
chandj.bending.전개도 배열 → bending_items.bending_data (JSON 컬럼, 내장)
|
||||
chandj.guiderail (20건) → bending_models (62건, guiderail+shutterbox+bottombar)
|
||||
guiderail/list.php → MNG /bending/products (절곡품 목록)
|
||||
bending CRUD → MNG /bending/base (기초관리)
|
||||
put_guiderail_image.php → 기존 ItemsFileController (R2)
|
||||
put_guiderail_image.php → 기존 FileController (R2) — ⬜ 이미지 업로드 미완료
|
||||
fetch_guiderail_detail.php → React GuiderailPreview
|
||||
drawingTool.js (Canvas) → 2차 구현 (1차는 이미지 업로드만)
|
||||
inputList[] (별도 배열) → bendingData[] (객체 배열)
|
||||
bendingrateList[] → bendingData[].rate
|
||||
sumList[] → bendingData[].sum
|
||||
colorList[] → bendingData[].color
|
||||
AList[] → bendingData[].aAngle
|
||||
inputList[] (별도 배열 5개) → bending_data JSON [{no, input, rate, sum, color, aAngle}]
|
||||
items (BENDING) + options → items 유지 (재고/BOM용, BendingInfoBuilder 무변경)
|
||||
bending_item_mappings → DROP 완료 (bending_items.code에 흡수)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 10. 레거시 guiderail 모듈 상세 분석
|
||||
|
||||
> 별도 문서로 분리: [`legacy-guiderail-analysis.md`](./legacy-guiderail-analysis.md)
|
||||
>
|
||||
> 포함 내용: 파일 구성(21개), DB 스키마(guiderail/bending), CRUD 흐름,
|
||||
> 전개도 생성, 구성요소(벽면형/측면형), 검색/필터, guidebook
|
||||
|
||||
|
||||
|
||||
@@ -388,3 +388,79 @@ php artisan bending-model:import-assembly-images # ✅ 결합형태 이미지 6
|
||||
- [x] artisan command 7개 (위 목록 참조)
|
||||
- [x] CRUD 검증 완료
|
||||
- [x] 이미지 마이그레이션 완료 (총 473건 R2 업로드)
|
||||
|
||||
|
||||
|
||||
|
||||
{
|
||||
"lot_no_code_table": [
|
||||
{
|
||||
"제품": "가이드레일(벽면형)",
|
||||
"제품Code": "R",
|
||||
"종류": [
|
||||
{ "종류명": "본체", "Code": "M" },
|
||||
{ "종류명": "본체(철재)", "Code": "T" },
|
||||
{ "종류명": "C형", "Code": "C" },
|
||||
{ "종류명": "D형", "Code": "D" },
|
||||
{ "종류명": "SUS 마감재", "Code": "S" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"제품": "가이드레일(측면형)",
|
||||
"제품Code": "S",
|
||||
"종류": [
|
||||
{ "종류명": "본체디딤", "Code": "M" },
|
||||
{ "종류명": "본체(철재)", "Code": "T" },
|
||||
{ "종류명": "C형", "Code": "C" },
|
||||
{ "종류명": "D형", "Code": "D" },
|
||||
{ "종류명": "SUS 마감재①", "Code": "S" },
|
||||
{ "종류명": "SUS 마감재②", "Code": "U" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"제품": "케이스",
|
||||
"제품Code": "C",
|
||||
"종류": [
|
||||
{ "종류명": "전면부", "Code": "F" },
|
||||
{ "종류명": "점검구", "Code": "P" },
|
||||
{ "종류명": "린텔부", "Code": "L" },
|
||||
{ "종류명": "후면코너부", "Code": "B" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"제품": "하단마감재(스크린)",
|
||||
"제품Code": "B",
|
||||
"종류": [
|
||||
{ "종류명": "SUS", "Code": "S" },
|
||||
{ "종류명": "EGI", "Code": "E" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"제품": "하단마감재(철재)",
|
||||
"제품Code": "T",
|
||||
"종류": [
|
||||
{ "종류명": "SUS", "Code": "S" },
|
||||
{ "종류명": "EGI", "Code": "E" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"제품": "L-Bar",
|
||||
"제품Code": "L",
|
||||
"종류": [
|
||||
{ "종류명": "스크린용", "Code": "A" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"제품": "연기차단재",
|
||||
"제품Code": "G",
|
||||
"종류": [
|
||||
{ "종류명": "화이바원단(W50)", "Code": "I" },
|
||||
{ "종류명": "화이바원단(W80)", "Code": "I" }
|
||||
]
|
||||
}
|
||||
],
|
||||
"비고": {
|
||||
"년월일": "Code 참조"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
370
dev/dev_plans/bending-management/step5-canvas그리기.md
Normal file
370
dev/dev_plans/bending-management/step5-canvas그리기.md
Normal file
@@ -0,0 +1,370 @@
|
||||
# Step 5: Canvas 그리기 기능 (5130 → MNG 적용)
|
||||
|
||||
> **프로젝트**: MNG (`sam/mng`)
|
||||
> **선행 조건**: Step 3 (MNG 화면) 완료
|
||||
> **참조**: 레거시 `5130/js/imageEditor.js`, `5130/js/drawingModule.js`
|
||||
> **상태**: ⬜ 분석 완료, 구현 미착수
|
||||
|
||||
---
|
||||
|
||||
## 1. 레거시 Canvas 분석 결과
|
||||
|
||||
### 1-1. 5130 Canvas 구현체 3개
|
||||
|
||||
| 파일 | 크기 | 라이브러리 | 용도 | 채택 여부 |
|
||||
|------|------|-----------|------|:---:|
|
||||
| `5130/js/imageEditor.js` | ~511줄 | **Fabric.js 5.3.0** | 프로덕션 이미지 에디터 (모달 dialog) | ✅ **채택** |
|
||||
| `5130/js/drawingModule.js` | ~966줄 | Pure Canvas 2D | 독립 모달 + 전체 UI 포함 | ❌ 중복 |
|
||||
| `5130/js/drawLib.js` | ~272줄 | Pure Canvas 2D | 경량 버전 | ❌ 기능 부족 |
|
||||
|
||||
**채택 이유**: `imageEditor.js`가 Fabric.js 기반으로 가장 안정적이며, 오브젝트 선택/편집/삭제 등 고급 기능 지원.
|
||||
|
||||
### 1-2. imageEditor.js 핵심 기능
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────┐
|
||||
│ Canvas Editor (1300×800 모달 dialog) │
|
||||
├─────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ [Polyline] [Free] [Line] [Text] [Eraser] [Select] │ ← 도구 모음
|
||||
│ [Clear] [Apply] │
|
||||
│ │
|
||||
│ ┌─────────────────────────────────────────┐ │
|
||||
│ │ │ │
|
||||
│ │ Canvas (800×600) │ │
|
||||
│ │ │ │
|
||||
│ │ · 직각 고정 모드 (0°/90°/180°/270°) │ │
|
||||
│ │ · 프리뷰 라인 (대시) │ │
|
||||
│ │ · SVG 커서 (지우개) │ │
|
||||
│ │ │ │
|
||||
│ └─────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ 색상: [●검정] [●빨강] [●파랑] [●초록] [●주황] [●보라] │
|
||||
│ 선굵기: [━━━] 지우개크기: [━━━] │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
**그리기 모드**:
|
||||
|
||||
| 모드 | 키보드 | 동작 |
|
||||
|------|--------|------|
|
||||
| Polyline | (기본) | 클릭으로 점 찍기 → 선 연결, ESC로 종료 |
|
||||
| Free | — | 드래그로 자유 그리기 (PencilBrush) |
|
||||
| Line | L | 클릭+드래그 → 직선, 직각 고정 지원 |
|
||||
| Text | — | 클릭 → IText 생성 → 인라인 편집 |
|
||||
| Eraser | — | 드래그로 지우기 (SVG 원형 커서, 5~100px) |
|
||||
| Select | — | 오브젝트 선택/이동/삭제 (Delete키) |
|
||||
|
||||
**직각 고정 알고리즘**:
|
||||
```javascript
|
||||
// 각도 계산 후 0°/90°/180°/270° 중 가장 가까운 방향으로 스냅
|
||||
const angle = Math.atan2(dy, dx) * 180 / Math.PI;
|
||||
// → horizontal or vertical 결정
|
||||
```
|
||||
|
||||
### 1-3. 5130에서의 사용처
|
||||
|
||||
| 화면 | Canvas 크기 | 배경 이미지 | 용도 |
|
||||
|------|------------|-----------|------|
|
||||
| `bending/write_form.php` | 370×300 | ❌ 없음 | 전개도 그리기 |
|
||||
| `guiderail/list.php` | 800×600 | ✅ 제품 사진 위 | 치수 표기 |
|
||||
| `shutterbox/list.php` | 800×600 | ✅ 제품 사진 위 | 치수 표기 |
|
||||
| `bottombar/list.php` | 800×600 | ✅ 제품 사진 위 | 치수 표기 |
|
||||
|
||||
---
|
||||
|
||||
## 2. MNG 현재 Canvas 현황
|
||||
|
||||
### 2-1. 기존 Canvas 사용처 (참고용)
|
||||
|
||||
| 화면 | 라이브러리 | 용도 | 재활용 |
|
||||
|------|-----------|------|:---:|
|
||||
| `esign/sign/sign.blade.php` | signature_pad 4.1.7 | 전자서명 | ❌ 다른 용도 |
|
||||
| `document-templates/block-editor.blade.php` | Alpine.js DOM | 블록 드래그 | ❌ 다른 용도 |
|
||||
| `rd/fire-shutter-drawing/index.blade.php` | Pure Canvas | 방화셔터 도면 | ❌ 특화 로직 |
|
||||
|
||||
### 2-2. MNG 기술 스택
|
||||
|
||||
| 항목 | 현재 | Canvas 추가 시 |
|
||||
|------|------|---------------|
|
||||
| JS 프레임워크 | Alpine.js 3.x | Alpine.js 유지 |
|
||||
| HTMX | 1.9.10 | HTMX 유지 |
|
||||
| CSS | Tailwind + DaisyUI | 유지 |
|
||||
| Canvas 라이브러리 | ❌ 없음 | **Fabric.js 5.3.0 CDN 추가** |
|
||||
| 아이콘 | RemixIcon | RemixIcon (또는 Bootstrap Icons 병행) |
|
||||
|
||||
---
|
||||
|
||||
## 3. 적용 대상 화면
|
||||
|
||||
### 3-1. 기초관리 폼 (`/bending/base/{id}/edit`)
|
||||
|
||||
```
|
||||
현재 (1차 구현): 추가 (2차):
|
||||
┌──────────────────┐ ┌──────────────────┐
|
||||
│ [형상 이미지] │ │ [형상 이미지] │
|
||||
│ │ │ │
|
||||
│ ┌────────────┐ │ │ ┌────────────┐ │
|
||||
│ │ 미리보기 │ │ │ │ 미리보기 │ │
|
||||
│ └────────────┘ │ → │ └────────────┘ │
|
||||
│ │ │ │
|
||||
│ [파일 선택] │ │ [파일 선택] │
|
||||
│ [Ctrl+V 붙여넣기]│ │ [Ctrl+V 붙여넣기]│
|
||||
│ │ │ [✏️ 그리기] │ ← Canvas 모달
|
||||
│ │ │ │
|
||||
└──────────────────┘ └──────────────────┘
|
||||
```
|
||||
|
||||
### 3-2. 절곡품 폼 (`/bending/products/{id}/edit`)
|
||||
|
||||
```
|
||||
현재: 추가:
|
||||
┌──────────────────┐ ┌──────────────────┐
|
||||
│ [결합형태 이미지] │ │ [결합형태 이미지] │
|
||||
│ [파일 선택] │ → │ [파일 선택] │
|
||||
│ │ │ [✏️ 그리기] │ ← Canvas 모달
|
||||
└──────────────────┘ └──────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. 구현 설계
|
||||
|
||||
### 4-1. 파일 구조
|
||||
|
||||
```
|
||||
mng/
|
||||
├── public/js/
|
||||
│ └── canvas-editor.js ← imageEditor.js 이식 (MNG 맞춤)
|
||||
├── resources/views/
|
||||
│ └── components/
|
||||
│ └── canvas-editor.blade.php ← 모달 Blade 컴포넌트
|
||||
```
|
||||
|
||||
### 4-2. Fabric.js 로딩
|
||||
|
||||
```html
|
||||
<!-- layouts/app.blade.php 또는 필요한 페이지에서만 -->
|
||||
@stack('scripts')
|
||||
|
||||
<!-- canvas-editor 사용 페이지에서 -->
|
||||
@push('scripts')
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/5.3.0/fabric.min.js"></script>
|
||||
<script src="{{ asset('js/canvas-editor.js') }}"></script>
|
||||
@endpush
|
||||
```
|
||||
|
||||
### 4-3. Blade 컴포넌트 설계
|
||||
|
||||
```html
|
||||
<!-- 사용법 -->
|
||||
<x-canvas-editor
|
||||
target-input="image_data" {{-- hidden input name --}}
|
||||
:existing-image="$imageUrl" {{-- 기존 이미지 URL --}}
|
||||
:width="800"
|
||||
:height="600"
|
||||
/>
|
||||
|
||||
<!-- 렌더링 -->
|
||||
<dialog id="canvas-editor-dialog" class="modal">
|
||||
<div class="modal-box max-w-6xl p-0">
|
||||
<!-- 도구 모음 -->
|
||||
<div class="flex gap-1 p-2 bg-base-200 border-b">
|
||||
<button class="btn btn-sm" data-mode="polyline">Polyline</button>
|
||||
<button class="btn btn-sm" data-mode="free">Free</button>
|
||||
<button class="btn btn-sm" data-mode="line">Line</button>
|
||||
<button class="btn btn-sm" data-mode="text">Text</button>
|
||||
<button class="btn btn-sm btn-warning" data-mode="eraser">Eraser</button>
|
||||
<button class="btn btn-sm" data-mode="select">Select</button>
|
||||
<div class="divider divider-horizontal mx-0"></div>
|
||||
<input type="checkbox" class="toggle toggle-sm" id="right-angle" checked>
|
||||
<label for="right-angle" class="text-sm">직각고정</label>
|
||||
<div class="flex-1"></div>
|
||||
<button class="btn btn-sm btn-error" id="canvas-clear">초기화</button>
|
||||
<button class="btn btn-sm btn-success" id="canvas-apply">적용</button>
|
||||
</div>
|
||||
|
||||
<!-- Canvas -->
|
||||
<canvas id="fabric-canvas" width="800" height="600"></canvas>
|
||||
|
||||
<!-- 색상/옵션 -->
|
||||
<div class="flex gap-2 p-2 bg-base-200 border-t items-center">
|
||||
<!-- 색상 팔레트 -->
|
||||
<div class="flex gap-1">
|
||||
<button class="w-6 h-6 rounded-full bg-black" data-color="#000000"></button>
|
||||
<button class="w-6 h-6 rounded-full bg-red-600" data-color="#ff0000"></button>
|
||||
<button class="w-6 h-6 rounded-full bg-blue-600" data-color="#0000ff"></button>
|
||||
<button class="w-6 h-6 rounded-full bg-green-600" data-color="#00aa00"></button>
|
||||
<button class="w-6 h-6 rounded-full bg-orange-500" data-color="#ff8800"></button>
|
||||
<button class="w-6 h-6 rounded-full bg-purple-600" data-color="#800080"></button>
|
||||
</div>
|
||||
<div class="divider divider-horizontal mx-0"></div>
|
||||
<!-- 선 굵기/지우개 크기 -->
|
||||
<label class="text-sm">선:</label>
|
||||
<input type="range" min="1" max="10" value="2" class="range range-xs w-20" id="line-width">
|
||||
<label class="text-sm">지우개:</label>
|
||||
<input type="range" min="5" max="100" value="20" class="range range-xs w-20" id="eraser-size">
|
||||
</div>
|
||||
</div>
|
||||
<form method="dialog" class="modal-backdrop"><button>close</button></form>
|
||||
</dialog>
|
||||
```
|
||||
|
||||
### 4-4. canvas-editor.js 핵심 구조
|
||||
|
||||
```javascript
|
||||
class CanvasEditor {
|
||||
constructor(options) {
|
||||
this.canvas = null; // Fabric.js Canvas
|
||||
this.mode = 'polyline'; // 현재 모드
|
||||
this.drawColor = '#000000';
|
||||
this.lineWidth = 2;
|
||||
this.eraserSize = 20;
|
||||
this.rightAngle = true; // 직각 고정
|
||||
this.polyPoints = []; // polyline 점 목록
|
||||
this.previewLine = null; // 프리뷰 라인
|
||||
this.targetInput = options.targetInput; // 결과 저장할 input
|
||||
this.existingImage = options.existingImage;
|
||||
}
|
||||
|
||||
// 주요 메서드
|
||||
init() // Fabric.js 캔버스 초기화
|
||||
setMode(mode) // 모드 변경
|
||||
loadBackgroundImage(url) // 기존 이미지를 배경으로 로드
|
||||
handlePolyline(e) // polyline 클릭 처리
|
||||
handleLine(e) // 직선 드래그
|
||||
handleText(e) // 텍스트 배치
|
||||
setupEraser() // PencilBrush 지우개 모드
|
||||
snapToRightAngle(p1,p2) // 직각 고정 계산
|
||||
clear() // 캔버스 초기화
|
||||
apply() // Base64 → hidden input, 모달 닫기
|
||||
toDataURL() // PNG/JPEG 내보내기
|
||||
}
|
||||
```
|
||||
|
||||
### 4-5. 데이터 흐름
|
||||
|
||||
```
|
||||
[그리기 버튼 클릭]
|
||||
→ Canvas 모달 열기
|
||||
→ (기존 이미지 있으면) 배경 이미지로 로드
|
||||
→ 사용자 그리기 작업
|
||||
→ [적용] 클릭
|
||||
→ Canvas → Base64 (DataURL)
|
||||
→ hidden input에 저장
|
||||
→ 폼 submit 시 API 전송
|
||||
→ API: Base64 디코딩 → R2 저장 → file_id 반환
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. 이식 시 변경 사항
|
||||
|
||||
### 5-1. 5130 → MNG 차이점
|
||||
|
||||
| 항목 | 5130 (레거시) | MNG (SAM) |
|
||||
|------|-------------|-----------|
|
||||
| 모달 | `<dialog>` 직접 생성 | DaisyUI `modal` 컴포넌트 |
|
||||
| 아이콘 | Bootstrap Icons CDN | RemixIcon (이미 로드됨) |
|
||||
| CSS | 인라인 + Bootstrap | Tailwind + DaisyUI |
|
||||
| JS 구조 | 전역 함수 | Class 기반 모듈 |
|
||||
| 이벤트 | jQuery | Vanilla JS + Alpine.js |
|
||||
| 이미지 저장 | FormData → PHP 파일 저장 | Base64 → API → R2 |
|
||||
| 배경 이미지 | 별도 로드 로직 | `/files/{id}/view` 프록시 |
|
||||
|
||||
### 5-2. 제거할 것 (5130 전용)
|
||||
|
||||
```
|
||||
❌ jQuery 의존성 (MNG는 Alpine.js)
|
||||
❌ Bootstrap Icons CDN (RemixIcon으로 교체)
|
||||
❌ 전역 변수/함수 (Class로 캡슐화)
|
||||
❌ 인라인 CSS 스타일 (Tailwind 클래스로 교체)
|
||||
```
|
||||
|
||||
### 5-3. 추가할 것 (MNG 맞춤)
|
||||
|
||||
```
|
||||
✅ DaisyUI 모달 통합
|
||||
✅ Alpine.js x-data 바인딩 (모달 상태 관리)
|
||||
✅ RemixIcon 아이콘 매핑
|
||||
✅ HTMX 호환 (폼 submit 시 hx-post 지원)
|
||||
✅ Base64 → API 업로드 로직
|
||||
✅ 반응형 캔버스 크기 (모바일 대응 불필요 — MNG는 PC 전용)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. 아이콘 매핑 (Bootstrap Icons → RemixIcon)
|
||||
|
||||
| 기능 | Bootstrap Icons | RemixIcon |
|
||||
|------|----------------|-----------|
|
||||
| Polyline | `bi-vector-pen` | `ri-pen-nib-line` |
|
||||
| Free Draw | `bi-brush` | `ri-brush-line` |
|
||||
| Line | `bi-slash-lg` | `ri-subtract-line` |
|
||||
| Text | `bi-type` | `ri-text` |
|
||||
| Eraser | `bi-eraser-fill` | `ri-eraser-line` |
|
||||
| Select | `bi-cursor-text` | `ri-cursor-line` |
|
||||
| Clear | (텍스트) | `ri-delete-bin-line` |
|
||||
| Apply | (텍스트) | `ri-check-line` |
|
||||
|
||||
---
|
||||
|
||||
## 7. 작업 순서
|
||||
|
||||
```
|
||||
7-1. Fabric.js CDN 추가 (@push('scripts'))
|
||||
7-2. canvas-editor.js 작성 (imageEditor.js 기반 이식)
|
||||
7-3. canvas-editor.blade.php 컴포넌트 생성
|
||||
7-4. 기초관리 폼에 [그리기] 버튼 + 컴포넌트 통합
|
||||
7-5. 절곡품 폼에 동일 적용
|
||||
7-6. API 연동 (Base64 → 이미지 업로드)
|
||||
7-7. 테스트 (그리기 → 저장 → 재로드 → 편집)
|
||||
```
|
||||
|
||||
### 예상 파일 변경
|
||||
|
||||
| 파일 | 변경 내용 |
|
||||
|------|----------|
|
||||
| `public/js/canvas-editor.js` | 🆕 신규 (imageEditor.js 이식) |
|
||||
| `resources/views/components/canvas-editor.blade.php` | 🆕 신규 (모달 컴포넌트) |
|
||||
| `resources/views/bending/base/form.blade.php` | 수정 — [그리기] 버튼 추가 |
|
||||
| `resources/views/bending/products/form.blade.php` | 수정 — [그리기] 버튼 추가 |
|
||||
| `resources/views/layouts/app.blade.php` | 확인 — `@stack('scripts')` 존재 여부 |
|
||||
|
||||
---
|
||||
|
||||
## 8. 주의사항
|
||||
|
||||
### 아키텍처
|
||||
|
||||
- ✅ MNG는 **샘플 확인용** — 동일 로직을 React에도 적용 예정
|
||||
- ✅ `canvas-editor.js`는 **프레임워크 무관** Class로 작성 → React 포팅 용이
|
||||
- ✅ Fabric.js는 CDN으로 로드 (npm 설치 불필요 — MNG는 Vite 빌드 최소화)
|
||||
- ❌ drawingModule.js (966줄) 이식 불필요 — imageEditor.js로 충분
|
||||
|
||||
### 기존 코드 보호
|
||||
|
||||
- ⚠️ 기존 이미지 업로드 로직 유지 (그리기는 **추가** 옵션)
|
||||
- ⚠️ 기존 Ctrl+V 붙여넣기 유지
|
||||
- ⚠️ `canvas-editor.js`는 새 파일 — 기존 JS 무변경
|
||||
|
||||
### 성능
|
||||
|
||||
- ⚠️ Fabric.js 5.3.0 = ~800KB (CDN gzip ~200KB) — 필요 페이지에서만 로드
|
||||
- ⚠️ Base64 이미지 크기 → JPEG 변환 (PNG 대비 1/3~1/5 크기)
|
||||
|
||||
---
|
||||
|
||||
## 관련 문서
|
||||
|
||||
| 문서 | 경로 |
|
||||
|------|------|
|
||||
| Step 3 MNG 화면 (이미지 전략) | `step3-MNG화면.md` §7 |
|
||||
| 레거시 분석 | `legacy-guiderail-analysis.md` |
|
||||
| 5130 imageEditor.js | `5130/js/imageEditor.js` |
|
||||
| 5130 drawingModule.js | `5130/js/drawingModule.js` |
|
||||
|
||||
---
|
||||
|
||||
**최종 업데이트**: 2026-03-18
|
||||
@@ -294,9 +294,294 @@ BD-XX-XXX 품목이 `items` 테이블에 등록만 되어 있고, **절곡품
|
||||
4. **전개도 데이터 구조** — 치수/연신율/합계 JSON 저장 방안 설계
|
||||
5. **이미지 업로드 기능** — 절곡품별 전개도 이미지 관리
|
||||
|
||||
---
|
||||
|
||||
## 6. API 구현 완료 현황 (2026-03-16)
|
||||
|
||||
### 6.1 절곡품 마스터 API (`/api/v1/bending-items`)
|
||||
|
||||
| Method | Path | 설명 | 상태 |
|
||||
|--------|------|------|------|
|
||||
| GET | `/api/v1/bending-items` | 목록 (필터+페이지네이션) | ✅ 완료 |
|
||||
| GET | `/api/v1/bending-items/filters` | 필터 옵션 (드롭다운용) | ✅ 완료 |
|
||||
| GET | `/api/v1/bending-items/{id}` | 상세 | ✅ 완료 |
|
||||
| POST | `/api/v1/bending-items` | 등록 | ✅ 완료 |
|
||||
| PUT | `/api/v1/bending-items/{id}` | 수정 | ✅ 완료 |
|
||||
| DELETE | `/api/v1/bending-items/{id}` | 삭제 | ✅ 완료 |
|
||||
|
||||
**API 파일 목록**:
|
||||
|
||||
| 파일 | 설명 |
|
||||
|------|------|
|
||||
| `app/Http/Controllers/Api/V1/BendingItemController.php` | 컨트롤러 |
|
||||
| `app/Services/BendingItemService.php` | 서비스 (OPTION_KEYS 정의) |
|
||||
| `app/Http/Resources/Api/V1/BendingItemResource.php` | 응답 리소스 |
|
||||
| `app/Http/Requests/Api/V1/BendingItemIndexRequest.php` | 목록 검증 |
|
||||
| `app/Http/Requests/Api/V1/BendingItemStoreRequest.php` | 등록 검증 |
|
||||
| `app/Http/Requests/Api/V1/BendingItemUpdateRequest.php` | 수정 검증 |
|
||||
| `routes/api/v1/production.php` | 라우트 정의 (127~135행) |
|
||||
|
||||
### 6.2 이미지 업로드 API (`/api/v1/items/{id}/files`)
|
||||
|
||||
| Method | Path | 설명 | 상태 |
|
||||
|--------|------|------|------|
|
||||
| POST | `/api/v1/items/{id}/files` | 업로드 (`field_key=bending_diagram`) | ✅ 완료 |
|
||||
| GET | `/api/v1/items/{id}/files` | 파일 목록 (`?field_key=bending_diagram`) | ✅ 완료 |
|
||||
| DELETE | `/api/v1/items/{id}/files/{fileId}` | 파일 삭제 | ✅ 완료 |
|
||||
| GET | `/api/v1/files/{id}/view` | 인라인 보기 (이미지 표시) | ✅ 완료 |
|
||||
| GET | `/api/v1/files/{id}/download` | 다운로드 | ✅ 완료 |
|
||||
|
||||
**R2 저장 경로**: `{tenant_id}/items/{year}/{month}/{hex}.{ext}`
|
||||
**예시**: `287/items/2026/03/1b4eba14ff5a832b.jpg`
|
||||
|
||||
### 6.3 API 응답 구조
|
||||
|
||||
#### 절곡품 상세 (`GET /api/v1/bending-items/{id}`)
|
||||
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"message": "조회 성공",
|
||||
"data": {
|
||||
"id": 15862,
|
||||
"code": "BD-BE-30",
|
||||
"name": "하단마감재(스크린) EGI 3000mm",
|
||||
"item_type": "PT",
|
||||
"item_category": "BENDING",
|
||||
"unit": "EA",
|
||||
"is_active": true,
|
||||
"item_name": "하단마감재",
|
||||
"item_sep": "스크린",
|
||||
"item_bending": "하단마감재",
|
||||
"item_spec": "60*40",
|
||||
"material": "EGI 1.55T",
|
||||
"model_name": null,
|
||||
"model_UA": "인정",
|
||||
"search_keyword": null,
|
||||
"rail_width": null,
|
||||
"registration_date": "2025-07-21",
|
||||
"author": "개발자",
|
||||
"memo": "메모",
|
||||
"exit_direction": null,
|
||||
"front_bottom_width": null,
|
||||
"box_width": null,
|
||||
"box_height": null,
|
||||
"bendingData": [
|
||||
{ "no": 1, "input": 15, "rate": null, "sum": 15, "color": false, "aAngle": false },
|
||||
{ "no": 2, "input": 14, "rate": "-1", "sum": 28, "color": false, "aAngle": false },
|
||||
{ "no": 3, "input": 40, "rate": "-1", "sum": 67, "color": false, "aAngle": false }
|
||||
],
|
||||
"prefix": "BE",
|
||||
"length_code": "30",
|
||||
"length_mm": 3000,
|
||||
"width_sum": 193,
|
||||
"bend_count": 6,
|
||||
"created_at": "2026-02-21 19:47:01",
|
||||
"updated_at": "2026-03-16 21:11:12"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 필터 옵션 (`GET /api/v1/bending-items/filters`)
|
||||
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"data": {
|
||||
"item_sep": ["스크린", "철재"],
|
||||
"item_bending": ["가이드레일", "케이스", "하단마감재", "마구리", "L-BAR"],
|
||||
"material": ["EGI 1.15T", "EGI 1.55T", "SUS 1.2T", "SUS 1.5T"],
|
||||
"model_UA": ["비인정", "인정"],
|
||||
"model_name": ["KSS01", "KSS02", "KSE01"]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 6.4 MNG 관리 화면 (완료)
|
||||
|
||||
| 화면 | URL | 설명 |
|
||||
|------|-----|------|
|
||||
| 목록 | `/bending/base` | 필터 + 페이지네이션 |
|
||||
| 등록 | `/bending/base/create` | 폼 + 전개도 테이블 + 이미지 업로드 |
|
||||
| 상세 | `/bending/base/{id}` | 읽기 전용 |
|
||||
| 수정 | `/bending/base/{id}/edit` | 수정 모드 + 이미지 교체 |
|
||||
|
||||
### 6.5 레거시 분류 조건 분석
|
||||
|
||||
`item_bending` 컬럼으로 타입 구분 (같은 bending 테이블 사용):
|
||||
|
||||
| `item_bending` 값 | 전용 필드 | 레거시 디렉토리 |
|
||||
|-------------------|----------|----------------|
|
||||
| `가이드레일` | `rail_width` | `/bending/` |
|
||||
| `케이스` | `exit_direction`, `box_width`, `box_height`, `front_bottom_width` | `/shutterbox/` |
|
||||
| `하단마감재` | 없음 (공통 필드만) | `/bottombar/` |
|
||||
| `마구리` | 없음 | - |
|
||||
| `L-BAR` | 없음 | - |
|
||||
| `보강평철` | 없음 | - |
|
||||
| `연기차단재` | 없음 | - |
|
||||
|
||||
---
|
||||
|
||||
## 7. React 연동 시 참고사항
|
||||
|
||||
### 7.1 서버 액션 추가 필요
|
||||
|
||||
React에 `/api/v1/bending-items` 전용 서버 액션이 없음. 추가 필요:
|
||||
|
||||
```
|
||||
예상 파일: src/components/bending/actions.ts
|
||||
|
||||
필요 함수:
|
||||
- fetchBendingItems(params) → GET /api/v1/bending-items
|
||||
- fetchBendingFilters() → GET /api/v1/bending-items/filters
|
||||
- fetchBendingItem(id) → GET /api/v1/bending-items/{id}
|
||||
- createBendingItem(data) → POST /api/v1/bending-items
|
||||
- updateBendingItem(id, data) → PUT /api/v1/bending-items/{id}
|
||||
- deleteBendingItem(id) → DELETE /api/v1/bending-items/{id}
|
||||
- uploadBendingImage(itemId, file) → POST /api/v1/items/{id}/files
|
||||
```
|
||||
|
||||
### 7.2 bendingData 필드 매핑 (API → React)
|
||||
|
||||
API 응답의 `bendingData`와 기존 React `BendingDetail` 타입 불일치:
|
||||
|
||||
| API 필드 | API 타입 | React 기존 타입 (`BendingDetail`) | 조치 |
|
||||
|----------|---------|----------------------------------|------|
|
||||
| `no` | integer | `no: number` | ✅ 일치 |
|
||||
| `input` | numeric | `input: number` | ✅ 일치 |
|
||||
| `rate` | string \| null | `elongation: number` | ⚠️ 이름+타입 다름 |
|
||||
| `sum` | numeric | `sum: number` | ✅ 일치 |
|
||||
| `color` | boolean | `shaded: boolean` | ⚠️ 이름 다름 |
|
||||
| `aAngle` | boolean | `aAngle?: number` | ⚠️ 타입 다름 |
|
||||
| - | - | `id: string` | React에만 존재 (클라이언트 전용) |
|
||||
| - | - | `calculated: number` | React에만 존재 (클라이언트 계산값) |
|
||||
|
||||
**권장**: React 타입을 API에 맞추거나, 변환 레이어 추가
|
||||
```typescript
|
||||
// API → React 변환 예시
|
||||
function transformBendingData(apiData: ApiBendingData[]): BendingDetail[] {
|
||||
return apiData.map((d, i) => ({
|
||||
id: `detail-${i}`,
|
||||
no: d.no,
|
||||
input: d.input,
|
||||
elongation: d.rate ? parseFloat(d.rate) : -1, // rate → elongation
|
||||
calculated: d.input + (d.rate ? parseFloat(d.rate) : 0),
|
||||
sum: d.sum,
|
||||
shaded: d.color, // color → shaded
|
||||
aAngle: d.aAngle ? 1 : 0, // boolean → number
|
||||
}));
|
||||
}
|
||||
```
|
||||
|
||||
### 7.3 인증 방식
|
||||
|
||||
API는 현재 **Bearer 토큰 없이 X-TENANT-ID 헤더**로 동작 (화이트리스트):
|
||||
- `api/v1/bending-items`, `api/v1/bending-items/*`
|
||||
- `api/v1/items/*/files`
|
||||
- `api/v1/files/*/view`, `api/v1/files/*/download`
|
||||
|
||||
React는 **HttpOnly Cookie + Next.js 프록시**로 인증하므로, Bearer 토큰이 자동 전달됨.
|
||||
React 연동 시 화이트리스트 의존 없이 정상 인증 경로로 동작할 것.
|
||||
|
||||
### 7.4 이미지 표시 경로
|
||||
|
||||
```
|
||||
React에서 이미지 표시:
|
||||
프록시 경로: /api/proxy/files/{fileId}/view
|
||||
→ Next.js API Route가 Bearer 토큰 붙여서
|
||||
→ API: GET /api/v1/files/{fileId}/view
|
||||
→ R2에서 stream
|
||||
```
|
||||
|
||||
### 7.5 Update 시 code unique 검증
|
||||
|
||||
`BendingItemUpdateRequest`에 자기 자신 제외 unique 체크 누락:
|
||||
```php
|
||||
// 현재 (미흡)
|
||||
'code' => 'sometimes|string|max:100',
|
||||
|
||||
// 수정 필요
|
||||
'code' => 'sometimes|string|max:100|unique:items,code,' . $this->route('id'),
|
||||
```
|
||||
|
||||
### 7.6 React API 호환성 검증 결과 (2026-03-17)
|
||||
|
||||
#### 호환 항목 (API 수정 불필요)
|
||||
|
||||
| 항목 | 상태 | 비고 |
|
||||
|------|------|------|
|
||||
| 응답 래핑 `{success, message, data}` | ✅ 호환 | ApiResponse 헬퍼 공용 |
|
||||
| 페이지네이션 구조 | ✅ 호환 | `toPaginationMeta()` 재사용 가능 |
|
||||
| 에러 응답 (422/404/500) | ✅ 호환 | 동일 에러 핸들링 구조 |
|
||||
| Null 처리 | ✅ 호환 | 선택적 필드 패턴 일치 |
|
||||
| 날짜 형식 | ✅ 호환 | `Y-m-d` 동일 |
|
||||
| snake_case → camelCase | ✅ 호환 | 기존 `transformItemFromApi()` 재사용 |
|
||||
|
||||
#### React 측 작업 필요 항목
|
||||
|
||||
**1. bendingData 필드 매핑** (Server Action 레벨)
|
||||
|
||||
| API 응답 (`bendingData`) | React 타입 (`BendingDetail`) | 조치 |
|
||||
|--------------------------|------------------------------|------|
|
||||
| `rate` (string\|null) | `elongation` (number) | 이름+타입 변환 |
|
||||
| `color` (boolean) | `shaded` (boolean) | 이름 변환 |
|
||||
| `aAngle` (boolean) | `aAngle` (number) | 타입 변환 |
|
||||
| `input`, `sum`, `no` | 동일 | ✅ 일치 |
|
||||
|
||||
변환 예시:
|
||||
```typescript
|
||||
function transformBendingData(apiData: ApiBendingData[]): BendingDetail[] {
|
||||
return apiData.map((d, i) => ({
|
||||
id: `detail-${i}`,
|
||||
no: d.no,
|
||||
input: d.input,
|
||||
elongation: d.rate ? parseFloat(d.rate) : -1,
|
||||
calculated: d.input + (d.rate ? parseFloat(d.rate) : 0),
|
||||
sum: d.sum,
|
||||
shaded: d.color,
|
||||
aAngle: d.aAngle ? 1 : 0,
|
||||
}));
|
||||
}
|
||||
```
|
||||
|
||||
**2. GuiderailModel 타입 + API 클라이언트 신규 작성**
|
||||
- React에 `GuiderailModel` 관련 타입 없음
|
||||
- `components[]`, `material_summary` 필드 구조 정의 필요
|
||||
- Server Action: `fetchGuiderailModels()`, `fetchGuiderailModel(id)` 등
|
||||
|
||||
**3. 파일 URL 프록시 처리**
|
||||
- API: `/api/v1/files/{id}/view`
|
||||
- React: `/api/proxy/files/{id}/view` (Next.js 프록시 경로)
|
||||
|
||||
#### 인증 방식 차이 (자동 호환)
|
||||
|
||||
| 호출자 | X-API-KEY | Bearer | tenant_id 소스 | 비고 |
|
||||
|--------|-----------|--------|---------------|------|
|
||||
| **MNG** | ✅ | ❌ | X-TENANT-ID 헤더 (`ensureContext`) | 현재 |
|
||||
| **React** | ✅ (프록시) | ✅ (쿠키) | Bearer → User → userTenants | 향후 |
|
||||
|
||||
React는 Next.js 프록시가 HttpOnly 쿠키에서 Bearer 토큰을 읽어 자동 첨부하므로,
|
||||
API의 `allowWithoutAuth` 화이트리스트에 의존하지 않고 정상 인증 경로로 동작함.
|
||||
`ensureContext()`는 Bearer 없을 때만 동작하는 fallback이라 충돌 없음.
|
||||
|
||||
### 7.7 MNG 부품 추가 시 리다이렉트 수정 (2026-03-17)
|
||||
|
||||
**문제**: `/bending/cases/{id}/edit`에서 부품 추가 시 `form.submit()` → 컨트롤러 `update()`가 show 페이지로 redirect, edit 모드 종료됨
|
||||
|
||||
**수정 내용**:
|
||||
- `form.blade.php`: `submitAndStayEdit()` 함수 추가 — hidden input `_redirect=edit` 세팅 후 submit
|
||||
- `BendingProductController::update()`: `_redirect=edit`이면 edit 페이지로 리다이렉트
|
||||
- `movePart()` 순서 변경도 동일 패턴 적용 (`location.reload()` → `submitAndStayEdit()`)
|
||||
|
||||
---
|
||||
|
||||
### 관련 문서
|
||||
|
||||
- 통합 마스터 플랜: `docs/dev/dev_plans/integrated-master-plan.md`
|
||||
- Phase 2 (절곡 분석/설계): `docs/dev/dev_plans/integrated-phase-2.md`
|
||||
- Phase 3 (절곡 검사, 완료): `docs/dev/dev_plans/integrated-phase-3.md`
|
||||
- 품목 정책: `docs/rules/item-policy.md`
|
||||
- 품목 정책: `docs/rules/item-policy.md`
|
||||
|
||||
---
|
||||
|
||||
**최종 업데이트**: 2026-03-17
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user