Files
sam-react-prod/claudedocs/item-master/[REF] api-requirements-items.md
byeongcheolryu 65a8510c0b fix: 품목기준관리 실시간 동기화 수정
- BOM 항목 추가/수정/삭제 시 섹션탭 즉시 반영
- 섹션 복제 시 UI 즉시 업데이트 (null vs undefined 이슈 해결)
- 항목 수정 기능 추가 (useTemplateManagement)
- 실시간 동기화 문서 추가

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-27 22:19:50 +09:00

26 KiB

품목 관리 API 요구사항 명세서

작성일: 2025-11-17 최종 수정: 2025-11-17 (v1.2) 대상: PHP/Laravel 백엔드 API 프론트엔드: Next.js 15 App Router 상태: 프론트엔드 구현 완료, 백엔드 API 대기 중


📋 목차

  1. 리스트 화면 API (품목 목록 조회)
  2. 품목 등록 화면 필요 데이터
  3. 품목 등록/수정 시 전송 데이터

1. 리스트 화면 API

1.1 품목 목록 조회 (GET)

엔드포인트: GET /api/items 또는 GET /api/items/paginated

참고:

  • /api/items - 전체 데이터 반환 (클라이언트 사이드 페이지네이션)
  • /api/items/paginated - 서버 사이드 페이지네이션 (권장)

Request Parameters (Query String)

파라미터 타입 필수 설명 예시
itemType string 품목 유형 필터 (FG/PT/SM/RM/CS) FG
search string 검색어 (품목코드, 품목명, 규격) 스크린
category1 string 대분류 필터 본체부품
category2 string 중분류 필터 가이드시스템
category3 string 소분류 필터 가이드레일
isActive boolean 활성 상태 필터 true
page integer 페이지 번호 (기본값: 1) 1
per_page integer 페이지당 항목 수 (기본값: 50) 50

Response Body

{
  "success": true,
  "data": [
    {
      "id": "1",
      "itemCode": "KD-FG-001",
      "itemName": "스크린 제품 A",
      "itemType": "FG",
      "unit": "EA",
      "specification": "2000x2000",
      "isActive": true,
      "category1": "본체부품",
      "category2": "가이드시스템",
      "category3": null,
      "purchasePrice": 100000,
      "salesPrice": 150000,
      "marginRate": 33.3,
      "processingCost": null,
      "laborCost": null,
      "installCost": null,

      // 제품(FG) 전용 필드
      "productName": "프리미엄 스크린",
      "productCategory": "SCREEN",
      "lotAbbreviation": "KD",
      "note": null,

      // 부품(PT) 전용 필드
      "partType": null,                 // "ASSEMBLY" | "BENDING" | "PURCHASED"
      "partUsage": null,                // "GUIDE_RAIL" | "BOTTOM_FINISH" | "CASE" | "DOOR" | "BRACKET" | "GENERAL"
      "installationType": null,         // 조립품: "벽면형" | "측면형"
      "assemblyType": null,             // 조립품: "M" | "T" | "C" | "D" | "S" | "U"
      "assemblyLength": null,           // 조립품: "2438" | "3000" | "3500" | "4000" | "4300"
      "material": null,                 // 절곡품: "EGI 1.55T" | "EGI 2.0T" | "SUS 1.2T" 등
      "length": null,                   // 절곡품: 길이/목함 (mm)
      "sideSpecWidth": null,            // 조립품: 측면 규격 가로 (mm)
      "sideSpecHeight": null,           // 조립품: 측면 규격 세로 (mm)

      // 버전 관리
      "currentRevision": 0,
      "isFinal": false,

      // 메타데이터
      "createdAt": "2025-01-10T00:00:00Z",
      "updatedAt": null
    }
  ],
  "pagination": {
    "current_page": 1,
    "last_page": 1,
    "per_page": 50,
    "total": 7
  }
}

리스트 화면에서 필수로 표시되는 필드

