Files
sam-react-prod/claudedocs/archive/sessions/[NEXT-2025-12-12] item-crud-session-context.md
유병철 07374c826c refactor(WEB): claudedocs 재정리 및 AuthContext/Zustand/유틸 코드 개선
- claudedocs 폴더 구조 재정리: archive/sessions, guides/migration·mobile·universal-list, refactoring 분류
- 오래된 세션 컨텍스트/체크리스트 문서 정리 (아카이브 이동 또는 삭제)
- AuthContext → authStore(Zustand) 전환 시작, RootProvider 간소화
- GenericCRUDDialog 공통 다이얼로그 컴포넌트 추가
- PermissionDialog 삭제 → GenericCRUDDialog로 대체
- RankDialog/TitleDialog GenericCRUDDialog 기반으로 리팩토링
- toast-utils.ts 삭제 (미사용)
- fileDownload.ts 개선, excel-download.ts 정리
- menuStore/themeStore Zustand 셀렉터 최적화
- useColumnSettings/useTableColumnStore 기능 보강
- 세금계산서/견적/작업자화면/결재 등 소규모 개선

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 17:17:13 +09:00

7.3 KiB

품목관리 세션 체크포인트

작성일: 2025-12-12 이전 세션: 2025-12-10 상태: 프론트엔드 작업 완료 (백엔드 API 대기)


🎯 오늘의 작업 목표

전개도 상세 입력 (폭 합계 연동) - 완료

BOM 테이블 UI 수정 - 완료

BOM 데이터 전송/로드 - 완료

파일 업로드 오류 수정 - 완료


완료된 작업

1. BOM API 연동 완료

변경 사항:

  • child_item_type 필드 추가 (PRODUCT/MATERIAL 구분)
  • BOM 저장 형식: { child_item_id, child_item_type, quantity } 최소 필드만 저장
  • 품목 유형 매핑: FG/PT → PRODUCT, SM/RM/CS → MATERIAL

수정 파일:

  • types.ts: BOMLine에 childItemType 필드 추가
  • DynamicBOMSection.tsx: getChildItemType() 헬퍼 함수 추가
  • index.tsx: BOM 전송 형식 간소화

2. 수정 화면 BOM 로드 버그 수정

문제: mapApiResponseToFormDatabom을 제외하여 initialData에 BOM이 없었음

해결: initialBomLines prop으로 BOM 데이터 별도 전달

수정 파일:

  • types.ts: DynamicItemFormPropsinitialBomLines?: BOMLine[] 추가
  • edit/page.tsx: API 응답에서 BOM 추출 → initialBomLines state → prop 전달
  • index.tsx: initialBomLines prop 수신 → useEffect로 setBomLines() 호출

3. BOM key 값 중복 에러 수정

문제: BOM 항목에 id가 없을 때 빈 문자열로 key 중복 발생

해결: page.tsxmapApiResponseToItemMaster에서 fallback key 생성

id: String(bomItem.id || bomItem.child_item_id || `bom-${index}`)

4. 이미지 업로드 500 에러 수정

문제: bending_diagram에 Base64 이미지 데이터가 JSON 본문에 포함되어 백엔드 500 에러

해결: API 호출 전 base64 이미지 데이터 제거 (파일은 별도 API로 업로드)

수정 파일:

  • edit/page.tsx: base64 이미지 필드 제거 로직 추가
  • create/page.tsx: 동일하게 적용
// API 호출 전 이미지 데이터 제거
if (submitData.bending_diagram?.startsWith('data:')) delete submitData.bending_diagram;
if (submitData.specification_file?.startsWith('data:')) delete submitData.specification_file;
if (submitData.certification_file?.startsWith('data:')) delete submitData.certification_file;

5. bending_details 배열 전송 오류 수정

문제: JSON.stringify()로 문자열 전송 → 백엔드에서 "배열이어야 합니다" 오류

해결: PHP가 이해하는 배열 형태로 FormData 전송

수정 파일: src/lib/api/items.ts

// 기존 (문자열)
formData.append('bending_details', JSON.stringify(options.bendingDetails));

// 수정 (배열 형태)
options.bendingDetails.forEach((detail, index) => {
  Object.entries(detail).forEach(([key, value]) => {
    formData.append(`bending_details[${index}][${key}]`, String(value));
  });
});

6. 제품 정보 섹션 빈 카드 숨김

문제: FG 품목 상세에서 "제품 정보" 섹션이 내용 없이 빈 카드로 표시

해결: 내용이 있을 때만 섹션 표시

수정 파일: ItemDetailClient.tsx

