Files
sam-docs/requests/equipment-frontend-request.md
김보곤 9c17850782 docs: [equipment] 사진 API 스펙 업데이트 (GCS→R2)
- 프론트엔드 요청 문서: 사진 업로드 API 상세 스펙 추가
- multipart/form-data files[] 배열 형식 명시
- 검증 규칙, Request/Response 예시 추가
- GCS 언급을 Cloudflare R2로 수정
- features/equipment README 동일 수정
2026-03-12 13:47:48 +09:00

25 KiB

설비관리 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 페이지 번호

응답:

{
  "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 — 드롭다운 데이터

응답:

{
  "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 — 대시보드 통계

응답:

{
  "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 — 활성 점검 주기 조회

응답:

{
  "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:

{
  "source_cycle": "daily",
  "target_cycles": ["weekly", "monthly"]
}

응답:

{
  "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 특정 설비만

응답 구조 (핵심):

{
  "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:

{
  "equipment_id": 1,
  "template_item_id": 10,
  "check_date": "2026-03-12",
  "cycle": "daily"
}

응답:

{
  "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:

{
  "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:

{
  "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:

{
  "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:

{
  "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"
    }
  ]
}

프론트엔드 구현 참고:

// 다중 파일 업로드 예시
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:

{
  "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에서 동적 로드

사진 관리 (수정 화면):

  • 설비 상세/수정 화면에서 사진 업로드/삭제 가능
  • 최대 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 12월, 34월, ..., 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_typeexternal(외주)일 때만 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 처리

6. 공통 응답 포맷

모든 API 응답은 다음 구조를 따릅니다:

{
  "success": true,
  "message": "성공/에러 메시지",
  "data": { ... }
}

에러 시:

{
  "success": false,
  "message": "에러 메시지",
  "errors": {
    "equipment_code": ["설비코드는 필수입니다."]
  }
}

7. 참고 사항

MNG R&D 화면 확인

개발서버 MNG에서 기존 구현을 확인할 수 있습니다:

  • URL: https://admin.codebridge-x.com/equipment
  • 대시보드, 등록대장, 점검 그리드, 수리이력 모두 동작하는 상태

개발서버 API 테스트

# 설비 목록 조회 예시
curl -H "X-Api-Key: <API_KEY>" \
     -H "Authorization: Bearer <TOKEN>" \
     "https://api.dev.codebridge-x.com/api/v1/equipment?per_page=5"

구현 순서 제안

  1. 1단계: 설비 CRUD (목록 → 등록 → 상세 → 수정) — 기본 DataTable + 폼
  2. 2단계: 수리이력 (목록 → 등록) — 1단계와 유사한 패턴
  3. 3단계: 점검 그리드 — 가장 복잡, 동적 그리드 + 셀 토글
  4. 4단계: 대시보드 — 통계 카드 + 간단한 차트

관련 문서


최종 업데이트: 2026-03-12