데스크톱 테이블 컬럼 (우선순위 순):

  1. id - 체크박스 및 번호에 사용
  2. itemCode - 품목코드 (배경색 표시)
  3. itemType - 품목유형 (색상별 Badge)
  4. partType - 부품유형 (PT 품목에서 Badge 추가 표시)
    • ASSEMBLY → "조립" (파란색 Badge)
    • BENDING → "절곡" (보라색 Badge)
    • PURCHASED → "구매" (녹색 Badge)
  5. itemName - 품목명
  6. specification - 규격
  7. unit - 단위 (Badge 표시)
  8. isActive - 품목 상태 (활성/비활성)

모바일 카드 레이아웃 (lg 미만):

  • 체크박스 + 품목코드 (코드 형식)
  • 품목유형 Badge + 부품유형 Badge (PT인 경우)
  • 품목명 (클릭 가능)
  • 규격 (있는 경우)
  • 단위 Badge
  • 액션 버튼 (조회/수정/삭제)

검색 및 필터링:

  • itemType - 탭 및 드롭다운 필터
  • itemCode, itemName, specification - 통합 검색

통계 카드:

  • 전체 품목 수
  • 품목 유형별 개수 (FG, PT, SM, RM, CS)

2. 품목 등록 화면 필요 데이터

2.1 공통 마스터 데이터 조회 (GET)

품목 등록 화면 진입 시 필요한 드롭다운 옵션 데이터

엔드포인트: GET /api/items/master-data

Response Body

{
  "success": true,
  "data": {
    // 단위 목록
    "units": ["EA", "SET", "KG", "M", "L", "BOX", "PCS"],

    // 제품 카테고리
    "productCategories": [
      { "code": "SCREEN", "label": "스크린" },
      { "code": "STEEL", "label": "철재" }
    ],

    // 부품 용도
    "partUsages": [
      { "code": "GUIDE_RAIL", "label": "가이드레일" },
      { "code": "BOTTOM_FINISH", "label": "하단마감재" },
      { "code": "CASE", "label": "케이스" },
      { "code": "DOOR", "label": "도어" },
      { "code": "BRACKET", "label": "브라켓" },
      { "code": "GENERAL", "label": "일반" }
    ],

    // 설치 유형
    "installationTypes": ["벽면형", "측면형"],

    // 조립품 종류
    "assemblyTypes": ["M", "T", "C", "D", "S", "U"],

    // 조립품 길이
    "assemblyLengths": ["2438", "3000", "3500", "4000", "4300"],

    // 재질 목록 (절곡품)
    "materials": [
      "EGI 1.55T",
      "EGI 2.0T",
      "SUS 1.2T",
      "SPHC-SD 1.6T"
    ],

    // 분류 체계
    "categories": {
      "본체부품": {
        "가이드시스템": ["가이드레일", "브라켓"],
        "케이스": ["상부케이스", "하부케이스"]
      },
      "구조재/부속품": {
        "볼트/너트": null,
        "와셔": null
      },
      "철강재": null
    }
  }
}

2.2 품목 상세 조회 (수정 모드용) (GET)

엔드포인트: GET /api/items/{itemCode}

URL 파라미터:

  • itemCode: 품목 코드 (예: KD-FG-001)

Response Body