// 기존
{item.itemType === 'FG' && (

// 수정
{item.itemType === 'FG' && (item.productCategory || item.lotAbbreviation || item.note) && (

백엔드 대기 사항

1. 파일 다운로드 인증 문제 🔴

현재 문제:

  • 파일 다운로드 URL(/storage/{id})에 직접 접근 시 "Unauthorized. Invalid or missing API key" 에러
  • 브라우저에서 <a href="url">다운로드</a> 클릭 시 API 키가 없어서 401 에러
  • 시방서(PDF), 인정서(PDF), 전개도(이미지) 모두 동일한 문제

수정 요청 옵션:

  1. 옵션 A (권장): Signed URL 방식 - 임시 토큰이 포함된 URL 생성 (만료 시간 설정)
  2. 옵션 B: 파일 다운로드 엔드포인트를 public으로 변경 (인증 불필요)
  3. 옵션 C: 프론트엔드 프록시 경유 (Next.js API route에서 API 키 추가)

2. 품목 조회 시 파일 URL 미반환 문제 🔴

현재 문제:

  • bending_diagram, specification_file, certification_file 필드에 **file_id(숫자)**만 반환됨
  • 프론트엔드에서 이미지/PDF를 표시하려면 실제 다운로드 URL이 필요
  • 현재 file_id만 있어서 파일을 불러올 수 없음

수정 요청: 품목 조회 응답에서 file_id와 함께 실제 URL도 반환:

{
  "id": 813,
  "bending_diagram": 123,
  "bending_diagram_url": "/api/v1/files/download/xxx",
  "specification_file": 456,
  "specification_file_url": "/api/v1/files/download/yyy",
  "certification_file": 789,
  "certification_file_url": "/api/v1/files/download/zzz"
}

🔄 코드 변경 요약

파일 변경 내용
types.ts BOMLine에 childItemType 추가, DynamicItemFormProps에 initialBomLines 추가
DynamicBOMSection.tsx getChildItemType() 헬퍼 함수, 품목 선택 시 childItemType 설정
index.tsx BOM 전송 형식 간소화, initialBomLines prop 처리
edit/page.tsx initialBomLines 전달, base64 이미지 제거 로직
create/page.tsx base64 이미지 제거 로직
items/[id]/page.tsx BOM key fallback 처리
ItemDetailClient.tsx 제품 정보 섹션 조건부 표시
lib/api/items.ts bending_details 배열 형태로 전송

📋 다음 세션 TODO

백엔드 API 완료 후

  • 파일 다운로드 URL 처리 (백엔드 응답 형식에 맞춰 적용)
  • 전개도 이미지 표시 테스트
  • 시방서/인정서 PDF 다운로드 테스트

DynamicItemForm 분할 작업 🎯

  • index.tsx 파일 분할 (현재 2000줄+ → 500줄 이하로)
  • 섹션별 컴포넌트 분리:
    • DynamicFormHeader.tsx - 헤더/제목
    • DynamicFormActions.tsx - 저장/취소 버튼
    • DynamicBendingSection.tsx - 전개도 섹션 (기존)
    • DynamicFileSection.tsx - 파일 업로드 섹션
    • useDynamicForm.ts - 메인 로직 훅
  • 상태 관리 정리 (props drilling 최소화)

파일 업로드 필드 동적화 🆕

참고: [DESIGN-2025-12-12] item-master-form-builder-roadmap.md

현재 문제:

  • 파일 업로드가 FileUpload.tsx로 하드코딩되어 있음
  • 품목기준관리에서 파일 필드를 동적으로 추가할 수 없음

목표:

  • 새 필드 타입 file, files, image 추가
  • 품목기준관리에서 파일 업로드 필드 동적 생성 가능

구현 작업:

  • field_typefile | files | image 타입 추가 (API 스키마)
  • FileField.tsx 컴포넌트 생성 (DynamicItemForm/fields/)
  • ImageField.tsx 컴포넌트 생성 (미리보기 포함)
  • DynamicFieldRenderer.tsx에 file/image 케이스 추가
  • properties 확장: { accept, maxSize, maxFiles }
  • 품목기준관리 UI에 파일 필드 타입 옵션 추가
  • 기존 하드코딩된 FileUpload 컴포넌트 동적 필드로 마이그레이션

📚 관련 문서

문서 위치
이전 세션 컨텍스트 [NEXT-2025-12-10] item-crud-session-context.md
DynamicForm 분리 계획 [PLAN-2025-12-08] dynamic-form-separation-plan.md
Radix UI 버그 해결 claudedocs/guides/[FIX-2025-12-05] radix-ui-select-controlled-mode-bug.md