# 설비관리 React 프론트엔드 구현 요청 > **작성일**: 2026-03-12 > **요청자**: R&D실 > **상태**: API 백엔드 완료, React 프론트엔드 구현 요청 --- ## 1. 개요 설비관리(Equipment Management) 기능의 React 프론트엔드를 구현해 주세요. API 백엔드(26개 엔드포인트)는 개발 완료되어 개발서버에 배포된 상태입니다. - **API 문서**: Swagger 미작성 상태이므로 아래 엔드포인트 스펙을 참고 - **MNG 참고**: `mng/resources/views/equipment/` 에 Blade/HTMX로 구현된 R&D 버전이 있으므로 화면 구성 참고 가능 - **API Base URL**: `https://api.dev.codebridge-x.com/api/v1` --- ## 2. 구현 화면 목록 | # | 화면 | 경로 (제안) | 우선순위 | 비고 | |---|------|------------|:--------:|------| | 1 | 설비 목록 | `/equipment` | 1순위 | DataTable + 필터 | | 2 | 설비 등록 | `/equipment/create` | 1순위 | 폼 | | 3 | 설비 상세 | `/equipment/:id` | 1순위 | 탭 3개 (기본정보/점검항목/수리이력) | | 4 | 설비 수정 | `/equipment/:id/edit` | 1순위 | 등록과 동일 폼 + 기존 사진 관리 | | 5 | 점검 그리드 | `/equipment/inspections` | 2순위 | 동적 그리드, 셀 토글 (가장 복잡) | | 6 | 수리이력 목록 | `/equipment/repairs` | 2순위 | DataTable + 필터 | | 7 | 수리이력 등록 | `/equipment/repairs/create` | 2순위 | 폼 | | 8 | 설비 대시보드 | `/equipment/dashboard` | 3순위 | 통계 카드 + 차트 | --- ## 3. API 엔드포인트 상세 ### 3.1 설비 CRUD (9개) #### `GET /v1/equipment` — 목록 조회 (페이지네이션) **Query Parameters:** | 파라미터 | 타입 | 필수 | 기본값 | 설명 | |----------|------|:----:|--------|------| | `search` | string | — | — | 설비코드, 설비명 LIKE 검색 | | `status` | string | — | — | `active` / `idle` / `disposed` | | `production_line` | string | — | — | 생산라인 필터 | | `equipment_type` | string | — | — | 설비유형 필터 | | `sort_by` | string | — | `sort_order` | 정렬 컬럼 | | `sort_direction` | string | — | `asc` | `asc` / `desc` | | `per_page` | integer | — | `20` | 페이지당 개수 | | `page` | integer | — | `1` | 페이지 번호 | **응답:** ```json { "success": true, "message": "...", "data": { "current_page": 1, "data": [ { "id": 1, "equipment_code": "KD-M-001", "name": "포밍기#1", "equipment_type": "포밍기", "specification": "1200x800mm", "manufacturer": "제조사", "model_name": "모델A", "serial_no": "SN-001", "location": "1공장-1F", "production_line": "스라트", "purchase_date": "2020-01-15", "install_date": "2020-02-01", "purchase_price": "15000000.00", "useful_life": 10, "status": "active", "disposed_date": null, "manager_id": 1, "sub_manager_id": 2, "photo_path": null, "memo": "비고", "options": {}, "is_active": 1, "sort_order": 1, "manager": { "id": 1, "name": "홍길동" }, "sub_manager": { "id": 2, "name": "김철수" } } ], "total": 12, "per_page": 20, "last_page": 1 } } ``` --- #### `GET /v1/equipment/options` — 드롭다운 데이터 **응답:** ```json { "success": true, "data": { "equipment_types": ["포밍기", "미싱기", "샤링기", "V컷팅기", "절곡기", "프레스", "드릴", "기타"], "production_lines": ["스라트", "스크린", "절곡", "기타"], "statuses": ["active", "idle", "disposed"], "equipment_list": [ { "id": 1, "equipment_code": "KD-M-001", "name": "포밍기#1" } ] } } ``` > 설비 등록/수정 폼, 필터 드롭다운에 사용 --- #### `GET /v1/equipment/stats` — 대시보드 통계 **응답:** ```json { "success": true, "data": { "total": 12, "active": 10, "idle": 2, "disposed": 0 } } ``` --- #### `POST /v1/equipment` — 설비 등록 **Request Body (JSON):** | 필드 | 타입 | 필수 | 설명 | |------|------|:----:|------| | `equipment_code` | string | ✅ | 설비코드 (tenant 내 unique) | | `name` | string | ✅ | 설비명 | | `equipment_type` | string | — | 설비유형 | | `specification` | string | — | 규격 | | `manufacturer` | string | — | 제조사 | | `model_name` | string | — | 모델명 | | `serial_no` | string | — | 제조번호 | | `location` | string | — | 위치 | | `production_line` | string | — | 생산라인 | | `purchase_date` | date | — | 구입일 (YYYY-MM-DD) | | `install_date` | date | — | 설치일 (YYYY-MM-DD) | | `purchase_price` | number | — | 구입가격 | | `useful_life` | integer | — | 내용연수 | | `status` | string | — | `active`(기본) / `idle` / `disposed` | | `disposed_date` | date | — | 폐기일 | | `manager_id` | integer | — | 담당자 ID (users FK) | | `sub_manager_id` | integer | — | 부담당자 ID (users FK) | | `memo` | string | — | 비고 | | `options` | object | — | 확장 속성 JSON | | `sort_order` | integer | — | 정렬순서 | **응답:** 생성된 설비 객체 (관계 포함) --- #### `GET /v1/equipment/{id}` — 설비 상세 **응답에 포함되는 관계 데이터:** - `manager` — 담당자 (User) - `subManager` — 부담당자 (User) - `inspectionTemplates` — 점검항목 배열 - `repairs` — 수리이력 배열 - `processes` — 연결 공정 배열 - `photos` — 사진 파일 배열 --- #### `PUT /v1/equipment/{id}` — 설비 수정 Body는 등록과 동일 (변경할 필드만 전송 가능) --- #### `DELETE /v1/equipment/{id}` — 설비 삭제 (Soft Delete) --- #### `POST /v1/equipment/{id}/restore` — 삭제된 설비 복원 --- #### `PATCH /v1/equipment/{id}/toggle` — 활성/비활성 토글 `is_active` 값이 반전됨 --- ### 3.2 점검 템플릿 (5개) #### `GET /v1/equipment/{id}/templates` — 활성 점검 주기 조회 **응답:** ```json { "data": ["daily", "weekly", "monthly"] } ``` > 해당 설비에 점검항목이 등록된 주기 목록 반환 --- #### `POST /v1/equipment/{id}/templates` — 점검항목 등록 **Request Body:** | 필드 | 타입 | 필수 | 설명 | |------|------|:----:|------| | `inspection_cycle` | string | ✅ | 주기: `daily`/`weekly`/`monthly`/`bimonthly`/`quarterly`/`semiannual` | | `item_no` | string | ✅ | 항목번호 | | `check_point` | string | ✅ | 점검개소 (예: 겉모양) | | `check_item` | string | ✅ | 점검항목 (예: 청결상태) | | `check_timing` | string | — | 시기: `operating` / `stopped` | | `check_frequency` | string | — | 주기 (예: 1회/일) | | `check_method` | string | — | 점검방법 | | `sort_order` | integer | — | 정렬순서 | --- #### `PUT /v1/equipment/templates/{templateId}` — 점검항목 수정 --- #### `DELETE /v1/equipment/templates/{templateId}` — 점검항목 삭제 --- #### `POST /v1/equipment/{id}/templates/copy` — 점검항목 다른 주기에 복사 **Request Body:** ```json { "source_cycle": "daily", "target_cycles": ["weekly", "monthly"] } ``` **응답:** ```json { "data": { "copied": 5, "skipped": 2, "source_count": 7, "target_cycles": ["weekly", "monthly"] } } ``` --- ### 3.3 점검 (5개) — 가장 핵심 기능 #### `GET /v1/equipment/inspections` — 점검 그리드 데이터 **Query Parameters:** | 파라미터 | 타입 | 필수 | 기본값 | 설명 | |----------|------|:----:|--------|------| | `cycle` | string | — | `daily` | 점검주기 | | `period` | string | — | 현재월 | daily: `YYYY-MM`, 그 외: `YYYY` | | `production_line` | string | — | — | 생산라인 필터 | | `equipment_id` | integer | — | — | 특정 설비만 | **응답 구조 (핵심):** ```json { "data": [ { "equipment": { "id": 1, "equipment_code": "KD-M-001", "name": "포밍기#1" }, "templates": [ { "id": 10, "item_no": "1", "check_point": "겉모양", "check_item": "청결상태", "check_timing": "operating", "check_method": "육안 확인" } ], "inspection": { "id": 5, "overall_judgment": "OK", "inspector_id": 1, "repair_note": "", "issue_note": "" }, "details": { "10_2026-03-01": { "result": "good" }, "10_2026-03-02": { "result": "bad" }, "10_2026-03-03": { "result": null } }, "labels": { "1": "1", "2": "2", "3": "3", ..., "31": "31" }, "can_inspect": true } ] } ``` > **details 키 형식**: `{template_item_id}_{check_date}` > **labels**: 그리드 열 헤더 (주기별로 다름) > **can_inspect**: 현재 사용자가 이 설비를 점검할 권한이 있는지 --- #### `PATCH /v1/equipment/inspections/toggle` — 셀 클릭 (결과 순환) **Request Body:** ```json { "equipment_id": 1, "template_item_id": 10, "check_date": "2026-03-12", "cycle": "daily" } ``` **응답:** ```json { "data": { "result": "good", "symbol": "○" } } ``` **결과 순환 규칙:** ``` (빈칸) → good(○) → bad(X) → repaired(△) → (빈칸) → ... ``` --- #### `PATCH /v1/equipment/inspections/set-result` — 결과 직접 설정 toggle과 같은 Body + `result` 필드 추가 (`good` / `bad` / `repaired` / `null`) --- #### `PATCH /v1/equipment/inspections/notes` — 메모/판정 업데이트 **Request Body:** ```json { "equipment_id": 1, "year_month": "2026-03", "cycle": "daily", "overall_judgment": "OK", "inspector_id": 1, "repair_note": "수리 사항...", "issue_note": "이상 사항..." } ``` --- #### `DELETE /v1/equipment/inspections/reset` — 점검 데이터 초기화 **Request Body:** ```json { "equipment_id": 1, "cycle": "daily", "period": "2026-03" } ``` --- ### 3.4 수리이력 (4개) #### `GET /v1/equipment/repairs` — 목록 (페이지네이션) **Query Parameters:** | 파라미터 | 타입 | 설명 | |----------|------|------| | `equipment_id` | integer | 설비 필터 | | `repair_type` | string | `internal`(사내) / `external`(외주) | | `date_from` | date | 수리일 시작 | | `date_to` | date | 수리일 종료 | | `search` | string | 설비명/수리내용 검색 | | `per_page` | integer | 페이지당 개수 (기본 20) | --- #### `POST /v1/equipment/repairs` — 수리이력 등록 **Request Body:** | 필드 | 타입 | 필수 | 설명 | |------|------|:----:|------| | `equipment_id` | integer | ✅ | 설비 ID | | `repair_date` | date | ✅ | 수리일 (YYYY-MM-DD) | | `repair_type` | string | — | `internal`(사내) / `external`(외주) | | `repair_hours` | number | — | 수리시간 (0.5 단위) | | `description` | string | — | 수리내용 | | `cost` | number | — | 수리비용 (원) | | `vendor` | string | — | 외주업체 (repair_type=external 시) | | `repaired_by` | integer | — | 수리자 ID | | `memo` | string | — | 비고 | --- #### `PUT /v1/equipment/repairs/{id}` — 수정 #### `DELETE /v1/equipment/repairs/{id}` — 삭제 --- ### 3.5 사진 (3개) #### `GET /v1/equipment/{id}/photos` — 사진 목록 **Response:** ```json { "success": true, "message": "데이터를 불러왔습니다.", "data": [ { "id": 1, "file_name": "IMG_001.jpg", "file_path": "1/equipment/2026/03/a1b2c3d4e5f6g7h8.jpg", "file_url": "/api/v1/files/1/download", "file_size": 524288, "mime_type": "image/jpeg", "created_at": "2026-03-12 10:30:00" } ] } ``` #### `POST /v1/equipment/{id}/photos` — 사진 업로드 > **multipart/form-data** 형식으로 직접 업로드한다. 별도 파일 업로드 API를 거치지 않는다. **Request (multipart/form-data):** | 필드 | 타입 | 필수 | 설명 | |------|------|:----:|------| | `files[]` | file[] | O | 이미지 파일 배열 (다중 업로드) | **검증 규칙:** - 허용 확장자: `jpg, jpeg, png, gif, bmp, webp` - 파일당 최대 크기: 10MB - 설비당 최대 사진 수: 10장 (현재 사진 수 + 업로드 수 ≤ 10) **Response:** ```json { "success": true, "message": "사진이 업로드되었습니다.", "data": [ { "id": 15, "file_name": "IMG_001.jpg", "file_path": "1/equipment/2026/03/a1b2c3d4e5f6g7h8.jpg", "file_url": "/api/v1/files/15/download", "file_size": 524288, "mime_type": "image/jpeg", "created_at": "2026-03-12 10:30:00" } ] } ``` **프론트엔드 구현 참고:** ```typescript // 다중 파일 업로드 예시 const formData = new FormData(); selectedFiles.forEach(file => formData.append('files[]', file)); await api.post(`/v1/equipment/${id}/photos`, formData, { headers: { 'Content-Type': 'multipart/form-data' } }); ``` #### `DELETE /v1/equipment/{id}/photos/{fileId}` — 사진 삭제 **Response:** ```json { "success": true, "message": "삭제되었습니다.", "data": { "file_id": 15, "deleted": true } } ``` --- ## 4. 화면별 구현 가이드 ### 4.1 설비 목록 ``` ┌────────────────────────────────────────────────────┐ │ 설비 등록대장 [+ 설비 등록] │ ├────────────────────────────────────────────────────┤ │ 필터: [검색] [상태 ▼] [라인 ▼] [유형 ▼] [검색] │ ├────────────────────────────────────────────────────┤ │ 설비번호 │ 설비명 │ 유형 │ 라인 │ 상태 │ 담당자 │…│ │ KD-M-001│ 포밍기 │포밍기│스라트│🟢가동│ 홍길동│…│ │ KD-M-002│ 미싱기 │미싱기│스크린│🟡유휴│ 김철수│…│ ├────────────────────────────────────────────────────┤ │ < 1 2 3 > │ └────────────────────────────────────────────────────┘ ``` **테이블 컬럼:** | 컬럼 | 필드 | 정렬 | |------|------|------| | 설비번호 | `equipment_code` | center | | 설비명 | `name` | left | | 유형 | `equipment_type` | center | | 위치 | `location` | center | | 생산라인 | `production_line` | center | | 상태 | `status` | center, Badge | | 담당자 정 | `manager.name` | center | | 담당자 부 | `sub_manager.name` | center | | 구입일 | `purchase_date` | center | | 액션 | — | 상세보기/수정/삭제 | **상태 Badge 색상:** | 상태 | 라벨 | 색상 | |------|------|------| | `active` | 가동 | 초록 | | `idle` | 유휴 | 노랑 | | `disposed` | 폐기 | 회색 | --- ### 4.2 설비 등록/수정 폼 **4개 섹션:** 1. **기본정보**: 설비코드*, 설비명*, 설비유형(select), 규격 2. **제조사 정보**: 제조사, 모델명, 제조번호 3. **설치 정보**: 위치, 생산라인(select), 구입일, 설치일, 구입가격, 내용연수 4. **관리자/비고**: 담당자(select), 부담당자(select), 상태(select), 비고(textarea) **드롭다운 고정값:** ``` 설비유형: 포밍기 / 미싱기 / 샤링기 / V컷팅기 / 절곡기 / 프레스 / 드릴 / 기타 생산라인: 스라트 / 스크린 / 절곡 / 기타 상태: 가동(active) / 유휴(idle) / 폐기(disposed) ``` > 담당자/부담당자 드롭다운은 사용자 API에서 동적 로드 **사진 관리 (등록/수정 화면):** - **등록 화면**: 사진을 미리 선택하면 대기열에 추가 + 미리보기 표시. 설비 저장 완료 후 자동 업로드. 드래그앤드롭, Ctrl+V 클립보드 붙여넣기 지원. - **수정 화면**: 기존 사진 조회/삭제 + 새 사진 추가 가능 - 최대 10장 제한 (설비당) --- ### 4.3 설비 상세 (탭 3개) ``` ← 뒤로 KD-M-001 포밍기#1 [🟢가동] [수정] ───────────────────────────────────────────── [기본정보] [점검항목] [수리이력] ───────────────────────────────────────────── ``` **탭 1: 기본정보** - 설비 상세 정보 (읽기 전용) - 사진 갤러리 - 연결된 공정 목록 **탭 2: 점검항목** - 주기별 탭 (daily/weekly/monthly/bimonthly/quarterly/semiannual) - 각 주기의 점검항목 테이블 (항목번호, 점검개소, 점검항목, 시기, 주기, 점검방법) - 항목 추가/수정/삭제 기능 - "다른 주기에 복사" 기능 **탭 3: 수리이력** - 해당 설비의 수리이력 테이블 --- ### 4.4 점검 그리드 (가장 복잡한 화면) ``` 설비 점검표 [일일] [주간] [월간] [2개월] [분기] [반기] ← 주기 탭 필터: [년월/연도] [라인 ▼] [설비 ▼] [조회] ┌──────────┬──────────┬───┬───┬───┬───┬──────┐ │ 설비 │ 점검항목 │ 1 │ 2 │ 3 │...│ 판정 │ │(고정열) │(고정열) │(토)│(일)│(월)│ │ │ ├──────────┼──────────┼───┼───┼───┼───┼──────┤ │ KD-M-001 │ 청결상태 │ — │ — │ ○ │ │ 합격 │ │ 포밍기#1 │ 윤활상태 │ — │ — │ X │ │ │ │(rowspan) │ 볼트이완 │ — │ — │ △ │ │ │ ├──────────┼──────────┼───┼───┼───┼───┼──────┤ │ KD-M-002 │ 청결상태 │ — │ — │ ○ │ │ 합격 │ └──────────┴──────────┴───┴───┴───┴───┴──────┘ 범례: ○ 양호 X 이상 △ 수리완료 ━ 비근무일 ``` **핵심 동작:** 1. **셀 클릭**: `PATCH /inspections/toggle` 호출 → 결과 순환 (빈칸→○→X→△→빈칸) 2. **비근무일**: 주말(토/일) + holidays 테이블 등록 휴일 → 클릭 불가, 음영 처리 (daily만 적용) 3. **고정 열**: 설비/점검항목 열은 가로 스크롤 시 고정 (sticky) 4. **자동 판정**: 비근무일 제외, 모든 점검항목이 good 또는 repaired면 "합격" 5. **rowspan**: 동일 설비의 여러 점검항목은 설비명을 세로 병합 **주기별 그리드 열 구성:** | 주기 | period 형식 | 열 개수 | 열 라벨 | |------|------------|---------|---------| | daily | `YYYY-MM` | 28~31 | 1, 2, 3, ..., 31 (요일 표시) | | weekly | `YYYY` | 52 | 1주, 2주, ..., 52주 | | monthly | `YYYY` | 12 | 1월, 2월, ..., 12월 | | bimonthly | `YYYY` | 6 | 1~2월, 3~4월, ..., 11~12월 | | quarterly | `YYYY` | 4 | 1분기, 2분기, 3분기, 4분기 | | semiannual | `YYYY` | 2 | 상반기, 하반기 | **점검 결과 심볼/색상:** | result | 심볼 | 색상 | |--------|------|------| | `good` | ○ | 초록 (`text-green-600`) | | `bad` | X | 빨강 (`text-red-600`) | | `repaired` | △ | 노랑 (`text-yellow-600`) | | `null` | (빈칸) | — | --- ### 4.5 수리이력 **목록 필터:** - 검색 (설비명/수리내용) - 설비 선택 (드롭다운) - 보전구분 (`internal` 사내 / `external` 외주) - 기간 (시작일 ~ 종료일) **테이블 컬럼:** | 컬럼 | 필드 | 형식 | |------|------|------| | 수리일 | `repair_date` | YYYY-MM-DD | | 설비 | `equipment.name` | 텍스트 | | 보전구분 | `repair_type` | Badge (사내: 파랑, 외주: 주황) | | 수리시간 | `repair_hours` | "2h" 또는 "-" | | 수리내용 | `description` | 텍스트 (40자 제한) | | 비용 | `cost` | 통화 형식 (1,000,000원) | | 외주업체 | `vendor` | 텍스트 또는 "-" | | 액션 | — | 수정/삭제 | **등록 폼 특이사항:** - `repair_type`이 `external`(외주)일 때만 `vendor`(외주업체) 필드 표시 - `repair_hours`는 0.5 단위 입력 (step=0.5) --- ### 4.6 대시보드 ``` ┌────────────┬────────────┬────────────┬────────────┐ │ 총 설비 │ 가동 중 │ 유휴 │ 폐기 │ │ 12대 │ 10대 │ 2대 │ 0대 │ └────────────┴────────────┴────────────┴────────────┘ ┌──────────────────────────┬──────────────────────────┐ │ 이번달 점검 현황 │ 설비 유형별 현황 │ │ 점검 대상: 12대 │ 포밍기 ████████ 5 │ │ 점검 완료: 8대 │ 절곡기 █████ 3 │ │ 완료율: 66% [████░░] │ 미싱기 ███ 2 │ │ 이상 발견: 2건 │ 기타 ██ 2 │ └──────────────────────────┴──────────────────────────┘ ┌────────────────────────────────────────────────────┐ │ 최근 수리이력 [전체보기 →] │ ├─────────┬──────────┬──────────┬───────────┬────────┤ │ 수리일 │ 설비 │ 보전구분 │ 수리내용 │ 비용 │ │ 03-08 │ KD-M-01 │ 사내 │ 베어링 교체│ 50,000│ └─────────┴──────────┴──────────┴───────────┴────────┘ ``` > `GET /v1/equipment/stats` 로 상단 4개 카드 데이터를 가져옴. > 점검 현황과 유형별 차트는 stats 응답을 가공하여 표시. --- ## 5. 비즈니스 규칙 ### 5.1 점검 권한 - 관리자(admin): 모든 설비 점검 가능 - 일반 사용자: 자신이 `manager_id` 또는 `sub_manager_id`인 설비만 점검 가능 - `can_inspect` 플래그로 API가 알려줌 → false면 셀 클릭 비활성화 ### 5.2 비근무일 제한 (daily만) - **일일 점검에서만** 주말(토/일) 및 등록된 휴일에 점검 기록 불가 - 해당 셀은 음영 처리 + 클릭 비활성화 - 그 외 주기(weekly/monthly 등)에는 제한 없음 ### 5.3 점검 결과 순환 셀 클릭 시 결과가 순환: ``` (빈칸) → good(○) → bad(X) → repaired(△) → (빈칸) ``` ### 5.4 자동 판정 - 도래한 날짜 중 비근무일 제외 - 모든 항목-날짜 조합이 `good` 또는 `repaired` → **합격(OK)** - 하나라도 `bad` 또는 미점검 → **불합격(NG)** ### 5.5 설비 사진 - 최대 10장 (설비당) - Cloudflare R2에 저장 (`Storage::disk('r2')`) - `POST /v1/equipment/{id}/photos`로 직접 업로드 (`files[]` multipart) - 허용 확장자: jpg, jpeg, png, gif, bmp, webp - 파일당 최대 10MB - 사진 URL: `/api/v1/files/{id}/download` - 삭제 시 soft delete 처리 - **등록 시 사진 업로드 흐름**: 사진을 미리 선택(대기열) → 설비 저장 → 생성된 ID로 사진 자동 업로드 - **수정 시 사진 관리**: 페이지 로드 시 기존 사진 표시 → 추가/삭제 즉시 반영 --- ## 6. 공통 응답 포맷 모든 API 응답은 다음 구조를 따릅니다: ```json { "success": true, "message": "성공/에러 메시지", "data": { ... } } ``` 에러 시: ```json { "success": false, "message": "에러 메시지", "errors": { "equipment_code": ["설비코드는 필수입니다."] } } ``` --- ## 7. 참고 사항 ### MNG R&D 화면 확인 개발서버 MNG에서 기존 구현을 확인할 수 있습니다: - **URL**: `https://admin.codebridge-x.com/equipment` - 대시보드, 등록대장, 점검 그리드, 수리이력 모두 동작하는 상태 ### 개발서버 API 테스트 ```bash # 설비 목록 조회 예시 curl -H "X-Api-Key: " \ -H "Authorization: Bearer " \ "https://api.dev.codebridge-x.com/api/v1/equipment?per_page=5" ``` ### 구현 순서 제안 1. **1단계**: 설비 CRUD (목록 → 등록 → 상세 → 수정) — 기본 DataTable + 폼 2. **2단계**: 수리이력 (목록 → 등록) — 1단계와 유사한 패턴 3. **3단계**: 점검 그리드 — 가장 복잡, 동적 그리드 + 셀 토글 4. **4단계**: 대시보드 — 통계 카드 + 간단한 차트 --- ## 관련 문서 - [설비관리 기능 문서](../features/equipment/README.md) - [서비스 구축 계획](../dev/dev_plans/equipment-service-build-plan.md) --- **최종 업데이트**: 2026-03-12 (설비 등록 시 사진 업로드 기능 반영)