{
  "success": true,
  "data": {
    // === 공통 필드 ===
    "id": "1",
    "itemCode": "KD-FG-001",
    "itemName": "스크린 제품 A",
    "itemType": "FG",
    "unit": "EA",
    "specification": "2000x2000",
    "isActive": true,

    // === 분류 ===
    "category1": "본체부품",
    "category2": "가이드시스템",
    "category3": null,

    // === 가격 정보 ===
    "purchasePrice": 100000,
    "salesPrice": 150000,
    "marginRate": 33.3,
    "processingCost": 20000,
    "laborCost": 15000,
    "installCost": 10000,

    // === 제품(FG) 전용 ===
    "productName": "프리미엄 스크린",
    "productCategory": "SCREEN",
    "lotAbbreviation": "KD",
    "note": "비고 내용",

    // === 부품(PT) 전용 - 조립품 ===
    "partType": "ASSEMBLY",
    "partUsage": "GUIDE_RAIL",
    "installationType": "벽면형",
    "assemblyType": "M",
    "assemblyLength": "2438",

    // === 부품(PT) 전용 - 절곡품 ===
    "bendingDiagram": "https://example.com/uploads/bending-diagram.png",
    "bendingDetails": [
      {
        "id": "bd-1",
        "no": 1,
        "input": 100,
        "elongation": -1,
        "calculated": 99,
        "sum": 99,
        "shaded": false,
        "aAngle": 90
      }
    ],
    "material": "EGI 1.55T",
    "length": "2000",

    // === 부품(PT) 전용 - 구매품 ===
    "electricOpenerPower": "220V",
    "electricOpenerCapacity": "300",
    "motorVoltage": "380V",

    // === BOM (자재명세서) ===
    "bom": [
      {
        "id": "bom-1",
        "childItemCode": "KD-PT-001",
        "childItemName": "가이드레일",
        "quantity": 2,
        "unit": "EA",
        "unitPrice": 35000,
        "quantityFormula": "H / 1000",
        "note": "비고"
      }
    ],

    // === 인정 정보 ===
    "certificationNumber": "인정번호-001",
    "certificationStartDate": "2025-01-01",
    "certificationEndDate": "2027-12-31",
    "specificationFile": "https://example.com/uploads/spec.pdf",
    "specificationFileName": "시방서.pdf",
    "certificationFile": "https://example.com/uploads/cert.pdf",
    "certificationFileName": "인정서.pdf",

    // === 메타데이터 ===
    "safetyStock": 10,
    "leadTime": 7,
    "currentRevision": 0,
    "isFinal": false,
    "createdAt": "2025-01-10T00:00:00Z",
    "updatedAt": "2025-01-12T00:00:00Z"
  }
}

2.3 BOM 품목 검색 (GET)

BOM 추가 시 하위 품목 검색용 - 2개의 분리된 API로 구현

2.3.1 품목 코드 검색 (자동완성)

엔드포인트: GET /api/items/search/codes

Query Parameters:

  • q: 검색어 (품목코드)
  • limit: 결과 개수 제한 (기본값: 10)

Response Body:

{
  "success": true,
  "data": ["KD-PT-001", "KD-PT-002", "KD-PT-003"]
}

2.3.2 품목명 검색 (자동완성)

엔드포인트: GET /api/items/search/names

Query Parameters:

  • q: 검색어 (품목명)
  • limit: 결과 개수 제한 (기본값: 10)

Response Body:

{
  "success": true,
  "data": [
    {
      "itemCode": "KD-PT-001",
      "itemName": "가이드레일"
    },
    {
      "itemCode": "KD-PT-002",
      "itemName": "가이드레일 브라켓"
    }
  ]
}

2.3.3 통합 품목 검색 (BOM 추가용)

엔드포인트: GET /api/items/search

Query Parameters:

  • q: 검색어 (품목코드 또는 품목명)
  • itemType: 품목 유형 필터 (선택)
  • limit: 결과 개수 제한 (기본값: 10)

Response Body:

{
  "success": true,
  "data": [
    {
      "itemCode": "KD-PT-001",
      "itemName": "가이드레일",
      "itemType": "PT",
      "partType": "BENDING",
      "unit": "EA",
      "specification": "2438mm",
      "purchasePrice": 35000,
      "salesPrice": 50000
    }
  ]
}

3. 품목 등록/수정 시 전송 데이터

3.1 품목 등록 (POST)

엔드포인트: POST /api/items

Content-Type: multipart/form-data (파일 업로드 포함 시)

Request Body

