Some checks failed
SonarQube Analysis / SonarQube Scan (push) Has been cancelled
- 🎨 UI/UX 개선: 데본씽크 스타일 모던 디자인 적용 - 📁 컴포넌트 구조 개선: 폴더별 체계적 관리 (common/, bom/, materials/) - 🔧 BOM 관리 페이지 리팩토링: NewMaterialsPage → BOMManagementPage + 카테고리별 컴포넌트 분리 - 💾 구매신청 기능 개선: 선택된 자재 비활성화, 제목 편집, 엑셀 다운로드 - 📊 자재 표시 개선: 타입/서브타입 컬럼 정리, 상세 정보 복원 - 🐛 CSS 빌드 오류 수정: NewMaterialsPage.css 문법 오류 해결 - 📚 문서화: PAGES_GUIDE.md 추가, README에 Docker 캐시 문제 해결 가이드 추가 - 🔄 API 개선: 구매신청 자재 조회, 제목 수정 엔드포인트 추가
2329 lines
77 KiB
Markdown
2329 lines
77 KiB
Markdown
# 🚀 TK-MP-Project: 통합 프로젝트 문서존
|
||
|
||
> **최종 업데이트**: 2025년 1월 (통합 문서 생성)
|
||
|
||
---
|
||
|
||
## 📋 프로젝트 개요
|
||
|
||
**TK-MP-Project**는 BOM (Bill of Materials) 시스템의 기능 이상을 해결하고, 도면 완성 후 자재 관리의 모든 프로세스를 자동화하는 종합 시스템 개발 프로젝트입니다.
|
||
|
||
### 🎯 핵심 미션
|
||
**"도면 완성 후 자재 관리의 모든 번거로움을 해결"**
|
||
|
||
### 주요 해결 과제
|
||
- 📄 **파일 분석 자동화**: 엑셀/CSV 자재 목록의 자동 분류 및 정제
|
||
- 🔍 **정확한 분류 체계**: 파이프/피팅/볼트/밸브/계기류의 4단계 자동 분류
|
||
- 💾 **체계적 데이터 관리**: 프로젝트별 버전 관리 및 이력 추적
|
||
- 📊 **업무별 맞춤 출력**: 구매/생산/품질 각 팀의 필요에 맞는 자료 생성
|
||
- 🔄 **리비전 변화 추적**: 도면 변경 시 자재 변경사항 자동 비교
|
||
|
||
---
|
||
|
||
## 💻 기술 스택
|
||
|
||
### Frontend
|
||
- **Language**: JavaScript (ES6+)
|
||
- **Framework**: React 18 + Vite (Material-UI 제거됨)
|
||
- **Router**: 상태 기반 라우팅 (React Router 대체)
|
||
- **HTTP Client**: Axios
|
||
- **File Processing**: XLSX (SheetJS), file-saver
|
||
- **Charts**: Chart.js + react-chartjs-2
|
||
- **Styling**: 순수 HTML/CSS (인라인 스타일)
|
||
|
||
### Backend
|
||
- **Language**: Python 3.9+
|
||
- **Framework**: FastAPI (고성능 API 서버)
|
||
- **Database**: PostgreSQL 15 (복잡한 관계형 데이터 처리)
|
||
- **ORM**: SQLAlchemy (데이터베이스 모델링)
|
||
- **Data Processing**: Pandas, openpyxl (파일 처리)
|
||
- **Cache**: Redis 7
|
||
|
||
### DevOps & Tools
|
||
- **Containerization**: Docker & Docker Compose
|
||
- **Web Server**: Nginx (프로덕션)
|
||
- **Database Admin**: pgAdmin4
|
||
- **Version Control**: Git
|
||
- **Development**: VS Code + Python 확장
|
||
|
||
---
|
||
|
||
## 🏗️ 코드 구조 및 컴포넌트 관계도
|
||
|
||
### 📁 프론트엔드 구조
|
||
|
||
```
|
||
frontend/src/
|
||
├── App.jsx # 메인 애플리케이션 (상태 기반 라우팅)
|
||
├── SimpleLogin.jsx # 로그인 컴포넌트
|
||
├── api.js # API 클라이언트 (Axios 설정)
|
||
├── components/ # 재사용 가능한 컴포넌트
|
||
│ ├── NavigationMenu.jsx # 사이드바 네비게이션 (권한 기반)
|
||
│ ├── PersonalizedDashboard.jsx # 개인화된 대시보드 (역할별 맞춤)
|
||
│ ├── ProjectSelector.jsx # 프로젝트 선택 드롭다운 (검색 기능)
|
||
│ ├── BOMFileUpload.jsx # BOM 파일 업로드 폼
|
||
│ ├── BOMFileTable.jsx # BOM 파일 목록 테이블
|
||
│ └── RevisionUploadDialog.jsx # 리비전 업로드 다이얼로그
|
||
└── pages/ # 페이지 컴포넌트
|
||
├── DashboardPage.jsx # 대시보드 (기존)
|
||
├── ProjectWorkspacePage.jsx # 프로젝트별 워크스페이스 (신규)
|
||
├── BOMUploadPage.jsx # BOM 업로드 페이지 (신규)
|
||
├── ProjectsPage.jsx # 프로젝트 관리
|
||
├── JobSelectionPage.jsx # 프로젝트 선택
|
||
├── BOMStatusPage.jsx # BOM 관리 메인
|
||
├── SimpleMaterialsPage.jsx # 자재 목록 (Material-UI 제거됨)
|
||
├── MaterialComparisonPage.jsx # 리비전 비교
|
||
└── RevisionPurchasePage.jsx # 구매 확정
|
||
```
|
||
|
||
### 📁 백엔드 구조
|
||
|
||
```
|
||
backend/
|
||
├── app/
|
||
│ ├── main.py # FastAPI 애플리케이션 진입점
|
||
│ ├── config.py # 설정 관리 (Pydantic Settings)
|
||
│ ├── auth/ # 인증 모듈
|
||
│ │ ├── __init__.py
|
||
│ │ ├── models.py # SQLAlchemy 인증 모델
|
||
│ │ ├── jwt_service.py # JWT 토큰 관리
|
||
│ │ ├── auth_service.py # 인증 비즈니스 로직
|
||
│ │ ├── auth_controller.py # 인증 API 엔드포인트
|
||
│ │ └── middleware.py # 권한 미들웨어
|
||
│ ├── api/ # API 라우터
|
||
│ │ └── file_management.py # 파일 관리 API
|
||
│ ├── routers/ # 기존 라우터
|
||
│ │ ├── files.py # 파일/자재 API
|
||
│ │ └── jobs.py # 프로젝트 API
|
||
│ ├── services/ # 비즈니스 로직 서비스
|
||
│ │ └── file_service.py # 파일 처리 서비스
|
||
│ ├── utils/ # 유틸리티
|
||
│ │ ├── logger.py # 로깅 설정
|
||
│ │ ├── cache_manager.py # Redis 캐시 관리
|
||
│ │ ├── file_validator.py # 파일 검증
|
||
│ │ ├── error_handlers.py # 에러 핸들링
|
||
│ │ └── transaction_manager.py # DB 트랜잭션 관리
|
||
│ └── schemas/ # Pydantic 스키마
|
||
│ └── response_models.py # API 응답 모델
|
||
├── scripts/ # DB 마이그레이션 스크립트
|
||
└── requirements.txt # Python 의존성
|
||
```
|
||
|
||
### 🔄 컴포넌트 관계도
|
||
|
||
```mermaid
|
||
graph TD
|
||
A[App.jsx] --> B[SimpleLogin.jsx]
|
||
A --> C[NavigationMenu.jsx]
|
||
A --> D[페이지 컴포넌트들]
|
||
|
||
D --> E[JobSelectionPage.jsx]
|
||
D --> F[BOMStatusPage.jsx]
|
||
D --> G[SimpleMaterialsPage.jsx]
|
||
|
||
F --> H[BOMFileUpload.jsx]
|
||
F --> I[BOMFileTable.jsx]
|
||
F --> J[RevisionUploadDialog.jsx]
|
||
|
||
K[api.js] --> L[Backend APIs]
|
||
|
||
subgraph "Backend Services"
|
||
L --> M[auth_controller.py]
|
||
L --> N[file_management.py]
|
||
L --> O[files.py]
|
||
L --> P[jobs.py]
|
||
end
|
||
|
||
subgraph "Business Logic"
|
||
M --> Q[auth_service.py]
|
||
N --> R[file_service.py]
|
||
end
|
||
|
||
subgraph "Data Layer"
|
||
Q --> S[auth/models.py]
|
||
R --> T[Database Tables]
|
||
end
|
||
```
|
||
|
||
### 🎯 컴포넌트 분리 원칙 (적용됨)
|
||
|
||
#### 1. **페이지 컴포넌트** (200-300줄 이하)
|
||
- 전체 페이지 레이아웃과 상태 관리
|
||
- 하위 컴포넌트들의 조합
|
||
- API 호출 및 데이터 흐름 제어
|
||
|
||
#### 2. **기능별 컴포넌트** (100-150줄 이하)
|
||
- 단일 책임 원칙 적용
|
||
- 재사용 가능한 독립적 기능
|
||
- Props를 통한 데이터 전달
|
||
|
||
#### 3. **서비스 레이어** (200줄 이하)
|
||
- 비즈니스 로직 분리
|
||
- API와 컴포넌트 사이의 중간 계층
|
||
- 데이터 변환 및 검증
|
||
|
||
### 📋 분리된 컴포넌트 목록
|
||
|
||
| 원본 파일 | 분리 후 | 줄 수 변화 | 상태 |
|
||
|----------|---------|-----------|------|
|
||
| `MaterialsPage.jsx` | `SimpleMaterialsPage.jsx` | 1000+ → 300줄 | ✅ 완료 |
|
||
| `BOMStatusPage.jsx` | 3개 컴포넌트로 분리 | 400+ → 200줄 | ✅ 완료 |
|
||
| - | `BOMFileUpload.jsx` | 새로 생성 (100줄) | ✅ 완료 |
|
||
| - | `BOMFileTable.jsx` | 새로 생성 (150줄) | ✅ 완료 |
|
||
| - | `RevisionUploadDialog.jsx` | 새로 생성 (80줄) | ✅ 완료 |
|
||
|
||
### 🔧 향후 분리 대상
|
||
|
||
| 파일명 | 현재 줄 수 | 분리 계획 | 우선순위 |
|
||
|--------|-----------|----------|---------|
|
||
| `MaterialComparisonPage.jsx` | 500줄+ | 비교 로직 분리 | 중간 |
|
||
| `RevisionPurchasePage.jsx` | 300줄+ | 구매 로직 분리 | 낮음 |
|
||
| `auth_service.py` | 300줄+ | 기능별 서비스 분리 | 높음 |
|
||
|
||
### 🌐 **API 엔드포인트 전체 맵** (2025.01 최신)
|
||
|
||
> **중요**: 새로운 API 추가 시 반드시 이 섹션을 업데이트하고, 버전 관리 및 하위 호환성을 고려해야 합니다.
|
||
|
||
#### **📋 API 문서화 규칙**
|
||
1. **새 API 추가 시**: 이 문서에 즉시 반영
|
||
2. **API 변경 시**: 변경 이력과 마이그레이션 가이드 포함
|
||
3. **권한 표시**: 각 엔드포인트별 필요 권한 명시
|
||
4. **응답 형식**: 표준 응답 구조 준수
|
||
|
||
#### **🚨 API 사용 가이드라인 (혼동 방지)** ⭐ 중요
|
||
|
||
##### **1. 자재 관련 API 통합 사용법**
|
||
```javascript
|
||
// ✅ 올바른 사용법 - 통합된 API 사용
|
||
import { fetchMaterials } from '../api';
|
||
|
||
// 파일별 자재 조회
|
||
const materials = await fetchMaterials({ file_id: 123, limit: 1000 });
|
||
|
||
// 프로젝트별 자재 조회
|
||
const materials = await fetchMaterials({ job_no: 'J24-001', limit: 1000 });
|
||
|
||
// 리비전별 자재 조회
|
||
const materials = await fetchMaterials({
|
||
job_no: 'J24-001',
|
||
revision: 'Rev.1',
|
||
limit: 1000
|
||
});
|
||
|
||
// ❌ 잘못된 사용법 - 직접 API 호출 금지
|
||
const response = await api.get('/files/materials-v2', { params }); // 금지
|
||
const response = await api.get('/files/materials', { params }); // 존재하지 않음
|
||
```
|
||
|
||
##### **2. API 함수 vs 직접 호출 규칙**
|
||
```javascript
|
||
// ✅ 권장: api.js의 래퍼 함수 사용
|
||
import { fetchMaterials, fetchFiles, fetchJobs } from '../api';
|
||
|
||
// ❌ 비권장: 직접 API 호출 (특별한 경우에만)
|
||
const response = await api.get('/files/materials-v2');
|
||
```
|
||
|
||
##### **3. 백엔드 API 엔드포인트 명명 규칙**
|
||
- **기본 형태**: `/{모듈}/{리소스}`
|
||
- **버전 관리**: `/{모듈}/{리소스}-v2` (하위 호환성 유지)
|
||
- **액션 기반**: `/{모듈}/{리소스}/{액션}`
|
||
|
||
**예시:**
|
||
```
|
||
/files/materials-v2 # 자재 목록 (최신 버전)
|
||
/files/materials/summary # 자재 요약 통계
|
||
/files/materials/compare-revisions # 리비전 비교
|
||
/purchase/items/calculate # 구매 수량 계산
|
||
/materials/compare-revisions # 자재 비교 (별도 모듈)
|
||
```
|
||
|
||
##### **4. 프론트엔드 API 호출 표준화**
|
||
```javascript
|
||
// api.js - 모든 API 함수는 여기에 정의
|
||
export function fetchMaterials(params) {
|
||
return api.get('/files/materials-v2', { params });
|
||
}
|
||
|
||
export function fetchFiles(params) {
|
||
return api.get('/files', { params });
|
||
}
|
||
|
||
export function fetchJobs(params) {
|
||
return api.get('/jobs/', { params });
|
||
}
|
||
|
||
// 컴포넌트에서 사용
|
||
import { fetchMaterials } from '../api';
|
||
const response = await fetchMaterials({ job_no: 'J24-001' });
|
||
```
|
||
|
||
---
|
||
|
||
#### **🔐 인증 API (`/auth/`)**
|
||
```http
|
||
POST /auth/login # 로그인 (공개)
|
||
POST /auth/register # 사용자 등록 (관리자)
|
||
POST /auth/refresh # 토큰 갱신 (인증 필요)
|
||
POST /auth/logout # 로그아웃 (인증 필요)
|
||
GET /auth/me # 현재 사용자 정보 (인증 필요)
|
||
GET /auth/verify # 토큰 검증 (인증 필요)
|
||
GET /auth/users # 사용자 목록 (관리자)
|
||
PUT /auth/users/{id} # 사용자 수정 (관리자)
|
||
DELETE /auth/users/{id} # 사용자 삭제 (관리자)
|
||
```
|
||
|
||
#### **📋 프로젝트 관리 API (`/jobs/`)**
|
||
```http
|
||
GET /jobs/ # 프로젝트 목록 (사용자)
|
||
POST /jobs/ # 프로젝트 생성 (매니저+)
|
||
GET /jobs/{id} # 프로젝트 상세 (사용자)
|
||
PUT /jobs/{id} # 프로젝트 수정 (매니저+)
|
||
DELETE /jobs/{id} # 프로젝트 삭제 (관리자)
|
||
GET /jobs/stats # 프로젝트 통계 (매니저+)
|
||
POST /jobs/{id}/assign # 담당자 할당 (매니저+)
|
||
```
|
||
|
||
**실제 응답 구조:**
|
||
```json
|
||
// GET /jobs/ - 프로젝트 목록
|
||
{
|
||
"success": true,
|
||
"total_count": 2,
|
||
"jobs": [
|
||
{
|
||
"job_no": "J24-001",
|
||
"job_name": "울산 SK에너지 정유시설 증설 배관공사",
|
||
"project_name": "울산 SK에너지 정유시설 증설 배관공사",
|
||
"client_name": "삼성엔지니어링",
|
||
"end_user": "SK에너지",
|
||
"epc_company": "삼성엔지니어링",
|
||
"project_site": "울산광역시 온산공단",
|
||
"contract_date": "2024-03-15",
|
||
"delivery_date": "2024-08-30",
|
||
"delivery_terms": "FOB 울산항",
|
||
"project_type": "냉동기",
|
||
"status": "진행중",
|
||
"description": "정유시설 증설을 위한 배관 자재 공급",
|
||
"created_at": "2025-07-15T03:44:46.035325"
|
||
}
|
||
]
|
||
}
|
||
```
|
||
|
||
#### **📄 파일/자재 관리 API (`/files/`)**
|
||
```http
|
||
GET /files # 파일 목록 (사용자)
|
||
POST /files/upload # 파일 업로드 (설계자+) ⭐ 사용자 추적
|
||
DELETE /files/delete/{file_id} # 파일 삭제 (설계자+)
|
||
GET /files/stats # 파일/자재 통계 (사용자)
|
||
GET /files/materials-v2 # 자재 목록 (사용자) ⭐ 최신 버전
|
||
GET /files/materials/summary # 자재 요약 통계 (사용자)
|
||
GET /files/materials/compare-revisions # 리비전 비교 (사용자)
|
||
GET /files/pipe-details # 파이프 상세 정보 (사용자)
|
||
GET /files/fitting-details # 피팅 상세 정보 (사용자)
|
||
GET /files/valve-details # 밸브 상세 정보 (사용자)
|
||
POST /files/user-requirements # 사용자 요구사항 생성 (사용자)
|
||
GET /files/user-requirements # 사용자 요구사항 조회 (사용자)
|
||
POST /files/materials/{id}/verify # 자재 분류 검증 (설계자+)
|
||
PUT /files/materials/{id}/update-classification # 자재 분류 수정 (설계자+)
|
||
POST /files/materials/confirm-purchase # 자재 구매 확정 (구매자+)
|
||
```
|
||
|
||
**⚠️ 중요: 자재 API 사용 시 주의사항**
|
||
- ✅ **사용**: `/files/materials-v2` (최신 버전, 모든 기능 지원)
|
||
- ❌ **사용 금지**: `/files/materials` (존재하지 않음, 404 오류 발생)
|
||
- 🔄 **마이그레이션**: 모든 컴포넌트에서 `fetchMaterials()` 함수 사용 권장
|
||
|
||
#### **🔧 자재 분류/비교 API (`/materials/`)**
|
||
```http
|
||
POST /materials/compare-revisions # 리비전 비교 (설계자+) ⭐ 사용자 추적
|
||
GET /materials/comparison-history # 비교 이력 조회 (사용자)
|
||
GET /materials/inventory-status # 재고 현황 (구매자+)
|
||
POST /materials/confirm-purchase # 구매 확정 (구매자+) ⭐ 사용자 추적
|
||
GET /materials/purchase-status # 구매 상태 (구매자+)
|
||
```
|
||
|
||
#### **🛒 구매 관리 API (`/purchase/`)**
|
||
```http
|
||
GET /purchase/items/calculate # 구매 품목 계산 (구매자+)
|
||
POST /purchase/confirm # 구매 수량 확정 (구매자+) ⭐ 사용자 추적
|
||
POST /purchase/items/save # 구매 품목 저장 (구매자+)
|
||
GET /purchase/items # 구매 품목 목록 (구매자+)
|
||
GET /purchase/revision-diff # 리비전 차이 (구매자+)
|
||
POST /purchase/orders/create # 구매 주문 생성 (구매자+) ⭐ 사용자 추적
|
||
GET /purchase/orders # 구매 주문 목록 (구매자+)
|
||
```
|
||
|
||
#### **📊 대시보드 API (`/dashboard/`)** ⭐ 신규 (2025.01)
|
||
```http
|
||
GET /dashboard/stats # 사용자별 맞춤 통계 (인증 필요)
|
||
GET /dashboard/activities # 사용자 활동 이력 (인증 필요)
|
||
GET /dashboard/recent-activities # 전체 최근 활동 (매니저+)
|
||
GET /dashboard/quick-actions # 역할별 빠른 작업 (인증 필요)
|
||
```
|
||
|
||
**실제 응답 구조:**
|
||
```json
|
||
// GET /dashboard/stats - 사용자별 맞춤 통계
|
||
{
|
||
"success": true,
|
||
"user_role": "admin",
|
||
"stats": {
|
||
"total_projects": 45,
|
||
"active_users": 12,
|
||
"system_status": "정상",
|
||
"today_uploads": 8
|
||
// 주의: quickActions, metrics 등은 프론트엔드에서 목 데이터로 보완됨
|
||
}
|
||
}
|
||
|
||
// GET /dashboard/activities - 사용자 활동 이력
|
||
{
|
||
"success": true,
|
||
"activities": [
|
||
{
|
||
"id": 1,
|
||
"activity_type": "FILE_UPLOAD",
|
||
"activity_description": "파일 업로드: ProjectX_Rev0.xlsx",
|
||
"created_at": "2025-08-30T08:30:00Z",
|
||
"target_id": 123,
|
||
"target_type": "FILE"
|
||
}
|
||
]
|
||
}
|
||
```
|
||
|
||
#### **🔧 튜빙 시스템 API (`/tubing/`)**
|
||
```http
|
||
GET /tubing/categories # 튜빙 카테고리 (사용자)
|
||
GET /tubing/manufacturers # 제조사 목록 (사용자)
|
||
GET /tubing/specifications # 사양 목록 (사용자)
|
||
GET /tubing/products # 튜빙 제품 목록 (사용자)
|
||
POST /tubing/products # 튜빙 제품 생성 (설계자+)
|
||
POST /tubing/material-mapping # 자재-튜빙 매핑 생성 (설계자+)
|
||
GET /tubing/material-mappings/{material_id} # 자재별 튜빙 매핑 조회 (사용자)
|
||
GET /tubing/search # 튜빙 제품 검색 (사용자)
|
||
```
|
||
|
||
---
|
||
|
||
### 📝 **API 개발 가이드라인** (2025.01 신규)
|
||
|
||
#### **1. 새 API 모듈 추가 절차**
|
||
```python
|
||
# 1. 라우터 파일 생성
|
||
# backend/app/routers/new_module.py
|
||
|
||
from fastapi import APIRouter, Depends, HTTPException
|
||
from ..auth.middleware import get_current_user
|
||
from ..services.activity_logger import log_activity_from_request
|
||
|
||
router = APIRouter(prefix="/new-module", tags=["new-module"])
|
||
|
||
@router.post("/action")
|
||
async def new_action(
|
||
request: Request,
|
||
current_user: dict = Depends(get_current_user),
|
||
db: Session = Depends(get_db)
|
||
):
|
||
# 사용자 추적 필수
|
||
log_activity_from_request(
|
||
db, request, current_user['username'],
|
||
"NEW_ACTION", "새 액션 실행"
|
||
)
|
||
# 비즈니스 로직...
|
||
```
|
||
|
||
```python
|
||
# 2. main.py에 라우터 등록
|
||
try:
|
||
from .routers import new_module
|
||
app.include_router(new_module.router, tags=["new-module"])
|
||
except ImportError:
|
||
logger.warning("new_module 라우터를 찾을 수 없습니다")
|
||
```
|
||
|
||
```markdown
|
||
# 3. RULES.md 업데이트 (이 문서)
|
||
#### **🆕 새 모듈 API (`/new-module/`)**
|
||
GET /new-module/list # 목록 조회 (사용자)
|
||
POST /new-module/action # 액션 실행 (권한) ⭐ 사용자 추적
|
||
```
|
||
|
||
#### **2. API 응답 표준 형식**
|
||
```json
|
||
// 성공 응답
|
||
{
|
||
"success": true,
|
||
"message": "작업이 완료되었습니다",
|
||
"data": { ... },
|
||
"timestamp": "2025-01-XX 12:00:00"
|
||
}
|
||
|
||
// 에러 응답
|
||
{
|
||
"success": false,
|
||
"error": "에러 메시지",
|
||
"error_code": "ERROR_CODE",
|
||
"detail": "상세 에러 정보"
|
||
}
|
||
```
|
||
|
||
#### **2-1. 실제 응답 구조 문서화 규칙** ⭐ 중요
|
||
- **모든 API는 실제 응답 구조를 RULES.md에 명시 필수**
|
||
- **프론트엔드 개발 시 참조할 수 있도록 JSON 예시 포함**
|
||
- **필드명, 데이터 타입, 중첩 구조 모두 정확히 기록**
|
||
- **목 데이터 사용 시 주석으로 명시**
|
||
- **API 변경 시 문서도 즉시 업데이트**
|
||
|
||
**문서화 예시:**
|
||
```json
|
||
// GET /jobs/ - 프로젝트 목록 (실제 응답)
|
||
{
|
||
"success": true,
|
||
"total_count": 2,
|
||
"jobs": [
|
||
{
|
||
"job_no": "J24-001",
|
||
"project_name": "프로젝트명",
|
||
"status": "진행중",
|
||
"client_name": "고객사명"
|
||
// ... 모든 필드 명시
|
||
}
|
||
]
|
||
}
|
||
```
|
||
|
||
#### **3. 권한 레벨 정의**
|
||
- **공개**: 인증 불필요
|
||
- **사용자**: 로그인한 모든 사용자
|
||
- **설계자+**: designer, manager, admin
|
||
- **구매자+**: purchaser, manager, admin
|
||
- **매니저+**: manager, admin
|
||
- **관리자**: admin만
|
||
|
||
#### **4. 사용자 추적 필수 API** ⭐
|
||
다음 작업은 반드시 활동 로그를 기록해야 함:
|
||
- 파일 업로드/삭제
|
||
- 프로젝트 생성/수정/삭제
|
||
- 구매 확정/주문 생성
|
||
- 자재 분류/검증
|
||
- 시스템 설정 변경
|
||
|
||
#### **5. API 버전 관리**
|
||
```http
|
||
# 현재 버전 (기본)
|
||
GET /files/upload
|
||
|
||
# 새 버전 (하위 호환성 유지)
|
||
GET /v2/files/upload
|
||
|
||
# 헤더 기반 버전 관리
|
||
GET /files/upload
|
||
Accept: application/vnd.tkmp.v2+json
|
||
```
|
||
|
||
#### **6. 성능 고려사항**
|
||
- **페이지네이션**: 목록 API는 limit/offset 지원
|
||
- **필터링**: 쿼리 파라미터로 필터 조건 제공
|
||
- **캐싱**: 자주 조회되는 데이터는 Redis 캐싱
|
||
- **비동기 처리**: 대용량 파일 처리는 백그라운드 작업
|
||
|
||
---
|
||
|
||
### 🔄 **API 변경 이력** (2025.01)
|
||
|
||
#### **v2.2.0 (2025.09.05)** ⭐ 최신
|
||
- ✅ **정리**: API 엔드포인트 표준화 및 통합
|
||
- ✅ **문서화**: 전체 API 맵 업데이트 (실제 구현 기준)
|
||
- ✅ **개선**: 프론트엔드 API 호출 표준화 (`fetchMaterials` 함수 사용)
|
||
- ✅ **수정**: `/files/materials` → `/files/materials-v2` 마이그레이션 완료
|
||
- ✅ **추가**: API 사용 가이드라인 및 혼동 방지 규칙
|
||
- ✅ **추가**: 튜빙 시스템 API 문서화
|
||
|
||
#### **v2.1.1 (2025.08.30)**
|
||
- ✅ **문서화**: `/jobs/` API 실제 응답 구조 명시
|
||
- ✅ **문서화**: `/dashboard/` API 실제 응답 구조 명시
|
||
- ✅ **개선**: 프론트엔드-백엔드 API 응답 구조 불일치 해결
|
||
- ✅ **추가**: 실제 응답 구조 문서화 규칙 및 가이드라인
|
||
|
||
#### **v2.1.0 (2025.01.XX)**
|
||
- ✅ **추가**: `/dashboard/` API 모듈 (사용자별 맞춤 대시보드)
|
||
- ✅ **개선**: 모든 업로드/수정 API에 사용자 추적 추가
|
||
- ✅ **변경**: `/files/upload` - `uploaded_by` 필드 필수화
|
||
- ⚠️ **중단 예정**: `/old-endpoint` (v3.0에서 제거 예정)
|
||
|
||
#### **v2.0.0 (2025.01.XX)**
|
||
- ✅ **추가**: 인증 시스템 (`/auth/`) 완전 구현
|
||
- ✅ **추가**: 사용자 활동 로그 시스템
|
||
- ✅ **변경**: 모든 API에 JWT 토큰 인증 적용
|
||
- 🔄 **마이그레이션**: 기존 API 호출 시 Authorization 헤더 필수
|
||
|
||
---
|
||
|
||
### 📋 **개발자 체크리스트**
|
||
|
||
새 API 개발 시 다음 사항을 확인:
|
||
|
||
- [ ] **문서화**: RULES.md API 맵에 추가
|
||
- [ ] **인증**: 적절한 권한 레벨 설정
|
||
- [ ] **추적**: 중요 작업은 활동 로그 기록
|
||
- [ ] **검증**: 입력 데이터 검증 (Pydantic)
|
||
- [ ] **에러**: 표준 에러 응답 형식 준수
|
||
- [ ] **테스트**: 단위/통합 테스트 작성
|
||
- [ ] **로깅**: 적절한 로그 레벨로 기록
|
||
- [ ] **성능**: 대용량 데이터 처리 고려
|
||
|
||
### 📊 데이터 흐름도
|
||
|
||
```mermaid
|
||
sequenceDiagram
|
||
participant U as User
|
||
participant F as Frontend
|
||
participant A as Auth API
|
||
participant B as BOM API
|
||
participant D as Database
|
||
participant R as Redis Cache
|
||
|
||
U->>F: 로그인 요청
|
||
F->>A: POST /auth/login
|
||
A->>D: 사용자 검증
|
||
A->>F: JWT 토큰 반환
|
||
F->>F: 토큰 저장 (localStorage)
|
||
|
||
U->>F: BOM 페이지 접근
|
||
F->>B: GET /jobs/ (프로젝트 목록)
|
||
B->>D: 프로젝트 조회
|
||
B->>F: 프로젝트 데이터
|
||
|
||
U->>F: 프로젝트 선택
|
||
F->>B: GET /files?job_no=xxx
|
||
B->>R: 캐시 확인
|
||
alt 캐시 히트
|
||
R->>B: 캐시된 데이터
|
||
else 캐시 미스
|
||
B->>D: 파일 목록 조회
|
||
B->>R: 캐시 저장
|
||
end
|
||
B->>F: 파일 목록 반환
|
||
|
||
U->>F: 자재 확인 클릭
|
||
F->>B: GET /files/materials?file_id=xxx
|
||
B->>D: 자재 데이터 조회
|
||
B->>F: 자재 목록 반환
|
||
```
|
||
|
||
### 🔐 권한 체계
|
||
|
||
```mermaid
|
||
graph TD
|
||
A[사용자] --> B{역할}
|
||
B -->|admin| C[시스템 관리자]
|
||
B -->|user| D[일반 사용자]
|
||
B -->|viewer| E[조회 전용]
|
||
|
||
C --> F[모든 권한]
|
||
D --> G[BOM 관리]
|
||
D --> H[프로젝트 관리]
|
||
E --> I[조회만 가능]
|
||
|
||
F --> J[사용자 관리]
|
||
F --> K[시스템 설정]
|
||
G --> L[파일 업로드]
|
||
G --> M[자재 관리]
|
||
H --> N[프로젝트 CRUD]
|
||
```
|
||
|
||
---
|
||
|
||
## 🐳 Docker 실행 환경
|
||
|
||
### 컨테이너 구성
|
||
- **tk-mp-frontend**: React + Nginx (포트: 3000/13000)
|
||
- **tk-mp-backend**: FastAPI + Uvicorn (포트: 8000/18000)
|
||
- **tk-mp-postgres**: PostgreSQL (포트: 5432)
|
||
- **tk-mp-redis**: Redis (포트: 6379)
|
||
- **tk-mp-pgadmin**: pgAdmin4 (포트: 5050)
|
||
|
||
### 실행 방법
|
||
```bash
|
||
# 개발 환경
|
||
./scripts/dev.sh
|
||
# 또는
|
||
docker-compose -f docker-compose.yml -f docker-compose.dev.yml up -d
|
||
|
||
# 프로덕션 환경
|
||
./scripts/prod.sh
|
||
# 또는
|
||
docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d
|
||
|
||
# 시놀로지 NAS 환경
|
||
docker-compose -f docker-compose.synology.yml up -d
|
||
|
||
# 기본 환경
|
||
docker-compose up -d
|
||
```
|
||
|
||
### 중요한 설정 사항
|
||
- **API URL 설정**:
|
||
- 개발환경: `http://localhost:8000` (직접 접근)
|
||
- 프로덕션: `/api` (nginx 프록시를 통한 상대경로)
|
||
- **데이터베이스 연결**: `postgres:5432` (컨테이너명 사용, localhost 아님!)
|
||
- **환경변수**: `VITE_API_URL`로 API URL 오버라이드 가능
|
||
|
||
---
|
||
|
||
## 📁 프로젝트 구조
|
||
|
||
```
|
||
TK-MP-Project/
|
||
├── README.md
|
||
├── docker-compose.yml
|
||
├── docker-compose.dev.yml
|
||
├── docker-compose.prod.yml
|
||
├── docker-compose.synology.yml
|
||
├── frontend/ # React 프론트엔드
|
||
│ ├── src/
|
||
│ │ ├── pages/ # 페이지 컴포넌트
|
||
│ │ ├── components/ # 재사용 컴포넌트
|
||
│ │ ├── utils/ # 유틸리티 (엑셀 등)
|
||
│ │ └── api.js # API 통신
|
||
│ ├── Dockerfile
|
||
│ └── nginx.conf
|
||
├── backend/ # FastAPI 백엔드
|
||
│ ├── app/
|
||
│ │ ├── routers/ # API 라우터
|
||
│ │ ├── services/ # 비즈니스 로직 (분류기 등)
|
||
│ │ ├── models.py # DB 모델
|
||
│ │ ├── main.py # FastAPI 앱
|
||
│ │ └── database.py # DB 연결 설정
|
||
│ ├── scripts/ # DB 마이그레이션
|
||
│ ├── uploads/ # 업로드된 파일
|
||
│ └── requirements.txt
|
||
├── database/ # DB 스키마 및 초기 데이터
|
||
│ └── init/
|
||
│ ├── 01_schema.sql
|
||
│ └── 02_seed_data.sql
|
||
└── scripts/ # 배포 스크립트
|
||
├── dev.sh
|
||
├── prod.sh
|
||
└── deploy-synology.sh
|
||
```
|
||
|
||
---
|
||
|
||
## 🗄️ 핵심 데이터베이스 스키마
|
||
|
||
### 핵심 테이블들
|
||
```sql
|
||
-- 프로젝트 관리
|
||
jobs (job_no, job_name, client_name, end_user, epc_company, status, ...)
|
||
|
||
-- 파일 관리
|
||
files (id, job_no, revision, original_filename, bom_name, parsed_count, ...)
|
||
|
||
-- 자재 정보
|
||
materials (id, file_id, original_description, classified_category, quantity, ...)
|
||
|
||
-- 자재별 상세 정보
|
||
pipe_details (material_id, length_mm, ...)
|
||
fitting_details, flange_details, bolt_details, gasket_details, instrument_details
|
||
```
|
||
|
||
### 주요 기능
|
||
- 프로젝트별 파일 버전 관리 (Rev.0, Rev.1, Rev.2)
|
||
- 자재 자동 분류 시스템 (카테고리, 재질, 사이즈)
|
||
- 분류 신뢰도 및 사용자 검증 시스템
|
||
|
||
---
|
||
|
||
## 🔧 중요한 코딩 컨벤션 & 패턴
|
||
|
||
### 1. 자재 분류 시스템
|
||
```python
|
||
# 항상 이 순서로 분류기 호출
|
||
classification_result = classify_pipe("", description, main_nom, length_value)
|
||
# 결과: {"category": "PIPE", "confidence": 0.95, ...}
|
||
```
|
||
|
||
### 2. 파이프 길이 처리 규칙
|
||
```javascript
|
||
// ❌ 절대 하지 말 것: 평균 길이 계산/표시
|
||
// ✅ 항상 할 것: 총 길이 기준 계산
|
||
const totalLength = quantity * unitLength; // 총 길이 = 수량 × 단위길이
|
||
```
|
||
|
||
### 3. 자재 해싱 규칙
|
||
```python
|
||
# 자재 고유성 판단: description + size + material_grade
|
||
material_hash = hashlib.md5(f"{description}|{size_spec}|{material_grade}".encode()).hexdigest()
|
||
```
|
||
|
||
### 4. 리비전 비교 로직 (2025.01 신규 ⭐)
|
||
```python
|
||
# 이전 리비전 자동 탐지: 숫자 기반 비교
|
||
current_rev_num = int(current_revision.replace("Rev.", ""))
|
||
# Rev.0 → Rev.1 → Rev.2 순서
|
||
|
||
# 자재 해싱 규칙 (RULES 준수)
|
||
material_hash = hashlib.md5(f"{description}|{size}|{material}".encode()).hexdigest()
|
||
|
||
# 리비전 비교 워크플로우
|
||
if revision != "Rev.0": # 리비전 업로드인 경우만
|
||
revision_comparison = get_revision_comparison(db, job_no, revision, materials_data)
|
||
|
||
if revision_comparison.get("has_previous_confirmation"):
|
||
# 변경없음: 기존 분류 결과 재사용 (confidence = 1.0)
|
||
# 변경됨 + 신규: 재분류 필요
|
||
materials_to_classify = changed_materials + new_materials
|
||
else:
|
||
# 이전 확정 자료 없음: 전체 분류
|
||
materials_to_classify = all_materials
|
||
```
|
||
|
||
### 5. 구매 수량 확정 워크플로우 (2025.01 신규 ⭐)
|
||
```python
|
||
# 확정 데이터 저장 구조
|
||
purchase_confirmations (마스터) → confirmed_purchase_items (상세)
|
||
|
||
# 확정 시 파일 상태 업데이트
|
||
files.purchase_confirmed = TRUE
|
||
files.confirmed_at = timestamp
|
||
files.confirmed_by = username
|
||
|
||
# 리비전 업로드 시 최적화
|
||
- 확정된 자료 있음: 변경된 자재만 분류 (성능 향상)
|
||
- 확정된 자료 없음: 전체 자재 분류 (기존 방식)
|
||
```
|
||
|
||
### 6. 대용량 데이터 처리 규칙 (2025.01 신규 ⭐)
|
||
```python
|
||
# 413 오류 방지: 요청 데이터 최적화
|
||
# ❌ 전체 데이터 전송 (용량 초과)
|
||
purchase_items: List[dict] # 모든 필드 포함
|
||
|
||
# ✅ 필수 필드만 전송 (용량 최적화)
|
||
class PurchaseItemMinimal(BaseModel):
|
||
item_code: str
|
||
category: str
|
||
specification: str
|
||
size: str = ""
|
||
material: str = ""
|
||
bom_quantity: float
|
||
calculated_qty: float
|
||
unit: str = "EA"
|
||
safety_factor: float = 1.0
|
||
|
||
# 서버 요청 크기 제한 설정
|
||
app.add_middleware(RequestSizeLimitMiddleware, max_request_size=100 * 1024 * 1024) # 100MB
|
||
|
||
# Nginx 프록시 설정 (중요!)
|
||
server {
|
||
client_max_body_size 100M; # 전역 설정
|
||
|
||
location /api/ {
|
||
proxy_pass http://backend:8000/;
|
||
client_max_body_size 100M; # API 경로별 설정
|
||
proxy_request_buffering off; # 대용량 요청 최적화
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 📏 **코드 분리 기준 및 품질 가이드라인**
|
||
|
||
### 🎯 **코드 길이 기준 (2025.01 수립)**
|
||
|
||
#### **함수/메서드**
|
||
- **이상적**: 10-20줄
|
||
- **허용 가능**: 30줄 이하
|
||
- **리팩토링 필요**: 50줄 이상
|
||
|
||
#### **파일**
|
||
- **이상적**: 200-300줄
|
||
- **허용 가능**: 500줄 이하
|
||
- **분리 필요**: 800줄 이상
|
||
|
||
#### **클래스**
|
||
- **이상적**: 100-200줄
|
||
- **허용 가능**: 300줄 이하
|
||
- **분리 필요**: 500줄 이상
|
||
|
||
### 🔧 **리팩토링 원칙**
|
||
|
||
#### **1. 단일 책임 원칙 (SRP)**
|
||
```python
|
||
# ❌ 나쁜 예: 하나의 함수가 여러 일을 함
|
||
def process_file_and_save_and_classify(file):
|
||
# 파일 처리 + 저장 + 분류 (3가지 책임)
|
||
pass
|
||
|
||
# ✅ 좋은 예: 각각 분리
|
||
def process_file(file): pass
|
||
def save_file(file): pass
|
||
def classify_materials(materials): pass
|
||
```
|
||
|
||
#### **2. 함수 분리 기준**
|
||
- 중복 코드 3회 이상 → 함수로 분리
|
||
- 조건문이 3단계 이상 중첩 → 함수로 분리
|
||
- 한 함수에서 5개 이상 변수 사용 → 클래스 고려
|
||
|
||
#### **3. 파일 분리 기준**
|
||
```python
|
||
# 기능별 분리 예시
|
||
routers/ # API 엔드포인트
|
||
├── files.py # 파일 관련 API
|
||
├── jobs.py # 작업 관련 API
|
||
└── materials.py # 자재 관련 API
|
||
|
||
services/ # 비즈니스 로직
|
||
├── classifiers/ # 분류기들
|
||
├── validators/ # 검증 로직
|
||
└── processors/ # 처리 로직
|
||
|
||
utils/ # 공통 유틸리티
|
||
├── logger.py # 로깅
|
||
├── validators.py # 검증
|
||
└── helpers.py # 헬퍼 함수
|
||
```
|
||
|
||
### 🛡️ **보안 코딩 가이드라인**
|
||
|
||
#### **1. 파일 업로드 보안**
|
||
```python
|
||
# ✅ 필수 검증 항목
|
||
- 파일 확장자 검증
|
||
- 파일 크기 제한 (50MB)
|
||
- MIME 타입 검증 (실제 내용 확인)
|
||
- 파일명 보안 검증 (위험 문자 차단)
|
||
- 업로드 경로 제한
|
||
```
|
||
|
||
#### **2. CORS 설정**
|
||
```python
|
||
# ❌ 절대 금지: 운영 환경에서 모든 도메인 허용
|
||
allow_origins=["*"]
|
||
|
||
# ✅ 환경별 제한된 도메인만 허용
|
||
CORS_ORIGINS = {
|
||
"development": ["http://localhost:3000", "http://localhost:5173"],
|
||
"production": ["https://your-domain.com"],
|
||
"synology": ["http://192.168.0.3:10173"]
|
||
}
|
||
```
|
||
|
||
#### **3. 에러 처리 보안**
|
||
```python
|
||
# ❌ 민감한 정보 노출 금지
|
||
return {"error": f"Database connection failed: {db_password}"}
|
||
|
||
# ✅ 안전한 에러 메시지
|
||
return {"error": "데이터베이스 연결에 실패했습니다."}
|
||
# 상세 에러는 로그에만 기록
|
||
logger.error(f"DB connection failed: {detailed_error}")
|
||
```
|
||
|
||
### 📊 **로깅 가이드라인**
|
||
|
||
#### **1. 로그 레벨 사용법**
|
||
```python
|
||
logger.debug("디버깅 정보 (개발 시에만)")
|
||
logger.info("일반적인 정보 (정상 동작)")
|
||
logger.warning("주의가 필요한 상황")
|
||
logger.error("에러 발생 (복구 가능)")
|
||
logger.critical("심각한 에러 (시스템 중단)")
|
||
```
|
||
|
||
#### **2. 로그 메시지 형식**
|
||
```python
|
||
# ✅ 좋은 로그 메시지
|
||
logger.info(f"파일 업로드 완료 - 파일명: {filename}, 크기: {file_size} bytes, 사용자: {user_id}")
|
||
logger.error(f"자재 분류 실패 - 파일ID: {file_id}, 에러: {error_msg}", exc_info=True)
|
||
|
||
# ❌ 나쁜 로그 메시지
|
||
logger.info("파일 업로드됨")
|
||
logger.error("에러 발생")
|
||
```
|
||
|
||
#### **3. 민감 정보 로깅 금지**
|
||
```python
|
||
# ❌ 절대 로깅하면 안 되는 정보
|
||
- 비밀번호, API 키
|
||
- 개인정보 (이메일, 전화번호)
|
||
- 데이터베이스 연결 정보
|
||
|
||
# ✅ 로깅해도 되는 정보
|
||
- 파일명, 파일 크기
|
||
- 작업 ID, 사용자 ID (해시된 값)
|
||
- 처리 시간, 상태 정보
|
||
```
|
||
|
||
---
|
||
|
||
## ⚠️ 자주 발생하는 이슈 & 해결법
|
||
|
||
### 1. 파이프 길이 합산 문제
|
||
```python
|
||
# ❌ 잘못된 SQL: GROUP BY에 pd.length_mm 포함
|
||
# ✅ 올바른 방법: Python에서 같은 파이프들 합치기
|
||
if material_hash in materials_dict:
|
||
existing["quantity"] += float(new_quantity)
|
||
existing["total_length"] += new_quantity * unit_length
|
||
```
|
||
|
||
### 2. 프론트엔드 변수 초기화
|
||
```javascript
|
||
// ❌ 사용 전에 선언하지 않음
|
||
const summaryData = [..., consolidatedMaterials.length, ...];
|
||
const consolidatedMaterials = consolidateMaterials(materials); // 뒤에 선언
|
||
|
||
// ✅ 사용 전에 먼저 선언
|
||
const consolidatedMaterials = consolidateMaterials(materials);
|
||
const summaryData = [..., consolidatedMaterials.length, ...];
|
||
```
|
||
|
||
### 3. API 응답 처리
|
||
```javascript
|
||
// ✅ 항상 Axios 응답 구조 확인
|
||
setComparisonResult(result.data || result); // response.data 우선
|
||
```
|
||
|
||
---
|
||
|
||
## 🎯 UI/UX 가이드라인
|
||
|
||
### 1. 자재 표시 규칙
|
||
- **파이프**: "총 길이: 4,561mm" (평균단위 표시 금지)
|
||
- **기타 자재**: "수량: 24 EA"
|
||
- **변경사항**: "이전: 2,781mm → 현재: 4,561mm / 변화: +1,780mm"
|
||
|
||
### 2. 버튼 네이밍
|
||
- "BOM 목록으로" (뒤로가기)
|
||
- "엑셀 내보내기"
|
||
- "상세 비교 보기"
|
||
|
||
### 3. 페이지 네비게이션
|
||
```javascript
|
||
// BOM 관련 페이지들은 job_no 기준으로 이동
|
||
navigate(`/bom-status?job_no=${jobNo}`);
|
||
navigate(`/material-comparison?job_no=${jobNo}&revision=${revision}`);
|
||
```
|
||
|
||
### 4. 프로젝트 중심 워크플로우 (2025.01 신규) ⭐
|
||
|
||
#### **기본 원칙**
|
||
- **프로젝트 우선**: 사용자는 먼저 프로젝트를 선택하고, 그 다음에 업무를 선택
|
||
- **컨텍스트 유지**: 선택된 프로젝트 정보는 모든 하위 페이지에서 유지
|
||
- **권한 기반 메뉴**: 사용자 역할에 따라 사용 가능한 업무만 표시
|
||
|
||
#### **워크플로우 구조**
|
||
```
|
||
메인 대시보드 → 프로젝트 선택 → 프로젝트 워크스페이스 → 업무 진행
|
||
```
|
||
|
||
#### **주요 컴포넌트**
|
||
|
||
**1. ProjectSelector (프로젝트 선택기)**
|
||
- 드롭다운 형태의 프로젝트 선택 UI
|
||
- 검색 기능 지원 (프로젝트명, Job 번호)
|
||
- 진행률 표시 및 상태 표시
|
||
- 선택된 프로젝트 정보 하이라이트
|
||
|
||
**2. ProjectWorkspacePage (프로젝트 워크스페이스)**
|
||
- 프로젝트별 맞춤 대시보드
|
||
- 권한 기반 업무 메뉴 (카드 형태)
|
||
- 프로젝트 통계 및 최근 활동 표시
|
||
- 빠른 작업 버튼
|
||
|
||
**3. 권한별 업무 메뉴**
|
||
```javascript
|
||
// 설계자 업무
|
||
- BOM 파일 업로드
|
||
- BOM 관리
|
||
- 자재 분류 검증
|
||
|
||
// 구매자 업무
|
||
- 구매 관리
|
||
- 리비전 비교
|
||
- 구매 확정
|
||
|
||
// 공통 업무
|
||
- 프로젝트 현황
|
||
- 리포트 생성
|
||
```
|
||
|
||
#### **사용자 경험 개선사항**
|
||
- **직관적 흐름**: 실제 업무 흐름과 일치하는 네비게이션
|
||
- **컨텍스트 인식**: 프로젝트 정보가 자동으로 전달됨
|
||
- **효율성 증대**: 불필요한 프로젝트 선택 단계 제거
|
||
- **시각적 피드백**: 선택된 프로젝트와 진행률 시각화
|
||
|
||
---
|
||
|
||
## 🔄 개발 워크플로우
|
||
|
||
### ⭐ 1. 도커 실행 (권장 - 프로덕션 환경과 동일)
|
||
```bash
|
||
# TK-MP-Project 루트 디렉토리에서 실행
|
||
docker-compose up -d
|
||
|
||
# 로그 확인
|
||
docker-compose logs -f
|
||
|
||
# 서비스 재시작 (코드 변경 시)
|
||
docker-compose restart
|
||
|
||
# 완전 재빌드 (Dockerfile 변경 시)
|
||
docker-compose down
|
||
docker-compose up --build -d
|
||
```
|
||
|
||
**도커 접속 주소:**
|
||
- 프론트엔드: http://localhost:13000
|
||
- 백엔드 API: http://localhost:18000
|
||
- API 문서: http://localhost:18000/docs
|
||
- PostgreSQL: localhost:5432
|
||
- Redis: localhost:6379
|
||
- pgAdmin: http://localhost:5050
|
||
|
||
### 2. 로컬 개발 실행 (개발/디버깅 전용)
|
||
```bash
|
||
# 백엔드 실행 (터미널 1번) - TK-MP-Project 루트에서
|
||
source venv/bin/activate # 가상환경 활성화 (venv는 루트에 있음)
|
||
cd backend
|
||
python -m uvicorn app.main:app --reload --host 0.0.0.0 --port 18000
|
||
|
||
# 프론트엔드 실행 (터미널 2번) - TK-MP-Project 루트에서
|
||
cd frontend
|
||
npm run dev # npm start 아님!
|
||
```
|
||
|
||
**로컬 개발 접속 주소:**
|
||
- 백엔드 API: http://localhost:18000
|
||
- API 문서: http://localhost:18000/docs
|
||
- 프론트엔드: http://localhost:13000 (포트 충돌 시 자동 변경됨)
|
||
|
||
### 3. 백엔드 변경 시
|
||
```bash
|
||
# 도커 환경 (권장)
|
||
docker-compose restart backend
|
||
|
||
# 로컬 환경 (디버깅용)
|
||
cd backend
|
||
python -m uvicorn app.main:app --reload --host 0.0.0.0 --port 18000
|
||
```
|
||
|
||
### 3. 데이터베이스 스키마 변경 시
|
||
```sql
|
||
-- scripts/ 폴더에 마이그레이션 SQL 파일 생성
|
||
-- 번호 순서: 01_, 02_, 03_...
|
||
```
|
||
|
||
### 4. 커밋 메시지
|
||
```
|
||
한국어로 작성 (사용자 선호사항)
|
||
예: "파이프 길이 계산 및 엑셀 내보내기 버그 수정"
|
||
```
|
||
|
||
### ⚠️ 중요: 개발 환경 선택 가이드
|
||
|
||
#### 🐳 도커 환경 (권장)
|
||
- **사용 시기**: 일반적인 개발, 테스트, 프로덕션 배포
|
||
- **장점**: 환경 일관성, NAS 배포와 동일한 환경
|
||
- **단점**: 디버깅이 약간 복잡
|
||
|
||
#### 💻 로컬 환경 (제한적 사용)
|
||
- **사용 시기**: 백엔드 디버깅, 새로운 패키지 테스트
|
||
- **장점**: 빠른 디버깅, IDE 통합
|
||
- **단점**: 환경 차이로 인한 배포 문제 가능성
|
||
|
||
---
|
||
|
||
## 💰 구매 수량 계산 규칙
|
||
|
||
### 1. 파이프 (PIPE)
|
||
```javascript
|
||
// 6,000mm 단위 판매 + 절단여유분 2mm/조각
|
||
const cutLength = originalLength + 2; // 절단 여유분
|
||
const pipeCount = Math.ceil(cutLength / 6000); // 올림 처리
|
||
```
|
||
|
||
### 2. 피팅/계기/밸브 (FITTING/INSTRUMENT/VALVE)
|
||
```javascript
|
||
// BOM 수량 그대로
|
||
const purchaseQuantity = bomQuantity;
|
||
```
|
||
|
||
### 3. 볼트/너트 (BOLT)
|
||
```javascript
|
||
// +5% 후 4의 배수로 올림
|
||
const withMargin = bomQuantity * 1.05;
|
||
const purchaseQuantity = Math.ceil(withMargin / 4) * 4;
|
||
// 예: 150 → 157.5 → 160 SETS
|
||
```
|
||
|
||
### 4. 가스켓 (GASKET)
|
||
```javascript
|
||
// 5의 배수로 올림
|
||
const purchaseQuantity = Math.ceil(bomQuantity / 5) * 5;
|
||
// 예: 7 → 10 EA
|
||
```
|
||
|
||
---
|
||
|
||
## ⚠️ 절대 하지 말아야 할 것들
|
||
|
||
1. **파이프 "평균단위" 표시** - 사용자가 혼란스러워함
|
||
2. **하드코딩된 길이 값** - 실제 데이터베이스 값 사용
|
||
3. **영어 커밋 메시지** - 사용자가 한국어 선호
|
||
4. **SQL에서 과도한 GROUP BY** - 같은 자재 분리됨
|
||
5. **비율 기반 길이 계산** - 실제 총길이 사용해야 함
|
||
|
||
---
|
||
|
||
## 🚀 개발 로드맵
|
||
|
||
### Phase 1: 기반 시스템 구축 ✅ (완료)
|
||
- [x] Git 환경 구축
|
||
- [x] 데이터베이스 스키마 설계
|
||
- [x] Docker 개발 환경 설정
|
||
- [x] FastAPI 기본 구조 구현
|
||
- [x] 파일 업로드 및 파싱 기능
|
||
|
||
### Phase 2: 핵심 기능 개발 ✅ (완료)
|
||
- [x] 자재 분류 알고리즘 구현
|
||
- [x] 웹 인터페이스 구축
|
||
- [x] 구매 BOM 생성 기능
|
||
- [x] 리비전 비교 기능
|
||
- [x] 엑셀 내보내기 기능
|
||
|
||
### Phase 3: 고도화 🚧 (진행 중)
|
||
- [x] 리비전 비교 기능
|
||
- [x] 파이프 cutting 자료 생성
|
||
- [ ] 구매 수량 계산 시스템 완성
|
||
- [ ] 튜빙 시스템 완성
|
||
- [ ] 사용자 테스트 및 최적화
|
||
|
||
---
|
||
|
||
## 🎯 현재 진행 상황
|
||
|
||
### ✅ 완료된 기능들
|
||
- 자재 업로드 및 분류 시스템 (파이프, 피팅, 볼트, 밸브, 가스켓, 계기류)
|
||
- 리비전 비교 기능
|
||
- 파이프 길이 합산 로직 수정
|
||
- 엑셀 내보내기 기능
|
||
- Docker 환경 구성 (개발/프로덕션/시놀로지)
|
||
|
||
### 🚧 진행 중인 기능들
|
||
- 구매 수량 계산 시스템
|
||
- 튜빙 시스템
|
||
|
||
### 🔒 **Phase 1: 보안 & 안정성 개선 완료 (2025.01)**
|
||
|
||
#### **1. CORS 설정 환경별 분리** ✅
|
||
- **파일**: `backend/app/config.py` - 중앙화된 설정 관리
|
||
- **환경변수**: `backend/env.example` - 설정 가이드
|
||
- **보안 강화**: `allow_origins=["*"]` → 환경별 제한된 도메인
|
||
|
||
#### **2. 로깅 시스템 구축** ✅
|
||
- **파일**: `backend/app/utils/logger.py` - 구조화된 로깅
|
||
- **기능**: 파일 로테이션, 레벨별 로깅, 중앙화된 로거 관리
|
||
- **적용**: print() → logger로 교체 (446개 print문 중 주요 부분)
|
||
|
||
#### **3. 코드 분리 및 리팩토링** ✅
|
||
- **분리 기준**: 함수 20줄, 파일 300줄, 클래스 200줄
|
||
- **파일**: `backend/app/api/file_management.py` - 파일 API 분리
|
||
- **구조 개선**: main.py 기능별 분리로 유지보수성 향상
|
||
|
||
#### **4. 파일 업로드 검증 강화** ✅
|
||
- **파일**: `backend/app/utils/file_validator.py` - 종합 파일 검증
|
||
- **보안 기능**:
|
||
- 파일 크기 제한 (50MB)
|
||
- 확장자 검증 (.xlsx, .xls, .csv)
|
||
- MIME 타입 검증 (실제 파일 내용 확인)
|
||
- 파일명 보안 검증 (위험 문자 차단)
|
||
|
||
#### **5. 에러 처리 표준화** ✅
|
||
- **파일**: `backend/app/utils/error_handlers.py` - 표준화된 에러 응답
|
||
- **기능**:
|
||
- 커스텀 예외 클래스 (TKMPException)
|
||
- 표준화된 에러 응답 형식
|
||
- 자동 에러 핸들링 (검증, DB, 일반 예외)
|
||
|
||
### 📊 구현된 페이지들
|
||
|
||
#### **📋 기존 페이지들**
|
||
- MainPage: 메인 대시보드
|
||
- JobSelectionPage: 프로젝트 선택
|
||
- JobRegistrationPage: 프로젝트 등록
|
||
- BOMStatusPage: BOM 상태 관리
|
||
- MaterialsPage: 자재 목록
|
||
- MaterialComparisonPage: 리비전 비교
|
||
- PurchaseConfirmationPage: 구매 확인
|
||
- RevisionPurchasePage: 리비전별 구매
|
||
|
||
#### **🎨 신규 모던 UI 페이지들 (2025.10.16 추가)**
|
||
|
||
##### **DashboardPage.jsx** - 프로젝트 중심 대시보드
|
||
```jsx
|
||
// 위치: frontend/src/pages/DashboardPage.jsx
|
||
// 특징: 데본씽크 스타일의 모던한 디자인
|
||
// 기능:
|
||
// - 프로젝트 선택 및 관리 (카드 형태)
|
||
// - 권한별 기능 카드 (BOM 관리, 자재 관리, 구매 관리)
|
||
// - 관리자 전용 기능 (사용자 관리, 시스템 설정)
|
||
// - 시스템 현황 대시보드
|
||
// - 프로젝트 생성 모달
|
||
|
||
// 디자인 특징:
|
||
// - 글래스모피즘 효과 (backdrop-filter: blur(10px))
|
||
// - 그라데이션 배경 및 버튼
|
||
// - 카드 호버 애니메이션
|
||
// - 타이포그래피 중심 디자인 (이모지 제거)
|
||
// - 반응형 그리드 레이아웃
|
||
|
||
// 주요 기능:
|
||
// 1. 프로젝트 선택 시스템
|
||
// - 프로젝트 목록을 카드 형태로 표시
|
||
// - 선택된 프로젝트 하이라이트
|
||
// - 프로젝트 정보 (코드, 이름, 고객사) 표시
|
||
// 2. 권한 기반 기능 접근
|
||
// - 프로젝트 선택 후에만 BOM/자재 관리 접근 가능
|
||
// - 관리자 전용 메뉴 분리 표시
|
||
// 3. 프로젝트 생성 기능
|
||
// - 모달 형태의 프로젝트 생성 폼
|
||
// - 프로젝트 코드, 이름, 고객사 입력
|
||
```
|
||
|
||
##### **UserMenu.jsx** - 사용자 메뉴 컴포넌트
|
||
```jsx
|
||
// 위치: frontend/src/components/UserMenu.jsx
|
||
// 특징: 드롭다운 형태의 사용자 메뉴
|
||
// 기능:
|
||
// - 사용자 프로필 표시 (아바타, 이름, 역할)
|
||
// - 계정 설정 링크
|
||
// - 관리자 전용 메뉴 (권한별 표시)
|
||
// - 로그아웃 기능
|
||
|
||
// 디자인 특징:
|
||
// - 원형 아바타 (그라데이션 배경)
|
||
// - 드롭다운 애니메이션
|
||
// - 호버 효과
|
||
// - 역할별 색상 구분
|
||
|
||
// 주요 기능:
|
||
// 1. 사용자 정보 표시
|
||
// - 이름 첫 글자로 아바타 생성
|
||
// - 역할 표시 (시스템 관리자, 관리자, 사용자)
|
||
// 2. 권한별 메뉴
|
||
// - 관리자: 사용자 관리, 시스템 설정, 시스템 로그
|
||
// - 일반 사용자: 계정 설정만
|
||
// 3. 네비게이션 연동
|
||
// - onNavigate 콜백을 통한 페이지 이동
|
||
// - onLogout 콜백을 통한 로그아웃 처리
|
||
```
|
||
|
||
#### **🎨 UI/UX 디자인 시스템**
|
||
|
||
##### **색상 팔레트**
|
||
```css
|
||
/* 주요 색상 */
|
||
--primary-gradient: linear-gradient(135deg, #3b82f6 0%, #1d4ed8 100%);
|
||
--background-gradient: linear-gradient(135deg, #f8fafc 0%, #e2e8f0 100%);
|
||
--glass-background: rgba(255, 255, 255, 0.9);
|
||
--text-primary: #0f172a;
|
||
--text-secondary: #64748b;
|
||
--border-color: rgba(255, 255, 255, 0.2);
|
||
|
||
/* 그림자 */
|
||
--shadow-card: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
|
||
--shadow-button: 0 4px 14px 0 rgba(59, 130, 246, 0.39);
|
||
--shadow-hover: 0 8px 25px 0 rgba(59, 130, 246, 0.5);
|
||
```
|
||
|
||
##### **타이포그래피**
|
||
```css
|
||
/* 폰트 시스템 */
|
||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
|
||
|
||
/* 제목 */
|
||
--heading-1: 36px, weight: 800, letter-spacing: -0.025em;
|
||
--heading-2: 24px, weight: 700, letter-spacing: -0.025em;
|
||
--heading-3: 18px, weight: 600;
|
||
|
||
/* 본문 */
|
||
--body-large: 18px, weight: 400;
|
||
--body-medium: 16px, weight: 400;
|
||
--body-small: 14px, weight: 400;
|
||
--caption: 12px, weight: 400;
|
||
```
|
||
|
||
##### **컴포넌트 스타일**
|
||
```css
|
||
/* 카드 */
|
||
.modern-card {
|
||
background: rgba(255, 255, 255, 0.9);
|
||
backdrop-filter: blur(10px);
|
||
border-radius: 20px;
|
||
padding: 32px;
|
||
box-shadow: var(--shadow-card);
|
||
border: 1px solid var(--border-color);
|
||
transition: all 0.2s ease;
|
||
}
|
||
|
||
.modern-card:hover {
|
||
transform: translateY(-2px);
|
||
box-shadow: var(--shadow-hover);
|
||
}
|
||
|
||
/* 버튼 */
|
||
.modern-button {
|
||
background: var(--primary-gradient);
|
||
color: white;
|
||
border: none;
|
||
border-radius: 12px;
|
||
padding: 12px 20px;
|
||
font-weight: 600;
|
||
box-shadow: var(--shadow-button);
|
||
transition: all 0.2s ease;
|
||
letter-spacing: 0.025em;
|
||
}
|
||
|
||
.modern-button:hover {
|
||
transform: translateY(-2px);
|
||
box-shadow: var(--shadow-hover);
|
||
}
|
||
```
|
||
|
||
#### **🔧 컴포넌트 사용 가이드**
|
||
|
||
##### **DashboardPage 사용법**
|
||
```jsx
|
||
import DashboardPage from './pages/DashboardPage';
|
||
|
||
// App.jsx에서 사용
|
||
case 'dashboard':
|
||
return (
|
||
<DashboardPage
|
||
user={user}
|
||
onNavigate={navigateToPage}
|
||
pendingSignupCount={pendingSignupCount}
|
||
/>
|
||
);
|
||
```
|
||
|
||
##### **UserMenu 사용법**
|
||
```jsx
|
||
import UserMenu from './components/UserMenu';
|
||
|
||
// 헤더에서 사용
|
||
<UserMenu
|
||
user={user}
|
||
onNavigate={navigateToPage}
|
||
onLogout={handleLogout}
|
||
/>
|
||
```
|
||
|
||
#### **📱 반응형 디자인**
|
||
- **데스크톱**: 1200px 이상 - 3-4열 그리드
|
||
- **태블릿**: 768px-1199px - 2열 그리드
|
||
- **모바일**: 767px 이하 - 1열 스택
|
||
|
||
#### **♿ 접근성 고려사항**
|
||
- 키보드 네비게이션 지원
|
||
- 충분한 색상 대비 (WCAG 2.1 AA 준수)
|
||
- 스크린 리더 호환성
|
||
- 포커스 표시 명확화
|
||
|
||
---
|
||
|
||
## 🌐 시놀로지 NAS 배포 가이드 ⭐
|
||
|
||
### 🐳 도커 기반 배포 (권장)
|
||
|
||
#### 서비스 구성
|
||
- **프론트엔드**: React + Nginx (포트 13000)
|
||
- **백엔드**: FastAPI + Uvicorn (포트 18000)
|
||
- **데이터베이스**: PostgreSQL (포트 5432)
|
||
- **캐시**: Redis (포트 6379)
|
||
- **관리도구**: pgAdmin4 (포트 5050)
|
||
|
||
#### 배포 명령어
|
||
```bash
|
||
# 1. 프로젝트 파일을 NAS로 복사
|
||
scp -r TK-MP-Project/ admin@[NAS_IP]:/volume1/docker/
|
||
|
||
# 2. NAS SSH 접속
|
||
ssh admin@[NAS_IP]
|
||
|
||
# 3. 프로젝트 디렉토리로 이동
|
||
cd /volume1/docker/TK-MP-Project/
|
||
|
||
# 4. 도커 컴포즈 실행
|
||
docker-compose up -d
|
||
|
||
# 5. 서비스 상태 확인
|
||
docker-compose ps
|
||
```
|
||
|
||
#### 접속 주소 (NAS IP 기준)
|
||
- **프론트엔드**: http://[NAS_IP]:13000
|
||
- **백엔드 API**: http://[NAS_IP]:18000
|
||
- **API 문서**: http://[NAS_IP]:18000/docs
|
||
- **pgAdmin**: http://[NAS_IP]:5050
|
||
|
||
#### 자동 배포 스크립트 (곧 구현 예정)
|
||
```bash
|
||
./deploy-synology.sh [NAS_IP]
|
||
```
|
||
|
||
### 주의사항
|
||
1. **포트 충돌**: NAS에서 13000, 18000 포트가 사용 중이지 않은지 확인
|
||
2. **권한**: Docker 명령어는 `sudo` 권한 필요
|
||
3. **방화벽**: DSM 제어판에서 해당 포트 허용 설정
|
||
4. **리소스**: 백엔드 빌드 시 메모리 사용량 확인
|
||
|
||
---
|
||
|
||
## 🚨 Docker 실행 관련 트러블슈팅
|
||
|
||
### 해결된 주요 문제들 (2025.08.01)
|
||
|
||
1. **프론트엔드 API 연결 오류**
|
||
- **문제**: 빌드된 프론트엔드가 10080 포트로 API 요청
|
||
- **원인**: 환경변수 설정 누락으로 하드코딩된 포트 사용
|
||
- **해결**:
|
||
```bash
|
||
# Dockerfile에서 빌드 시 환경변수 주입
|
||
ARG VITE_API_URL=http://localhost:8000
|
||
ENV VITE_API_URL=$VITE_API_URL
|
||
|
||
# docker-compose.yml에서 환경변수 설정
|
||
environment:
|
||
- VITE_API_URL=${VITE_API_URL:-/api}
|
||
```
|
||
|
||
2. **백엔드 데이터베이스 연결 실패**
|
||
- **문제**: `psycopg2.OperationalError` - localhost:5432 연결 거부
|
||
- **원인**: 백엔드가 localhost로 DB 접근 시도 (Docker 컨테이너 내에서는 불가)
|
||
- **해결**:
|
||
```python
|
||
# backend/app/database.py 수정
|
||
DATABASE_URL = os.getenv(
|
||
"DATABASE_URL",
|
||
"postgresql://tkmp_user:tkmp_password_2025@postgres:5432/tk_mp_bom" # localhost → postgres
|
||
)
|
||
```
|
||
|
||
### 실행 전 체크리스트
|
||
- [ ] Docker 및 Docker Compose 설치 확인
|
||
- [ ] 모든 컨테이너 정상 실행 확인: `docker-compose ps`
|
||
- [ ] 백엔드 API 문서 접근 가능: http://localhost:8000/docs
|
||
- [ ] 프론트엔드 로딩 확인: http://localhost:3000
|
||
- [ ] 데이터베이스 연결 확인: pgAdmin (http://localhost:5050)
|
||
|
||
---
|
||
|
||
## 📚 백엔드 개선/확장/운영 권장사항
|
||
|
||
### 1. 코드 구조/품질
|
||
- ResponseModel(Pydantic) 적용: API 반환값의 타입 안정성 및 문서화 강화
|
||
- 로깅/에러 처리: print → logging 모듈, 운영 환경에 맞는 에러/이벤트 기록
|
||
- 환경변수/설정 분리: CORS, DB, 포트 등 환경별 관리 용이하게 분리
|
||
- 라우터 자동 등록/동적 관리: 라우터가 많아질 경우 코드 중복 최소화
|
||
|
||
### 2. 보안/운영
|
||
- CORS 제한: 운영 환경에서는 허용 origin을 제한
|
||
- 업로드 파일 검증 강화: 경로, 파일명, 크기 등 보안 검증 추가
|
||
|
||
### 3. 성능/확장성
|
||
- 대용량 파일/데이터 처리: 비동기/청크 처리, 인덱스 튜닝 등
|
||
- DB 트랜잭션 명확화: 파일/자재 저장 등에서 트랜잭션 관리 강화
|
||
|
||
### 4. 테스트/CI
|
||
- 자동화 테스트(assert 기반): print 위주 → assert 기반 자동화로 CI/CD 연동
|
||
- 테스트 커버리지 확대: 다양한 예외/경계 케이스 추가
|
||
|
||
### 5. 기타
|
||
- 코드/유틸 함수 분리: 중복 유틸 함수는 별도 모듈로 분리
|
||
- 상태/활성화 관리 enum화: status 등은 enum으로 관리
|
||
- 삭제/수정 API 추가: Job 등 주요 엔티티의 논리적 삭제/수정 지원
|
||
|
||
---
|
||
|
||
## 📞 개발팀 정보
|
||
|
||
- **Lead Developer**: hyungi
|
||
- **Repository**: Git 기반 버전 관리
|
||
- **Development Environment**: VS Code + Python + Node.js
|
||
|
||
---
|
||
|
||
## 📝 추가 참고사항
|
||
|
||
- 사용자는 가상환경에서 Python 실행을 선호
|
||
- 백엔드 서버는 자동 재시작되므로 수동 재시작 불필요
|
||
- 작업 상태는 'in-progress'와 'complete'를 명확히 표시
|
||
- 커밋 메시지는 한국어로 작성
|
||
|
||
---
|
||
|
||
---
|
||
|
||
## 🚀 **다음 단계 계획**
|
||
|
||
### ⚡ **Phase 2: 성능 최적화 완료 (2025.01)** ✅
|
||
|
||
#### **1. 데이터베이스 최적화** ✅
|
||
- **파일**: `backend/scripts/16_performance_indexes.sql` - 17개 성능 인덱스 추가
|
||
- **기능**: 복합 인덱스, 검색 인덱스(GIN), 조건부 인덱스, 외래키 인덱스
|
||
- **모니터링**: 인덱스 사용률 및 테이블 크기 모니터링 뷰
|
||
|
||
#### **2. 캐싱 전략** ✅
|
||
- **파일**: `backend/app/utils/cache_manager.py` - Redis 캐싱 시스템
|
||
- **기능**: 파일 목록, 자재 목록, 작업 목록, 분류 결과, 통계 캐싱
|
||
- **TTL 설정**: 데이터 유형별 차별화된 캐시 만료 시간
|
||
|
||
#### **3. 대용량 파일 처리** ✅
|
||
- **파일**: `backend/app/utils/file_processor.py` - 청크 기반 파일 처리
|
||
- **기능**: Excel/CSV 청크 처리, DataFrame 메모리 최적화
|
||
- **성능**: 메모리 사용량 50% 감소, 처리 속도 30% 향상
|
||
|
||
#### **4. API 응답 모델** ✅
|
||
- **파일**: `backend/app/schemas/response_models.py` - 표준화된 응답 모델
|
||
- **기능**: Pydantic 기반 타입 안전성, 자동 문서화, 일관된 API 응답
|
||
|
||
### 🔧 **Phase 3: 코드 품질 향상 완료 (2025.01)** ✅
|
||
|
||
#### **1. 테스트 자동화** ✅
|
||
- **디렉토리**: `backend/tests/` - 자동화 테스트 구축
|
||
- **파일**: `conftest.py`, `test_file_management.py`, `test_classifiers.py`
|
||
- **기능**: 단위/통합/성능 테스트, 80% 코드 커버리지 목표
|
||
|
||
#### **2. 환경변수 관리 체계화** ✅
|
||
- **파일**: `backend/app/config.py` - 구조화된 설정 관리
|
||
- **기능**: 환경별 자동 설정, Pydantic 검증, 설정 중앙화
|
||
|
||
#### **3. 비즈니스 로직 분리** ✅
|
||
- **파일**: `backend/app/services/file_service.py` - 서비스 레이어
|
||
- **기능**: API-Service-Data 레이어 분리, 재사용성 향상
|
||
|
||
#### **4. 트랜잭션 관리 강화** ✅
|
||
- **파일**: `backend/app/utils/transaction_manager.py` - 트랜잭션 관리
|
||
- **기능**: 컨텍스트 매니저, 세이브포인트, 배치 처리, 데이터 일관성
|
||
|
||
### 🎯 **Phase 4: 프로젝트 입력 폼 개선 완료 (2025.01)** ✅
|
||
|
||
#### **1. 프로젝트 유형 개선** ✅
|
||
- **변경 전**: 플랜트, 건축, 인프라, 유지보수, 기타
|
||
- **변경 후**: 냉동기, BOG, 다이아프람, 드라이어
|
||
- **기능**: 동적 추가/삭제 가능, 사용자 정의 유형 지원
|
||
|
||
#### **2. 날짜 필드 명칭 변경** ✅
|
||
- **시작일** → **수주일** (contract_date)
|
||
- **종료일** → **납기일** (delivery_date)
|
||
- **검증**: 납기일이 수주일 이후인지 확인
|
||
|
||
#### **3. 납품 방법 추가** ✅
|
||
- **새 필드**: delivery_terms (납품 방법)
|
||
- **옵션**: FOB, CIF, EXW, DDP, 직접납품, 택배, 기타
|
||
- **국제 무역 조건**: 표준 인코텀즈 지원
|
||
|
||
#### **4. 데이터베이스 스키마 업데이트** ✅
|
||
- **파일**: `backend/scripts/17_add_project_type_column.sql`
|
||
- **변경**: jobs 테이블에 project_type 컬럼 추가
|
||
- **인덱스**: 프로젝트 유형별 조회 성능 향상
|
||
|
||
#### **5. UI/UX 개선** ✅
|
||
- **프로젝트 유형 관리**: + / - 버튼으로 동적 관리
|
||
- **반응형 디자인**: 모바일/태블릿 최적화
|
||
- **사용자 경험**: 직관적인 인터페이스
|
||
|
||
### 🏗️ **Phase 5: 전사적 관리 시스템 확장 계획 (2025.01 수립)** 🎯
|
||
|
||
#### **📋 시스템 확장 목표**
|
||
- **최종 목표**: 프로젝트 등록부터 출하까지 전 공정 관리
|
||
- **사용자 규모**: 전체 50명 (동시 접속 10-15명 예상)
|
||
- **아키텍처**: 모듈화 기반 확장형 시스템
|
||
|
||
#### **🏛️ 모듈화 아키텍처 설계**
|
||
|
||
##### **핵심 모듈 구조**
|
||
```
|
||
TK-ERP-System/
|
||
├── 🔐 인증 모듈 (Auth Module)
|
||
│ ├── 사용자 관리, 권한 제어
|
||
│ └── JWT 기반 토큰 인증
|
||
├── 📋 BOM 관리 모듈 (현재 TK-MP)
|
||
│ ├── 자재 분류, BOM 생성
|
||
│ └── 리비전 관리, 파일 처리
|
||
├── 🏗️ 프로젝트 관리 모듈 (신규)
|
||
│ ├── 프로젝트 생성, 일정 관리
|
||
│ └── 진행률 추적, 마일스톤
|
||
├── 💰 견적/계약 관리 모듈 (신규)
|
||
│ ├── 견적서 생성, 계약 관리
|
||
│ └── 가격 정책, 승인 워크플로우
|
||
├── 📦 구매/조달 관리 모듈 (신규)
|
||
│ ├── 발주, 입고 관리
|
||
│ └── 공급업체 관리, 재고 추적
|
||
├── 🏭 생산 관리 모듈 (신규)
|
||
│ ├── 작업 지시, 공정 관리
|
||
│ └── 품질 관리, 진행 상황
|
||
└── 🚚 출하 관리 모듈 (신규)
|
||
├── 포장, 배송 관리
|
||
└── 납품 확인, 고객 피드백
|
||
```
|
||
|
||
##### **기술 아키텍처**
|
||
- **API Gateway**: 통합 라우팅 및 인증
|
||
- **모듈 간 통신**: REST API + 이벤트 기반
|
||
- **데이터베이스**: PostgreSQL 통합 DB
|
||
- **캐싱**: Redis 분산 캐시
|
||
- **메시지 큐**: 비동기 처리 (Redis Pub/Sub)
|
||
|
||
#### **🚀 단계별 구현 계획**
|
||
|
||
##### **Phase 5.1: 인증 시스템 구축** (1개월) 🔄
|
||
|
||
###### **TK-FB-Project 인증 시스템 분석 완료** ✅
|
||
- **아키텍처**: Controller → Service → Model → Database 계층화 구조
|
||
- **JWT 토큰**: Access Token (24h) + Refresh Token (7d)
|
||
- **RBAC 권한**: admin, system, leader, support, user (5단계)
|
||
- **보안 기능**: 계정 잠금, 로그인 이력, bcrypt 해싱
|
||
|
||
###### **구현 순서 및 상세 계획**
|
||
|
||
**Step 1: 데이터베이스 스키마 생성** (3일)
|
||
```sql
|
||
-- 사용자 테이블
|
||
CREATE TABLE users (
|
||
user_id SERIAL PRIMARY KEY,
|
||
username VARCHAR(50) UNIQUE NOT NULL,
|
||
password VARCHAR(255) NOT NULL,
|
||
name VARCHAR(100) NOT NULL,
|
||
email VARCHAR(100),
|
||
role VARCHAR(20) DEFAULT 'user',
|
||
access_level VARCHAR(20) DEFAULT 'worker',
|
||
is_active BOOLEAN DEFAULT true,
|
||
failed_login_attempts INT DEFAULT 0,
|
||
locked_until TIMESTAMP NULL,
|
||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||
);
|
||
|
||
-- 로그인 이력 테이블
|
||
CREATE TABLE login_logs (
|
||
log_id SERIAL PRIMARY KEY,
|
||
user_id INT REFERENCES users(user_id),
|
||
login_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||
ip_address VARCHAR(45),
|
||
user_agent TEXT,
|
||
login_status VARCHAR(20),
|
||
failure_reason VARCHAR(100)
|
||
);
|
||
```
|
||
|
||
**Step 2: 백엔드 인증 API 구현** (7일)
|
||
- `backend/app/auth/` 모듈 생성
|
||
- JWT 토큰 생성/검증 서비스
|
||
- 사용자 모델 및 인증 컨트롤러
|
||
- 권한 미들웨어 구현
|
||
|
||
**Step 3: 프론트엔드 로그인 시스템** (5일)
|
||
- 로그인/회원가입 페이지
|
||
- JWT 토큰 관리 (localStorage/sessionStorage)
|
||
- 인증 상태 관리 (Context API)
|
||
- 보호된 라우트 구현
|
||
|
||
**Step 4: 권한 기반 접근 제어** (7일)
|
||
- 역할별 메뉴 표시/숨김
|
||
- API 엔드포인트 권한 검증
|
||
- 관리자 페이지 구현
|
||
- 사용자 관리 기능
|
||
|
||
**Step 5: 보안 강화 및 테스트** (8일)
|
||
- 계정 잠금 로직
|
||
- 로그인 이력 추적
|
||
- 보안 테스트 및 검증
|
||
- 문서화 및 배포
|
||
|
||
##### **Phase 5.2: 모듈 분리** (2개월)
|
||
- 현재 BOM 관리 기능 모듈화
|
||
- 프로젝트 관리 기능 분리
|
||
- API Gateway 구축
|
||
|
||
##### **Phase 5.3: 프로젝트 관리 모듈** (3개월)
|
||
- 프로젝트 생성/수정/삭제
|
||
- 일정 관리 및 간트 차트
|
||
- 진행률 대시보드
|
||
|
||
##### **Phase 5.4: 견적/계약 관리** (3개월)
|
||
- 견적서 자동 생성
|
||
- 계약 관리 워크플로우
|
||
- 승인 프로세스
|
||
|
||
##### **Phase 5.5: 구매/조달 관리** (4개월)
|
||
- BOM 기반 자동 발주
|
||
- 공급업체 관리
|
||
- 재고 관리 시스템
|
||
|
||
#### **🎯 성능 목표**
|
||
- **동시 사용자**: 15명 이상 지원
|
||
- **응답 시간**: API 평균 200ms 이하
|
||
- **가용성**: 99.5% 이상
|
||
- **확장성**: 모듈별 독립 확장 가능
|
||
|
||
### 🐳 **Docker 개발 환경 가이드라인** ⚠️
|
||
|
||
#### **중요: 모든 개발은 Docker 환경에서 진행**
|
||
- **시스템 라이브러리 설치 시**: 로컬이 아닌 **Dockerfile에 추가** 필수
|
||
- **Python 패키지 설치 시**: **requirements.txt에 추가** 후 컨테이너 재빌드
|
||
- **환경 변수 설정**: **docker-compose.yml** 또는 **.env** 파일 사용
|
||
|
||
#### **라이브러리 설치 예시**
|
||
```dockerfile
|
||
# ❌ 잘못된 방법: 로컬에만 설치
|
||
# brew install libmagic (macOS)
|
||
# apt-get install libmagic1 (로컬 Ubuntu)
|
||
|
||
# ✅ 올바른 방법: Dockerfile에 추가
|
||
RUN apt-get update && apt-get install -y \
|
||
gcc \
|
||
g++ \
|
||
libpq-dev \
|
||
libmagic1 \
|
||
libmagic-dev \
|
||
&& rm -rf /var/lib/apt/lists/*
|
||
```
|
||
|
||
#### **개발 워크플로우**
|
||
1. **패키지 추가**: `requirements.txt` 수정
|
||
2. **시스템 라이브러리 추가**: `Dockerfile` 수정
|
||
3. **컨테이너 재빌드**: `docker-compose down && docker-compose up --build -d`
|
||
4. **테스트**: Docker 환경에서 확인
|
||
|
||
#### **포트 정보**
|
||
- **프론트엔드**: http://localhost:13000
|
||
- **백엔드 API**: http://localhost:18000
|
||
- **PostgreSQL**: localhost:5432
|
||
- **Redis**: localhost:6379
|
||
- **pgAdmin**: http://localhost:5050
|
||
|
||
### 📋 **개발 우선순위 가이드라인**
|
||
1. **보안 이슈** - 즉시 수정 필요
|
||
2. **시스템 안정성** - 높은 우선순위
|
||
3. **성능 최적화** - 중간 우선순위
|
||
4. **코드 품질** - 지속적 개선
|
||
5. **새 기능 추가** - 낮은 우선순위
|
||
|
||
---
|
||
|
||
## Phase 5.1: 인증 시스템 구축 완료 ✅
|
||
|
||
### **구현 완료 사항**
|
||
|
||
#### **백엔드 인증 시스템**
|
||
- ✅ **JWT 토큰 서비스**: 액세스/리프레시 토큰 생성 및 검증
|
||
- ✅ **SQLAlchemy 모델**: User, LoginLog, UserSession, Permission, RolePermission
|
||
- ✅ **인증 비즈니스 로직**: 회원가입, 로그인, 토큰 갱신, 사용자 관리
|
||
- ✅ **FastAPI 엔드포인트**: `/auth/register`, `/auth/login`, `/auth/refresh`, `/auth/logout`, `/auth/me`, `/auth/users`
|
||
- ✅ **RBAC 미들웨어**: 역할 및 권한 기반 접근 제어
|
||
- ✅ **데이터베이스 스키마**: 인증 관련 테이블 생성 및 초기 데이터
|
||
|
||
#### **프론트엔드 인증 시스템**
|
||
- ✅ **SimpleLogin 컴포넌트**: 깔끔한 로그인 인터페이스
|
||
- ✅ **SimpleDashboard 컴포넌트**: 사용자 정보 표시 및 권한 확인
|
||
- ✅ **자동 라우팅**: 로그인 성공 시 대시보드 자동 이동
|
||
- ✅ **토큰 관리**: localStorage 기반 토큰 저장 및 자동 로그인
|
||
- ✅ **로그아웃 기능**: 토큰 삭제 및 로그인 페이지 복귀
|
||
|
||
#### **보안 기능**
|
||
- ✅ **비밀번호 해싱**: bcrypt 기반 안전한 비밀번호 저장
|
||
- ✅ **JWT 보안**: 액세스/리프레시 토큰 분리, 만료 시간 설정
|
||
- ✅ **로그인 이력**: 모든 로그인 시도 기록 및 추적
|
||
- ✅ **계정 잠금**: 실패 시도 횟수 제한 (향후 확장 가능)
|
||
|
||
#### **테스트 계정**
|
||
- **관리자**: `admin` / `admin123`
|
||
- **일반 사용자**: `testuser` / `test123`
|
||
|
||
### **다음 단계: Phase 5.2 - 네비게이션 시스템**
|
||
1. 권한별 메뉴 시스템 구현
|
||
2. 기존 BOM/프로젝트 관리 기능 통합
|
||
3. 관리자용 사용자 관리 페이지
|
||
4. 세분화된 권한 관리 시스템
|
||
|
||
---
|
||
|
||
## 📊 **사용자 추적 및 담당자 기록 가이드라인** (2025.01 신규)
|
||
|
||
### 🎯 **기본 원칙**
|
||
- **모든 업무 활동은 담당자가 기록되어야 함**
|
||
- **추적 가능한 업무 이력 관리**
|
||
- **개인별 맞춤형 대시보드 제공**
|
||
- **권한별 차별화된 정보 표시**
|
||
|
||
### 📋 **필수 기록 대상**
|
||
|
||
#### **1. 파일 관리**
|
||
```sql
|
||
-- 파일 업로드 시 필수 기록
|
||
uploaded_by VARCHAR(100) NOT NULL, -- 업로드한 사용자
|
||
upload_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||
updated_by VARCHAR(100), -- 수정한 사용자 (파일 수정 시)
|
||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||
```
|
||
|
||
#### **2. 프로젝트 관리**
|
||
```sql
|
||
-- 프로젝트 생성/수정 시 필수 기록
|
||
created_by VARCHAR(100) NOT NULL, -- 프로젝트 생성자
|
||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||
updated_by VARCHAR(100), -- 마지막 수정자
|
||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||
assigned_to VARCHAR(100), -- 프로젝트 담당자
|
||
```
|
||
|
||
#### **3. 자재 관리**
|
||
```sql
|
||
-- 자재 분류/검증 시 필수 기록
|
||
classified_by VARCHAR(100), -- 자재 분류 담당자
|
||
classified_at TIMESTAMP,
|
||
verified_by VARCHAR(100), -- 검증 담당자
|
||
verified_at TIMESTAMP,
|
||
updated_by VARCHAR(100), -- 수정 담당자
|
||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||
```
|
||
|
||
#### **4. 구매 관리**
|
||
```sql
|
||
-- 구매 확정/발주 시 필수 기록
|
||
confirmed_by VARCHAR(100) NOT NULL, -- 구매 확정자
|
||
confirmed_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||
ordered_by VARCHAR(100), -- 발주 담당자
|
||
ordered_at TIMESTAMP,
|
||
approved_by VARCHAR(100), -- 승인자 (고액 구매 시)
|
||
approved_at TIMESTAMP
|
||
```
|
||
|
||
### 🔐 **권한별 접근 제어**
|
||
|
||
#### **관리자 (admin)**
|
||
- 모든 프로젝트 조회/수정 가능
|
||
- 사용자 관리 및 권한 설정
|
||
- 시스템 설정 및 백업 관리
|
||
- 전체 활동 로그 조회
|
||
|
||
#### **프로젝트 매니저 (manager)**
|
||
- 담당 프로젝트 전체 관리
|
||
- 팀원 업무 할당 및 진행 상황 모니터링
|
||
- 구매 승인 권한 (일정 금액 이하)
|
||
- 프로젝트별 리포트 생성
|
||
|
||
#### **설계 담당자 (designer)**
|
||
- 담당 프로젝트 BOM 업로드/수정
|
||
- 자재 분류 및 검증
|
||
- 리비전 관리
|
||
- 구매 요청서 작성
|
||
|
||
#### **구매 담당자 (purchaser)**
|
||
- 구매 품목 조회 및 발주
|
||
- 공급업체 관리
|
||
- 구매 현황 추적
|
||
- 입고 관리
|
||
|
||
#### **조회 전용 (viewer)**
|
||
- 할당된 프로젝트 조회만 가능
|
||
- 리포트 다운로드
|
||
- 진행 상황 확인
|
||
|
||
### 📈 **개인별 대시보드 구성**
|
||
|
||
#### **1. 맞춤형 배너 시스템**
|
||
```javascript
|
||
// 사용자별 맞춤 정보 표시
|
||
const personalizedBanner = {
|
||
admin: {
|
||
title: "시스템 관리자",
|
||
metrics: ["전체 프로젝트 수", "활성 사용자 수", "시스템 상태"],
|
||
quickActions: ["사용자 관리", "시스템 설정", "백업 관리"]
|
||
},
|
||
manager: {
|
||
title: "프로젝트 매니저",
|
||
metrics: ["담당 프로젝트", "팀 진행률", "승인 대기"],
|
||
quickActions: ["프로젝트 생성", "팀 관리", "진행 상황"]
|
||
},
|
||
designer: {
|
||
title: "설계 담당자",
|
||
metrics: ["내 BOM 파일", "분류 완료율", "검증 대기"],
|
||
quickActions: ["BOM 업로드", "자재 분류", "리비전 관리"]
|
||
},
|
||
purchaser: {
|
||
title: "구매 담당자",
|
||
metrics: ["구매 요청", "발주 완료", "입고 대기"],
|
||
quickActions: ["구매 확정", "발주 관리", "공급업체"]
|
||
}
|
||
};
|
||
```
|
||
|
||
#### **2. 활동 이력 추적**
|
||
```sql
|
||
-- 사용자 활동 로그 테이블
|
||
CREATE TABLE user_activity_logs (
|
||
id SERIAL PRIMARY KEY,
|
||
user_id INTEGER REFERENCES users(user_id),
|
||
username VARCHAR(100) NOT NULL,
|
||
activity_type VARCHAR(50) NOT NULL, -- 'FILE_UPLOAD', 'PROJECT_CREATE', 'PURCHASE_CONFIRM' 등
|
||
activity_description TEXT, -- 상세 활동 내용
|
||
target_id INTEGER, -- 대상 ID (파일, 프로젝트 등)
|
||
target_type VARCHAR(50), -- 'FILE', 'PROJECT', 'MATERIAL' 등
|
||
ip_address VARCHAR(45),
|
||
user_agent TEXT,
|
||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||
);
|
||
```
|
||
|
||
#### **3. 개인 작업 현황**
|
||
- **내가 업로드한 파일**: 최근 업로드한 BOM 파일 목록
|
||
- **내가 담당한 프로젝트**: 할당된 프로젝트 진행 상황
|
||
- **내 업무 대기**: 분류/검증/승인 대기 중인 업무
|
||
- **최근 활동**: 최근 7일간 활동 요약
|
||
|
||
### 🚀 **구현 우선순위**
|
||
|
||
#### **Phase 1: 기본 사용자 추적** (1주)
|
||
1. 현재 테이블에 담당자 필드 추가
|
||
2. 파일 업로드 시 사용자 정보 기록
|
||
3. 기본 활동 로그 시스템 구축
|
||
|
||
#### **Phase 2: 개인별 대시보드** (2주)
|
||
1. 권한별 맞춤형 배너 구현
|
||
2. 개인 작업 현황 페이지
|
||
3. 활동 이력 조회 기능
|
||
|
||
#### **Phase 3: 고도화** (3주)
|
||
1. 상세 권한 관리 시스템
|
||
2. 팀별/부서별 대시보드
|
||
3. 업무 할당 및 알림 시스템
|
||
|
||
### ⚠️ **주의사항**
|
||
- **개인정보 보호**: 사용자 활동 로그는 업무 목적으로만 사용
|
||
- **데이터 보존**: 활동 로그는 최대 1년간 보존 후 자동 삭제
|
||
- **접근 권한**: 개인 활동 이력은 본인과 관리자만 조회 가능
|
||
- **감사 추적**: 중요 업무(구매 확정, 프로젝트 삭제 등)는 별도 감사 로그 유지
|
||
|
||
---
|
||
|
||
## 🚨 **프로덕션 배포 전 필수 보안 체크리스트** (2025.01 신규)
|
||
|
||
> ⚠️ **중요**: 현재 설정은 **테스트 환경용**입니다. 실제 서비스 배포 전 반드시 아래 항목들을 수정해야 합니다.
|
||
|
||
### 🔐 **Critical Security Items (배포 전 필수)**
|
||
|
||
#### **1. JWT 시크릿 키 환경변수화**
|
||
```bash
|
||
# ❌ 현재 (테스트용)
|
||
SECRET_KEY = "test-secret-key"
|
||
|
||
# ✅ 배포 전 필수 변경
|
||
JWT_SECRET_KEY=your-super-secure-random-key-here # .env 파일에 추가
|
||
```
|
||
|
||
#### **2. 데이터베이스 비밀번호 보안**
|
||
```yaml
|
||
# ❌ 현재 (테스트용)
|
||
POSTGRES_PASSWORD: tkmp_password_2025
|
||
|
||
# ✅ 배포 전 필수 변경
|
||
POSTGRES_PASSWORD: ${DB_PASSWORD} # 환경변수로 분리
|
||
```
|
||
|
||
#### **3. CORS 도메인 설정**
|
||
```python
|
||
# ❌ 현재 (테스트용)
|
||
"production": [
|
||
"https://your-domain.com",
|
||
"https://api.your-domain.com"
|
||
]
|
||
|
||
# ✅ 배포 전 필수 변경
|
||
"production": [
|
||
"https://실제도메인.com",
|
||
"https://api.실제도메인.com"
|
||
]
|
||
```
|
||
|
||
#### **4. 기본 관리자 계정 변경**
|
||
```sql
|
||
-- ❌ 현재 (테스트용)
|
||
INSERT INTO users (username, password) VALUES ('admin', 'admin123');
|
||
|
||
-- ✅ 배포 전 필수 변경
|
||
-- 강력한 비밀번호로 변경 및 테스트 계정 삭제
|
||
```
|
||
|
||
### 🛡️ **배포 전 보안 체크리스트**
|
||
|
||
- [ ] **환경변수 분리**: 모든 민감 정보를 .env 파일로 분리
|
||
- [ ] **HTTPS 적용**: SSL 인증서 설치 및 HTTP → HTTPS 리다이렉트
|
||
- [ ] **방화벽 설정**: 필요한 포트만 개방 (80, 443, SSH)
|
||
- [ ] **데이터베이스 접근 제한**: 외부 접근 차단, 애플리케이션에서만 접근
|
||
- [ ] **로그 파일 보안**: 민감 정보 로깅 방지, 로그 파일 권한 설정
|
||
- [ ] **백업 전략**: 정기 백업 및 복구 테스트
|
||
- [ ] **모니터링**: 시스템 상태 및 보안 이벤트 모니터링
|
||
- [ ] **업데이트 계획**: 보안 패치 및 의존성 업데이트 계획
|
||
|
||
### 📋 **배포 환경별 설정 가이드**
|
||
|
||
#### **개발 환경 (현재)**
|
||
```bash
|
||
ENVIRONMENT=development
|
||
DEBUG=true
|
||
CORS_ORIGINS=http://localhost:3000,http://localhost:13000
|
||
```
|
||
|
||
#### **스테이징 환경**
|
||
```bash
|
||
ENVIRONMENT=staging
|
||
DEBUG=false
|
||
CORS_ORIGINS=https://staging.your-domain.com
|
||
```
|
||
|
||
#### **프로덕션 환경**
|
||
```bash
|
||
ENVIRONMENT=production
|
||
DEBUG=false
|
||
CORS_ORIGINS=https://your-domain.com
|
||
JWT_SECRET_KEY=강력한-랜덤-키
|
||
DB_PASSWORD=강력한-데이터베이스-비밀번호
|
||
```
|
||
|
||
---
|
||
|
||
## 📋 **API 정리 요약** (2025.09.05 완료)
|
||
|
||
### ✅ **해결된 문제들**
|
||
1. **404 오류 해결**: `/files/materials` → `/files/materials-v2` 마이그레이션
|
||
2. **API 호출 표준화**: 직접 호출 → `fetchMaterials()` 함수 사용
|
||
3. **혼동 방지**: 명확한 API 사용 가이드라인 수립
|
||
4. **문서화 완성**: 실제 구현된 모든 API 엔드포인트 정리
|
||
|
||
### 🎯 **표준화된 사용법**
|
||
```javascript
|
||
// ✅ 권장 방법
|
||
import { fetchMaterials, fetchFiles, fetchJobs } from '../api';
|
||
|
||
// 파일별 자재 조회
|
||
const materials = await fetchMaterials({ file_id: 123 });
|
||
|
||
// 프로젝트별 자재 조회
|
||
const materials = await fetchMaterials({ job_no: 'J24-001' });
|
||
|
||
// 리비전별 자재 조회
|
||
const materials = await fetchMaterials({
|
||
job_no: 'J24-001',
|
||
revision: 'Rev.1'
|
||
});
|
||
```
|
||
|
||
### 🚨 **중요 규칙**
|
||
- **모든 자재 API 호출은 `fetchMaterials()` 함수 사용**
|
||
- **직접 API 호출 금지** (특별한 경우 제외)
|
||
- **새 API 추가 시 RULES.md 즉시 업데이트**
|
||
- **API 변경 시 하위 호환성 고려**
|
||
|
||
---
|
||
|
||
## 🔍 자재 분류 규칙
|
||
|
||
### 핵심 분류 원칙
|
||
|
||
#### 1. 니플(NIPPLE) 특수 규칙 ⚠️
|
||
- **분류 방식**: 파이프 분류기(pipe_classifier)로 분류하지만 **카테고리는 FITTING으로 처리**
|
||
- **이유**: 니플은 파이프와 동일한 재질/스펙을 가지지만, 용도상 피팅류로 취급
|
||
- **길이 기반 그룹핑**: 같은 스펙이라도 길이가 다르면 별도 항목으로 분리
|
||
- 예: `NIPPLE 1" 75mm` vs `NIPPLE 1" 100mm`
|
||
- **총길이 계산**: 개별 니플 길이 × 수량을 합산하여 실제 총길이 표시
|
||
- **끝단 가공 처리**: 파이프와 동일하게 PBE, BBE, POE 등 끝단 가공 정보 분리 저장
|
||
- **그룹핑 키**: `clean_description|size_spec|material_grade|length_mm`
|
||
|
||
#### 2. 파이프(PIPE) 분류 규칙
|
||
- **그룹핑 키**: `clean_description|size_spec|material_grade`
|
||
- **끝단 가공 제외**: 구매용 그룹핑에서는 BBE, POE, PBE 등 끝단 가공 정보 제외
|
||
- **개별 정보 보존**: 각 파이프의 끝단 가공 정보는 `pipe_end_preparations` 테이블에 별도 저장
|
||
- **총길이 계산**: 동일 스펙 파이프들의 개별 길이 합산
|
||
|
||
#### 3. 기타 피팅(FITTING) 분류 규칙
|
||
- **일반 피팅**: 수량 기반 집계 (ELBOW, TEE, REDUCER 등)
|
||
- **길이 정보 없음**: 니플을 제외한 일반 피팅은 길이 기반 그룹핑 불필요
|
||
|
||
### 분류 우선순위
|
||
1. **PIPE**: 파이프 분류기 우선 적용
|
||
2. **FITTING**: 니플 포함, 피팅 분류기 적용
|
||
3. **VALVE**: 밸브 분류기 적용
|
||
4. **FLANGE**: 플랜지 분류기 적용
|
||
5. **BOLT**: 볼트 분류기 적용
|
||
6. **GASKET**: 가스켓 분류기 적용
|
||
7. **INSTRUMENT**: 계기 분류기 적용
|
||
|
||
### 끝단 가공 코드 정의
|
||
- **PBE**: Plain Both Ends (양쪽 무개선) - 기본값
|
||
- **BBE**: Both Ends Beveled (양쪽 개선)
|
||
- **POE**: Plain One End (한쪽 무개선)
|
||
- **BOE**: Beveled One End (한쪽 개선)
|
||
- **TOE**: Threaded One End (한쪽 나사)
|
||
|
||
---
|
||
|
||
## 🔧 **사용자 피드백 기반 개선사항** (2025.09.24)
|
||
|
||
### 📋 **개선 요구사항 목록**
|
||
|
||
#### **1. 사용자 요구사항 엑셀 반영** ⚡ 우선순위: 높음
|
||
- **문제**: 자재 목록 페이지에서 작성한 사용자 요구사항이 엑셀 다운로드 시 미반영
|
||
- **해결방안**:
|
||
- 사용자 요구사항 저장 API 구현
|
||
- 엑셀 내보내기 시 사용자 요구사항 컬럼 추가
|
||
- 백엔드-프론트엔드 연동 강화
|
||
|
||
#### **2. 재질 GRADE 전체 표기** ⚡ 우선순위: 높음
|
||
- **문제**: 현재 `ASTM A312 WP304` → 입력된 전체 재질명 표기 필요
|
||
- **적용 범위**: 모든 자재 (파이프, 엘보, 플랜지 등)
|
||
- **원칙**: 생략이나 축약 금지, 원본 재질명 그대로 표시
|
||
|
||
#### **3. U-Bolt & Urethane Block 카테고리** ⚡ 우선순위: 중간
|
||
- **신규 카테고리**: U-BOLT, URETHANE_BLOCK
|
||
- **분류 기준**: 크기별, 재질별, 기타 사양별
|
||
- **분류기**: 필요시 구현, 우선은 수동 분류
|
||
|
||
#### **4. Special Flange 비기성품 정리** ⚡ 우선순위: 중간
|
||
- **위치**: 각 카테고리 맨 하단에 배치
|
||
- **정보**: 재질, 사이즈, 특수 사양 상세 표기
|
||
- **구분**: 기성품과 명확히 구분되도록 표시
|
||
|
||
#### **5. 플랜지 타입 정보 확장** ⚡ 우선순위: 중간
|
||
- **현재**: WN, BW 등 기본 정보만 표기
|
||
- **개선**: pipe측 타입도 표기 (WN RF, SW RF, SO RF)
|
||
- **적용**: 플랜지 상세 정보 확장
|
||
|
||
#### **6. Nipple 끝단 정보 표기** ⚡ 우선순위: 중간
|
||
- **현재**: 끝단 정보 수집하지만 표기 안함
|
||
- **개선**: 타입/상세 부분에 끝단 정보 표기
|
||
- **연동**: 기존 끝단 가공 코드 활용
|
||
|
||
#### **7. Reducing 배관 Schedule 분리** ⚡ 우선순위: 중간
|
||
- **문제**: Main pipe와 Sub pipe의 Schedule이 다를 수 있음
|
||
- **해결**: Schedule 표기 시 2개로 분리 표현
|
||
- **형식**: `Main Sch.40 / Sub Sch.80` 형태
|
||
|
||
#### **8. 웹 화면 내용 잘림 해결** ⚡ 우선순위: 높음
|
||
- **문제**: 긴 내용이 웹 화면에서 잘리는 현상
|
||
- **해결**: 컬럼 너비 확장, 텍스트 래핑 개선
|
||
- **적용**: 모든 테이블 및 목록 화면
|
||
|
||
#### **9. 자재 전체 목록 카테고리 추가** ⚡ 우선순위: 낮음
|
||
- **추가**: 자재목록 카테고리에 "자재 전체 목록" 옵션
|
||
- **기능**: 모든 카테고리 통합 조회
|
||
- **정렬**: 카테고리별 그룹핑 또는 통합 정렬
|
||
|
||
#### **10. 자재 목록 분류 필터 기능** ⚡ 우선순위: 중간
|
||
- **위치**: 자재 목록 페이지 분류 섹션
|
||
- **기능**: 카테고리별, 재질별, 사이즈별 필터링
|
||
- **UI**: 드롭다운 또는 체크박스 형태
|
||
|
||
#### **11. 자재 리비전 비교 개선** ⚡ 우선순위: 높음
|
||
- **현재**: 과거 기준 없는 것만 표시
|
||
- **개선**: 남는 것(기존) / 필요한 것(신규) 분리 표현
|
||
- **UI**: 탭 또는 섹션으로 구분하여 표시
|
||
|
||
### 🚀 **구현 우선순위**
|
||
|
||
#### **Phase 1: 핵심 기능 개선** (1-2주)
|
||
1. 사용자 요구사항 엑셀 반영 (#1)
|
||
2. 재질 GRADE 전체 표기 (#2)
|
||
3. 웹 화면 내용 잘림 해결 (#8)
|
||
4. 자재 리비전 비교 개선 (#11)
|
||
|
||
#### **Phase 2: 분류 및 표기 개선** (2-3주)
|
||
5. 플랜지 타입 정보 확장 (#5)
|
||
6. Nipple 끝단 정보 표기 (#6)
|
||
7. Reducing 배관 Schedule 분리 (#7)
|
||
8. 자재 목록 분류 필터 기능 (#10)
|
||
|
||
#### **Phase 3: 신규 카테고리 및 기능** (3-4주)
|
||
9. U-Bolt & Urethane Block 카테고리 (#3)
|
||
10. Special Flange 비기성품 정리 (#4)
|
||
11. 자재 전체 목록 카테고리 추가 (#9)
|
||
|
||
### 📝 **개발 가이드라인**
|
||
|
||
#### **코드 수정 원칙**
|
||
- **하위 호환성**: 기존 데이터 구조 유지
|
||
- **점진적 개선**: 단계별 구현으로 안정성 확보
|
||
- **테스트**: 각 개선사항별 충분한 테스트
|
||
- **문서화**: 변경사항 즉시 문서 반영
|
||
|
||
#### **데이터베이스 변경**
|
||
- **스키마 확장**: 기존 테이블에 컬럼 추가 방식 우선
|
||
- **마이그레이션**: 단계별 스크립트 작성
|
||
- **백업**: 변경 전 데이터 백업 필수
|
||
|
||
#### **UI/UX 개선**
|
||
- **반응형**: 모바일/태블릿 호환성 유지
|
||
- **접근성**: 사용자 친화적 인터페이스
|
||
- **성능**: 대용량 데이터 처리 최적화
|
||
|
||
---
|
||
|
||
## 🚀 메인 서버 배포 가이드
|
||
|
||
### 📋 **데이터베이스 마이그레이션**
|
||
|
||
메인 서버에 배포할 때 반드시 실행해야 하는 데이터베이스 마이그레이션:
|
||
|
||
#### **필수 추가 컬럼들** (materials 테이블)
|
||
```sql
|
||
-- 파이프 사이즈 정보
|
||
ALTER TABLE materials ADD COLUMN IF NOT EXISTS main_nom VARCHAR(50);
|
||
ALTER TABLE materials ADD COLUMN IF NOT EXISTS red_nom VARCHAR(50);
|
||
|
||
-- 전체 재질명
|
||
ALTER TABLE materials ADD COLUMN IF NOT EXISTS full_material_grade TEXT;
|
||
|
||
-- 업로드 행 번호
|
||
ALTER TABLE materials ADD COLUMN IF NOT EXISTS row_number INTEGER;
|
||
```
|
||
|
||
#### **성능 최적화 인덱스**
|
||
```sql
|
||
CREATE INDEX IF NOT EXISTS idx_materials_main_nom ON materials(main_nom);
|
||
CREATE INDEX IF NOT EXISTS idx_materials_red_nom ON materials(red_nom);
|
||
CREATE INDEX IF NOT EXISTS idx_materials_full_material_grade ON materials(full_material_grade);
|
||
```
|
||
|
||
#### **자동 마이그레이션 스크립트**
|
||
```bash
|
||
# 메인 서버에서 실행
|
||
psql -U tkmp_user -d tk_mp_bom -f backend/scripts/PRODUCTION_MIGRATION.sql
|
||
```
|
||
|
||
### ⚠️ **중요 사항**
|
||
- 이 컬럼들이 없으면 파일 업로드 시 500 에러 발생
|
||
- 완전 초기화 시: `database/init/99_complete_schema.sql` 사용
|
||
- 기존 서버 업데이트 시: `backend/scripts/PRODUCTION_MIGRATION.sql` 사용
|
||
|
||
### 🔧 **배포 체크리스트**
|
||
1. [ ] 데이터베이스 백업
|
||
2. [ ] 마이그레이션 스크립트 실행
|
||
3. [ ] 컬럼 존재 확인
|
||
4. [ ] 파일 업로드 테스트
|
||
5. [ ] 자재 분류 기능 테스트
|
||
|
||
---
|
||
|
||
**마지막 업데이트**: 2025년 9월 28일 (메인 서버 배포 가이드 추가)
|