docs: [제품검사] FQC 문서 시스템 계획 + 스냅샷 Lazy Snapshot 반영
- fqc-document-system-plan.md: FormRequest 상태 수정, Phase 2.4 Lazy Snapshot 확정, 참고 파일 추가 - document-snapshot-architecture-plan.md: Lazy Snapshot 캡처 원칙 추가 - server-access-management.md 신규 - README.md 수정 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -53,6 +53,7 @@
|
||||
2. rendered_html이 있으면 무조건 그것을 사용 (완전한 스냅샷)
|
||||
3. 구조화 데이터는 편집/검색/통계용으로 병행 유지
|
||||
4. React에서만 문서 렌더링 책임 → MNG는 출력만 담당
|
||||
5. Lazy Snapshot: 조회 시 rendered_html 없으면 자동 캡처 → 저장 (점진적 스냅샷 전환)
|
||||
```
|
||||
|
||||
### 1.4 변경 승인 정책
|
||||
@@ -76,8 +77,9 @@
|
||||
|
||||
### 2.2 React 현황 (구현 완료)
|
||||
|
||||
rendered_html 캡처 원칙: **입력 화면에서 저장할 때** 해당 데이터의 "문서 뷰"를 캡처.
|
||||
보기(readOnly)에서는 캡처하지 않음.
|
||||
#### 캡처 원칙 A: 입력 시 저장 (Active Capture)
|
||||
|
||||
입력 화면에서 저장할 때 해당 데이터의 "문서 뷰"를 캡처. 보기(readOnly)에서는 캡처하지 않음.
|
||||
|
||||
| Save Path | 파일 | 방식 | 캡처 대상 |
|
||||
|-----------|------|------|----------|
|
||||
@@ -90,6 +92,40 @@ rendered_html 캡처 원칙: **입력 화면에서 저장할 때** 해당 데이
|
||||
> 이후 InspectionReportModal을 edit 모드로 열어 저장하면 캡처됨.
|
||||
> 향후 오프스크린 렌더링으로 확장 가능 (템플릿 로딩 등 async 의존성 해결 필요).
|
||||
|
||||
#### 캡처 원칙 B: 조회 시 자동 캡처 (Lazy Snapshot)
|
||||
|
||||
문서 조회(view/readOnly) 시 `rendered_html`이 없으면 자동 캡처하여 백그라운드 저장.
|
||||
|
||||
```
|
||||
문서 View 시
|
||||
├── rendered_html 있음 → 그대로 표시 (기존)
|
||||
└── rendered_html 없음 → 동적 렌더링 완료 후 캡처 → API로 rendered_html 저장
|
||||
(다음 조회부터는 스냅샷 사용)
|
||||
```
|
||||
|
||||
**적용 대상**:
|
||||
- readonly 문서 (제품검사 요청서 등 — 입력 없이 자동 생성되는 문서)
|
||||
- 마이그레이션 이전 기존 데이터 (rendered_html이 NULL인 과거 문서)
|
||||
- WorkerScreen 인라인 저장 후 아직 모달에서 저장하지 않은 문서
|
||||
|
||||
**구현 방식**:
|
||||
```typescript
|
||||
// 문서 표시 컴포넌트에서 (DocumentViewer, Modal 등)
|
||||
useEffect(() => {
|
||||
if (document && !document.rendered_html && isContentRendered) {
|
||||
const html = contentWrapperRef.current?.innerHTML
|
||||
|| await captureRenderedHtml(DocumentComponent, props);
|
||||
patchDocumentRenderedHtml(document.id, html); // 백그라운드 저장
|
||||
}
|
||||
}, [document, isContentRendered]);
|
||||
```
|
||||
|
||||
**고려사항**:
|
||||
- 사용자 UX 영향 없음 (백그라운드 비동기 저장)
|
||||
- 조회 권한만 있는 사용자도 트리거 가능해야 함
|
||||
- 동시 접속 시 중복 저장 가능 → 같은 HTML이므로 실질적 문제 없음
|
||||
- 캡처 타이밍: template 로드 + 데이터 바인딩 완료 후 (isContentRendered 판단 필요)
|
||||
|
||||
### 2.3 API 현황 (구현 완료)
|
||||
|
||||
- Document 모델 `$fillable`에 `rendered_html` 포함 ✅
|
||||
@@ -298,6 +334,7 @@ Phase 1과 Phase 3의 MNG 코드 수정은 병렬 가능 (fallback 유지).
|
||||
| 2026-03-06 | Phase 2 보정 | API UpsertRequest rendered_html 누락 수정, DocumentService upsert() rendered_html 전달 추가 | UpsertRequest.php, DocumentService.php | ✅ |
|
||||
| 2026-03-06 | Phase 2 보정 | ImportInspection: 입력폼 캡처 → 오프스크린 성적서 렌더링으로 변경 | ImportInspectionInputModal.tsx, capture-rendered-html.tsx | ✅ |
|
||||
| 2026-03-06 | Phase 2 보정 | InspectionReportModal readOnly 자동 캡처 useEffect 제거 | InspectionReportModal.tsx | ✅ |
|
||||
| 2026-03-06 | 원칙 확장 | Lazy Snapshot 패턴 추가 — 조회 시 rendered_html 없으면 자동 캡처/저장 | 아키텍처 원칙 | - |
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -135,7 +135,7 @@
|
||||
| 2.1 | mng에 제품검사 요청서 template 신규 등록 (시더) | ⏳ | 시더 방식 확정 |
|
||||
| 2.2 | React 동적 렌더링 컴포넌트 구현 | ⏳ | 하드코딩 → 양식 기반 전환 |
|
||||
| 2.3 | 요청서 문서 생성 API 연동 | ⏳ | quality_document 생성 시 자동 생성 확정 |
|
||||
| 2.4 | rendered_html 스냅샷 저장 적용 | ⏳ | |
|
||||
| 2.4 | rendered_html 스냅샷 저장 적용 (Lazy Snapshot) | ⏳ | 요청서 최초 조회 시 rendered_html 없으면 자동 캡처/저장 |
|
||||
|
||||
### Phase 3: 통합 및 정리
|
||||
|
||||
@@ -202,9 +202,13 @@ Phase 2: 제품검사 요청서 신규
|
||||
│ ├── 개소 데이터 자동 매핑 (quality_document_locations → 사전고지 테이블)
|
||||
│ └── 파일: api/app/Services/QualityDocumentService.php
|
||||
│
|
||||
└── Step 2.4: rendered_html 스냅샷
|
||||
├── 요청서 저장/표시 시 HTML 캡처
|
||||
└── API 전송 및 저장
|
||||
└── Step 2.4: rendered_html 스냅샷 (Lazy Snapshot 패턴)
|
||||
├── 요청서는 readonly 문서 → "입력 시 저장" 캡처 불가
|
||||
├── Lazy Snapshot 적용: 요청서 최초 조회 시 rendered_html 없으면 자동 캡처
|
||||
├── captureRenderedHtml 유틸리티 활용 (react/src/lib/utils/capture-rendered-html.tsx)
|
||||
├── 또는 contentWrapperRef.innerHTML로 렌더링 완료 후 캡처
|
||||
├── 백그라운드 API 호출로 rendered_html 저장 (PATCH /v1/documents/{id} 또는 upsert)
|
||||
└── 참조: document-snapshot-architecture-plan.md 캡처 원칙 B
|
||||
|
||||
Phase 3: 통합 및 정리
|
||||
├── InspectionDetail.tsx에서 모달 연동 통합 테스트
|
||||
@@ -391,9 +395,14 @@ const methodFreqCoverage = buildCompositeRowSpan(sectionItems);
|
||||
- method+frequency `공인시험기관|1회/5년` → 9행 (내화3 + 차연1 + 개폐5)
|
||||
- `작동테스트`는 method/frequency 빈값 → 병합 대상 아님
|
||||
|
||||
#### 5.1.4 rendered_html 캡처 패턴 (참조: 중간검사)
|
||||
#### 5.1.4 rendered_html 캡처 패턴
|
||||
|
||||
**`react/src/components/production/WorkOrders/documents/InspectionReportModal.tsx`** (라인 341-366):
|
||||
> **캡처 원칙** (document-snapshot-architecture-plan.md 참조):
|
||||
> - **Active Capture**: 입력 화면에서 저장할 때 캡처. readOnly에서는 캡처하지 않음.
|
||||
> - **Lazy Snapshot**: 조회 시 rendered_html 없으면 자동 캡처/저장 (점진적 전환).
|
||||
> FQC 성적서는 Active Capture (편집 모드 저장 시), 요청서는 Lazy Snapshot (readonly 자동 캡처) 적용.
|
||||
|
||||
**패턴 1: innerHTML 직접 캡처** (참조: 중간검사 `InspectionReportModal.tsx` 라인 341-366)
|
||||
|
||||
```typescript
|
||||
// 1. ref 정의
|
||||
@@ -414,7 +423,19 @@ const handleSave = async () => {
|
||||
</div>
|
||||
```
|
||||
|
||||
**FQC에 적용할 위치**: `InspectionReportModal.tsx`의 FQC 모드 저장 로직에 동일 패턴 추가.
|
||||
**패턴 2: 오프스크린 렌더링** (참조: 수입검사 `ImportInspectionInputModal.tsx`)
|
||||
|
||||
```typescript
|
||||
import { captureRenderedHtml } from '@/lib/utils/capture-rendered-html';
|
||||
|
||||
// 문서 컴포넌트를 오프스크린으로 렌더링 → HTML 캡처
|
||||
const html = await captureRenderedHtml(DocumentComponent, documentProps);
|
||||
```
|
||||
|
||||
- 유틸리티 위치: `react/src/lib/utils/capture-rendered-html.tsx` (flushSync + createRoot)
|
||||
- 문서가 화면에 렌더링되지 않는 상황에서 캡처할 때 사용 (Lazy Snapshot에 활용 가능)
|
||||
|
||||
**FQC 성적서 적용 (Phase 1.3)**: 패턴 1 사용. `InspectionReportModal.tsx`의 FQC 모드 저장 로직에 동일 패턴 추가.
|
||||
현재 `fqcActions.ts`의 `saveFqcDocument()`는 `POST /v1/documents/upsert` 사용 → body에 `rendered_html` 추가.
|
||||
|
||||
#### 5.1.5 FqcDocumentContent.tsx 현재 구조 (보완 대상)
|
||||
@@ -647,6 +668,7 @@ DocumentTemplate (제품검사 요청서)
|
||||
| 1 | 성적서 양식 보완 방안 | **방안 C 확정** — 하드코딩 데이터를 template items로 완전 이관. SectionItem에 method/frequency/measurement_type 이미 존재 | mng, react | ✅ 확정 |
|
||||
| 2 | 요청서 template 생성 방법 | **시더 확정** — ProductInspectionRequestTemplateSeeder 작성 (mng/database/seeders/). 재현성 + 버전 관리 | mng | ✅ 확정 |
|
||||
| 3 | 요청서 문서 생성 시점 | **자동 생성 확정** — quality_document 생성 시 자동. 기존 성적서 bulk create 패턴과 동일 | api | ✅ 확정 |
|
||||
| 4 | 요청서 rendered_html 캡처 방식 | **Lazy Snapshot 확정** — 요청서는 readonly 문서이므로 최초 조회 시 rendered_html 없으면 자동 캡처/저장. `captureRenderedHtml` 유틸리티 또는 `contentWrapperRef.innerHTML` 활용 | react | ✅ 확정 |
|
||||
|
||||
---
|
||||
|
||||
@@ -664,7 +686,7 @@ DocumentTemplate (제품검사 요청서)
|
||||
| API (DocumentService create/update) | ✅ | rendered_html 조건부 저장 |
|
||||
| React (InspectionReportModal) | ✅ | contentWrapperRef.innerHTML 캡처 |
|
||||
| MNG (show/print.blade.php) | ✅ | rendered_html 우선 출력 + fallback |
|
||||
| FormRequest 검증 | ⚠️ | rendered_html 검증 규칙 확인 필요 |
|
||||
| FormRequest 검증 | ✅ | StoreRequest/UpdateRequest/UpsertRequest 모두 nullable string 검증 완료 |
|
||||
|
||||
### mng template 구조 핵심
|
||||
- `DocumentTemplateSectionItem` 필드: category, item, standard, tolerance, standard_criteria, method, measurement_type, frequency_n, frequency_c, frequency, regulation, field_values(JSON)
|
||||
@@ -689,6 +711,7 @@ DocumentTemplate (제품검사 요청서)
|
||||
| 2026-03-06 | 에이전트 조사 | template ID 65 현황, rendered_html 현황, mng 구조 분석 반영 | - | - |
|
||||
| 2026-03-06 | 자기완결성 보완 | 시더 데이터, rowSpan 로직, rendered_html 캡처 패턴, API 구조, 타입 정의 추가 | - | - |
|
||||
| 2026-03-06 | 방법론 수정 6건 | ①컬럼 아키텍처 재설계(template 2개+시각 8컬럼) ②프론트 타입 갭 보완 ③rowSpan 복합키 알고리즘 ④Template ID 안정성 대책 ⑤measurement_type=none 처리 ⑥시더 위치 명확화(mng) | - | - |
|
||||
| 2026-03-06 | 스냅샷 아키텍처 정합성 검토 반영 | ①FormRequest 검증 ✅ 확인 ②Phase 2.4 Lazy Snapshot 전략 확정 ③참고 파일 추가(capture-rendered-html.tsx, UpsertRequest) ④캡처 원칙(Active/Lazy) 명시 ⑤오프스크린 렌더링 참조 추가 | 5.1.4, 6.1, 9 | - |
|
||||
|
||||
---
|
||||
|
||||
@@ -724,6 +747,8 @@ DocumentTemplate (제품검사 요청서)
|
||||
|------|------|----------|
|
||||
| `react/src/components/production/WorkOrders/documents/TemplateInspectionContent.tsx` | 중간검사 동적 렌더링 (참조 모델) | 917-999: 컬럼타입별 렌더링, 1105-1183: renderComplexCells() |
|
||||
| `react/src/components/production/WorkOrders/documents/InspectionReportModal.tsx` | 중간검사 모달 (rendered_html 캡처 패턴) | 167: contentWrapperRef, 341-366: handleSave+innerHTML |
|
||||
| `react/src/lib/utils/capture-rendered-html.tsx` | 오프스크린 렌더링 유틸리티 (flushSync+createRoot) | Phase 2.4 Lazy Snapshot에서 활용 가능 |
|
||||
| `react/src/components/material/ReceivingManagement/ImportInspectionInputModal.tsx` | 수입검사 오프스크린 캡처 참조 | captureRenderedHtml 사용 예시 |
|
||||
|
||||
### API (수정 대상)
|
||||
| 파일 | 역할 | 핵심 라인 |
|
||||
@@ -732,6 +757,7 @@ DocumentTemplate (제품검사 요청서)
|
||||
| `api/app/Services/QualityDocumentService.php` | 품질관리 문서 서비스 | 176-209: store(), 749-799: requestDocument(), 804-868: resultDocument() |
|
||||
| `api/app/Models/Documents/Document.php` | 문서 모델 | 76: $fillable에 rendered_html |
|
||||
| `api/app/Models/Qualitys/QualityDocumentLocation.php` | 개소 모델 | fillable: post_width, post_height, change_reason, inspection_data |
|
||||
| `api/app/Http/Requests/Document/UpsertRequest.php` | documents/upsert 검증 | rendered_html nullable string 검증 완료 |
|
||||
|
||||
### MNG (확인/수정 대상)
|
||||
| 파일 | 역할 |
|
||||
|
||||
Reference in New Issue
Block a user