{
  // === 공통 필드 (모든 품목 유형) ===
  "itemCode": "KD-FG-001",          // 자동생성 또는 수동입력
  "itemName": "스크린 제품 A",
  "itemType": "FG",                 // FG/PT/SM/RM/CS
  "unit": "EA",
  "specification": "2000x2000",
  "isActive": true,

  // === 분류 ===
  "category1": "본체부품",
  "category2": "가이드시스템",
  "category3": null,

  // === 가격 정보 ===
  "purchasePrice": 100000,
  "salesPrice": 150000,
  "marginRate": 33.3,              // 자동계산 또는 수동입력
  "processingCost": 20000,
  "laborCost": 15000,
  "installCost": 10000,

  // === 제품(FG) 전용 필드 ===
  "productName": "프리미엄 스크린",
  "productCategory": "SCREEN",
  "lotAbbreviation": "KD",
  "note": "비고 내용",

  // === 부품(PT) 전용 필드 - 조립품 ===
  "partType": "ASSEMBLY",           // ASSEMBLY/BENDING/PURCHASED
  "partUsage": "GUIDE_RAIL",
  "installationType": "벽면형",
  "assemblyType": "M",
  "assemblyLength": "2438",

  // === 부품(PT) 전용 필드 - 절곡품 ===
  "material": "EGI 1.55T",
  "length": "2000",
  "bendingLength": "2000",
  "bendingDetails": [
    {
      "no": 1,
      "input": 100,
      "elongation": -1,
      "calculated": 99,
      "sum": 99,
      "shaded": false,
      "aAngle": 90
    }
  ],

  // === 부품(PT) 전용 필드 - 구매품 ===
  "electricOpenerPower": "220V",
  "electricOpenerCapacity": "300",
  "motorVoltage": "380V",
  "motorCapacity": "500",
  "chainSpec": "체인규격",

  // === BOM (자재명세서) ===
  "bom": [
    {
      "childItemCode": "KD-PT-001",
      "childItemName": "가이드레일",
      "quantity": 2,
      "unit": "EA",
      "unitPrice": 35000,
      "quantityFormula": "H / 1000",    // 수량 계산식 (선택)
      "note": "비고",

      // 절곡품 BOM인 경우
      "isBending": true,
      "width": 100,
      "bendingDetails": [...]
    }
  ],

  // === 인정 정보 (제품/부품) ===
  "certificationNumber": "인정번호-001",
  "certificationStartDate": "2025-01-01",
  "certificationEndDate": "2027-12-31",

  // === 메타데이터 ===
  "safetyStock": 10,
  "leadTime": 7,
  "isVariableSize": false,
  "currentRevision": 0,
  "isFinal": false
}

파일 업로드 (FormData)

const formData = new FormData();

// JSON 데이터
formData.append('data', JSON.stringify(itemData));

// 파일들
formData.append('specificationFile', specificationFile);  // 시방서
formData.append('certificationFile', certificationFile);  // 인정서
formData.append('bendingDiagram', bendingDiagramFile);    // 절곡품 전개도

Response Body (성공)

{
  "success": true,
  "message": "품목이 등록되었습니다.",
  "data": {
    "id": "1",
    "itemCode": "KD-FG-001",
    // ... 전체 품목 데이터
  }
}

Response Body (실패)

{
  "success": false,
  "message": "품목 등록에 실패했습니다.",
  "errors": {
    "itemName": ["품목명은 필수입니다."],
    "unit": ["단위는 필수입니다."]
  }
}

3.2 품목 수정 (PUT)

엔드포인트: PUT /api/items/{itemCode}

Request Body: 품목 등록과 동일 (변경된 필드만 전송 가능)

참고:

  • itemType은 수정 불가 (품목 유형 변경 시 신규 등록 필요)
  • 파일은 새로운 파일 업로드 시만 전송

3.3 품목 삭제 (DELETE)

엔드포인트: DELETE /api/items/{itemCode}

Response Body

{
  "success": true,
  "message": "품목이 삭제되었습니다."
}

4. 데이터 검증 규칙

4.1 공통 필수 필드

모든 품목 유형에서 필수:

  • itemType - 품목 유형
  • itemName - 품목명
  • unit - 단위
  • isActive - 활성 상태 (기본값: true)

4.2 제품(FG) 필수 필드

  • productName - 상품명
  • itemName - 품목명
  • itemCode - 자동생성: {productName}-{itemName}

4.3 부품(PT) 필수 필드

조립품 (ASSEMBLY):

  • itemName - 품목명
  • length - 길이
  • itemCode - 자동생성 규칙 있음

절곡품 (BENDING):

  • itemName - 품목명
  • length - 길이/목함
  • specification - 규격 (재질)
  • itemCode - 자동생성 규칙 있음

구매품 (PURCHASED):

  • itemName - 품목명
  • specification - 규격
  • itemCode - 자동생성 규칙 있음

4.4 부자재/원자재/소모품 (SM/RM/CS) 필수 필드

  • itemName - 품목명
  • unit - 단위
  • specification - 규격
  • itemCode - 자동생성 규칙 있음

5. 품목 코드 자동생성 규칙

5.1 제품 (FG)

형식: {상품명}-{품목명}

예시:

  • 상품명: 프리미엄 스크린
  • 품목명: 2000x2000
  • 결과: 프리미엄 스크린-2000x2000

5.2 부품 (PT) - 조립품

형식: KD-{설치유형코드}{조립종류}{길이}

예시:

  • 설치유형: 벽면형 → M
  • 조립종류: T
  • 길이: 2438
  • 결과: KD-MT2438

5.3 부품 (PT) - 절곡품

형식: {재질}-{길이/목함}

예시:

  • 재질: EGI 1.55T
  • 길이: 2000
  • 결과: EGI 1.55T-2000

5.4 부품 (PT) - 구매품

형식: {품목명}

예시: 전동개폐기 220V 300KG

5.5 부자재/원자재/소모품 (SM/RM/CS)

형식: 수동 입력 또는 {품목명}-{규격}

예시:

  • 품목명: 볼트
  • 규격: M6x20
  • 결과: 볼트-M6x20

6. 파일 업로드 요구사항

참조: /downloads/file_storage_implementation_guide.md - 파일 저장소 시스템 전체 구현 가이드

6.1 허용 파일 형식

기본 정책:

  • 최대 파일 크기: 20MB
  • 파일명 처리:
    • 사용자가 보는 이름 (display_name): 원본 파일명 유지
    • 실제 저장 이름 (stored_name): 64bit 난수 (16자 hex) + 확장자
파일 종류 허용 확장자 MIME 타입 비고
시방서 .pdf, .docx, .hwp, .jpg, .png application/pdf, application/vnd.openxmlformats-officedocument.wordprocessingml.document, application/x-hwp, image/jpeg, image/png 문서 및 이미지 형식 모두 지원
인정서 .pdf, .docx, .hwp, .jpg, .png application/pdf, application/vnd.openxmlformats-officedocument.wordprocessingml.document, application/x-hwp, image/jpeg, image/png 문서 및 이미지 형식 모두 지원
절곡품 전개도 .jpg, .png, .pdf image/jpeg, image/png, application/pdf 이미지 및 PDF 형식
기타 첨부 .xlsx, .xls, .csv, .zip, .rar application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, application/vnd.ms-excel, text/csv, application/zip, application/x-rar-compressed Excel, 압축 파일 등

차단 확장자 (보안):

exe, sh, bat, cmd, dwg, dxf, step, iges

6.2 파일 저장 경로

경로 구조 (테넌트별 분리):

storage/app/tenants/{tenant_id}/{folder_key}/{year}/{month}/{stored_name}

품목 관련 파일 경로 예시:

storage/app/tenants/1/product/2025/01/a1b2c3d4e5f6g7h8.pdf
storage/app/tenants/1/product/2025/01/i9j0k1l2m3n4o5p6.jpg

임시 업로드 경로 (temp 폴더):

storage/app/tenants/{tenant_id}/temp/{year}/{month}/{stored_name}

6.3 파일 업로드 프로세스

[Frontend] 파일 선택 → multipart/form-data 전송
    ↓
[Backend] 파일 검증
    - 확장자 체크 (허용 목록)
    - MIME 타입 검증
    - 파일 크기 체크 (20MB 이하)
    - 용량 체크 (테넌트 용량 확인)
    ↓
[Backend] temp 폴더에 임시 저장
    - 난수 파일명 생성 (16자 hex + 확장자)
    - 경로: /tenants/{id}/temp/{year}/{month}/{random}.{ext}
    - DB 저장 (is_temp=true, folder_id=NULL)
    ↓
[Response] { file_id, display_name, file_size, mime_type }
    ↓
[Frontend] 품목 등록 시 file_id 전송
    ↓
[Backend] 문서 저장 후 파일 이동
    - temp → product 폴더로 이동
    - DB 업데이트 (is_temp=false, folder_id, document_id)

6.4 파일 응답 형식

업로드 성공 응답:

{
  "success": true,
  "data": {
    "file_id": 123,
    "display_name": "시방서.pdf",
    "stored_name": "a1b2c3d4e5f6g7h8.pdf",
    "file_size": 1024000,
    "mime_type": "application/pdf",
    "file_type": "document",
    "is_temp": true,
    "created_at": "2025-01-17T10:00:00Z"
  }
}

파일 URL 형식:

GET /api/files/{file_id}/download
→ 파일 스트리밍 응답 (Content-Disposition: attachment)

6.5 에러 응답

HTTP 코드 에러 상황 메시지 예시
400 파일 없음 No file uploaded
400 차단된 확장자 File extension '.exe' is not allowed
400 MIME 타입 불일치 Invalid MIME type
413 파일 크기 초과 File size exceeds 20MB limit
413 용량 초과 Storage quota exceeded. Please delete files or contact support.
422 처리 불가 Failed to store file

7. 에러 코드

HTTP 코드 설명 예시
200 성공 조회, 수정, 삭제 성공
201 생성 성공 품목 등록 성공
400 잘못된 요청 필수 필드 누락, 유효성 검증 실패
404 리소스 없음 품목을 찾을 수 없음
409 충돌 품목코드 중복
422 처리 불가 비즈니스 로직 오류
500 서버 오류 예상치 못한 서버 오류

8. 다음 단계

8.1 우선순위 1: 리스트 화면 API

  • GET /api/items 구현
  • 페이지네이션 구현
  • 검색 및 필터링 구현

8.2 우선순위 2: 마스터 데이터 API

  • GET /api/items/master-data 구현
  • 드롭다운 옵션 데이터 제공

8.3 우선순위 3: 품목 등록 API

  • POST /api/items 구현
  • 파일 업로드 처리
  • 품목코드 자동생성 로직

8.4 우선순위 4: 품목 수정/삭제 API

  • GET /api/items/{itemCode} 구현
  • PUT /api/items/{itemCode} 구현
  • DELETE /api/items/{itemCode} 구현

8.5 우선순위 5: BOM 검색 API

  • GET /api/items/search 구현

9. 프론트엔드 구현 현황 (2025-11-17)

완료된 화면

품목 목록 화면

  • 경로: /[locale]/(protected)/items
  • 컴포넌트: ItemListClient.tsx
  • 기능:
    • 품목 유형별 탭 필터 (전체/제품/부품/부자재/원자재/소모품)
    • 통합 검색 (품목코드, 품목명, 규격)
    • 데스크톱 테이블 + 모바일 카드 반응형 레이아웃
    • 페이지네이션 (클라이언트 사이드)
    • 일괄 삭제
    • 품목유형 + 부품유형 Badge 표시

품목 상세 화면

  • 경로: /[locale]/(protected)/items/[itemCode]
  • 컴포넌트: ItemDetailClient.tsx
  • 기능:
    • 품목 유형별 조건부 섹션 표시
    • 제품(FG): 기본 정보, 제품 정보, BOM
    • 부품(PT) - 조립: 기본 정보, 조립 부품 세부 정보, BOM
    • 부품(PT) - 절곡: 기본 정보, 가이드레일 세부 정보
    • 부품(PT) - 구매: 기본 정보
    • 부자재/원자재/소모품: 기본 정보
    • BOM 테이블 표시

품목 등록/수정 화면

  • 경로:
    • 등록: /[locale]/(protected)/items/new
    • 수정: /[locale]/(protected)/items/[itemCode]/edit
  • 상태: 🚧 개발 예정

구현된 타입 정의

  • 파일: src/types/item.ts
  • 타입: ItemMaster, BOMLine, BendingDetail, ItemType, PartType 등 완료

구현된 API 클라이언트

  • 파일: src/lib/api/items.ts
  • 함수:
    • fetchItems() - 목록 조회
    • fetchItemsPaginated() - 페이지네이션 목록
    • fetchItemByCode() - 상세 조회
    • createItem() - 등록
    • updateItem() - 수정
    • deleteItem() - 삭제
    • uploadFile() - 파일 업로드
    • searchItemCodes() - 코드 검색
    • searchItemNames() - 품목명 검색

🚧 개발 대기 중

  • 품목 등록/수정 폼 화면
  • BOM 관리 인터페이스
  • 절곡품 전개도 편집기

10. 백엔드 API 구현 우선순위

Phase 1: 필수 API (회의 직후 착수)

  1. GET /api/items - 품목 목록 조회
  2. GET /api/items/{itemCode} - 품목 상세 조회
  3. GET /api/items/master-data - 마스터 데이터 조회

Phase 2: CRUD API

  1. POST /api/items - 품목 등록
  2. PUT /api/items/{itemCode} - 품목 수정
  3. DELETE /api/items/{itemCode} - 품목 삭제

Phase 3: 검색 및 유틸리티

  1. GET /api/items/search - 통합 검색
  2. GET /api/items/search/codes - 코드 검색
  3. GET /api/items/search/names - 품목명 검색
  4. POST /api/items/{itemCode}/files - 파일 업로드

Phase 4: BOM 관리

  1. GET /api/items/{itemCode}/bom - BOM 조회
  2. POST /api/items/{itemCode}/bom - BOM 라인 추가
  3. PUT /api/items/{itemCode}/bom/{lineId} - BOM 라인 수정
  4. DELETE /api/items/{itemCode}/bom/{lineId} - BOM 라인 삭제

11. 회의 안건 (PHP 백엔드 팀)

1. API 엔드포인트 확정

  • /api/items vs /api/items/paginated 중 선택
  • 검색 API 분리 방식 (codes, names) 승인

2. 데이터베이스 스키마 검토

  • items 테이블 구조
  • bom_lines 테이블 구조
  • item_revisions 테이블 (버전 관리)
  • 파일 저장 경로 및 구조

3. 인증 방식 확인

  • Bearer Token vs Cookie 방식
  • CORS 설정

4. 파일 업로드 구현

  • 참조 문서: /downloads/file_storage_implementation_guide.md
  • 저장 경로: storage/app/tenants/{tenant_id}/{folder_key}/{year}/{month}/{stored_name}
  • 최대 파일 크기: 20MB
  • 허용 확장자:
    • 문서: pdf, docx, hwp
    • 이미지: jpg, png
    • 기타: xlsx, xls, csv, zip, rar
  • 차단 확장자: exe, sh, bat, cmd, dwg, dxf, step, iges
  • 파일명 처리: 난수 저장명 (16자 hex) + 원본명 보존 (display_name)

5. 에러 응답 형식 통일

{
  "success": false,
  "message": "에러 메시지",
  "errors": {
    "fieldName": ["검증 실패 메시지"]
  }
}

6. 개발 일정 협의

  • Phase 1 (필수 API): 목표 일정
  • Phase 2-4: 순차 개발 일정

12. 버전 히스토리

  • v1.0 (2025-11-17 09:00): 초안 작성, API 요구사항 정의
  • v1.1 (2025-11-17 17:30): 프론트엔드 구현 현황 반영, 검색 API 세분화, 모바일 레이아웃 추가, 회의 안건 작성
  • v1.2 (2025-11-17 회의 후): 파일 업로드 요구사항 개정 (회의 결과 반영)
    • 시방서/인정서: PDF뿐만 아니라 이미지(JPG, PNG), 문서(DOCX, HWP) 형식 지원
    • 최대 파일 크기: 10MB → 20MB로 증가
    • 파일 저장소 구현 가이드 참조 추가 (/downloads/file_storage_implementation_guide.md)
    • 테넌트별 파일 저장 경로 구조 명시
    • 파일명 처리 방식 명시 (난수 저장명 + 원본명 보존)
    • 차단 확장자 목록 추가 (보안)

관련 파일

프론트엔드

  • src/types/item.ts - 품목 타입 정의
  • src/lib/api/items.ts - 품목 API 클라이언트
  • src/components/items/ItemListClient.tsx - 품목 목록 화면
  • src/components/items/ItemDetailClient.tsx - 품목 상세 화면
  • src/components/items/ItemForm.tsx - 품목 등록/수정 폼
  • src/lib/utils/validation.ts - Zod 검증 스키마

설정 파일

  • .env.local - API URL 및 키 설정

참조 문서

  • claudedocs/item-master/[API-2025-11-23] item-master-backend-requirements.md - 백엔드 요구사항
  • claudedocs/item-master/[DESIGN-2025-11-24] item-management-dynamic-frontend.md - 동적 화면 설계