Files
TK-BOM-Project/RULES.md
Hyungi Ahn 28a1302cae
Some checks failed
SonarQube Analysis / SonarQube Scan (push) Has been cancelled
📝 RULES.md 업데이트: Docker 환경 구성 및 트러블슈팅 가이드 추가
- Docker 컨테이너 구성 및 실행 방법 명시
- 해결된 주요 문제들 문서화:
  * 프론트엔드 API 연결 오류 (10080 포트 문제)
  * 백엔드 데이터베이스 연결 실패 (localhost vs postgres)
  * 환경별 설정 관리 개선
- 실행 전 체크리스트 제공으로 향후 헷갈림 방지
2025-08-01 13:46:37 +09:00

286 lines
9.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 🏗️ TK-MP-Project Rules & Context
## 📋 **프로젝트 개요**
- **목적**: 배관 자재 BOM 관리 및 리비전 비교 시스템
- **주요 기능**: 파일 업로드, 자재 분류, 리비전 비교, 구매 관리, 엑셀 내보내기
## 🛠️ **기술 스택**
```
Frontend: React.js + Material-UI + Vite + React Router DOM + Nginx
Backend: FastAPI + SQLAlchemy + Python + Uvicorn
Database: PostgreSQL (운영 및 개발)
캐시: Redis
관리도구: pgAdmin4
컨테이너: Docker + Docker Compose
기타: Axios, XLSX (SheetJS), file-saver
```
## 📁 **프로젝트 구조**
```
TK-MP-Project/
├── frontend/src/
│ ├── pages/ # 페이지 컴포넌트
│ ├── components/ # 재사용 컴포넌트
│ ├── utils/ # 유틸리티 (엑셀 등)
│ └── api.js # API 통신
├── backend/app/
│ ├── routers/ # API 라우터
│ ├── services/ # 비즈니스 로직 (분류기 등)
│ ├── models.py # DB 모델
│ └── main.py # FastAPI 앱
└── database/ # DB 스키마/시드
```
## 🐳 **Docker 실행 환경**
### 컨테이너 구성
- **tk-mp-frontend**: React + Nginx (포트: 3000)
- **tk-mp-backend**: FastAPI + Uvicorn (포트: 8000)
- **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
# 기본 환경
docker-compose up -d
```
### 중요한 설정 사항
- **API URL 설정**:
- 개발환경: `http://localhost:8000` (직접 접근)
- 프로덕션: `/api` (nginx 프록시를 통한 상대경로)
- **데이터베이스 연결**: `postgres:5432` (컨테이너명 사용, localhost 아님!)
- **환경변수**: `VITE_API_URL`로 API URL 오버라이드 가능
## 🗄️ **핵심 데이터베이스 스키마**
```sql
-- 핵심 테이블들
jobs (job_no, job_name, client_name, ...)
files (id, job_no, revision, original_filename, ...)
materials (id, file_id, original_description, classified_category, quantity, ...)
pipe_details (material_id, length_mm, ...)
-- 기타: fitting_details, flange_details, bolt_details, gasket_details
```
## 🔧 **중요한 코딩 컨벤션 & 패턴**
### **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. 리비전 비교 로직**
```python
# 이전 리비전 자동 탐지: 숫자 기반 비교
current_rev_num = int(current_revision.replace("Rev.", ""))
# Rev.0 → Rev.1 → Rev.2 순서
```
## 🐛 **자주 발생하는 이슈 & 해결법**
### **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}`);
```
## 🔄 **개발 워크플로우**
### **1. 서버 실행 명령어**
```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 8000
# 프론트엔드 실행 (터미널 2번) - TK-MP-Project 루트에서
cd frontend
npm run dev # npm start 아님!
```
**접속 주소:**
- 백엔드 API: http://localhost:8000
- API 문서: http://localhost:8000/docs
- 프론트엔드: http://localhost:5173
### **2. 백엔드 변경 시**
```bash
# 항상 가상환경에서 실행 (사용자 선호사항)
cd backend
python -m uvicorn app.main:app --reload --host 0.0.0.0 --port 8000
```
### **3. 데이터베이스 스키마 변경 시**
```sql
-- scripts/ 폴더에 마이그레이션 SQL 파일 생성
-- 번호 순서: 01_, 02_, 03_...
```
### **4. 커밋 메시지**
```
한국어로 작성 (사용자 선호사항)
예: "파이프 길이 계산 및 엑셀 내보내기 버그 수정"
```
## ⚠️ **절대 하지 말아야 할 것들**
1. **파이프 "평균단위" 표시** - 사용자가 혼란스러워함
2. **하드코딩된 길이 값** - 실제 데이터베이스 값 사용
3. **영어 커밋 메시지** - 사용자가 한국어 선호
4. **SQL에서 과도한 GROUP BY** - 같은 자재 분리됨
5. **비율 기반 길이 계산** - 실제 총길이 사용해야 함
## 💰 **구매 수량 계산 규칙**
### **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
```
## 🎯 **현재 진행 상황**
- ✅ 자재 업로드 및 분류 시스템
- ✅ 리비전 비교 기능
- ✅ 파이프 길이 합산 로직 수정
- ✅ 엑셀 내보내기 기능
- 🚧 구매 수량 계산 시스템 (진행 중)
## 📚 **추가 참고사항**
- 사용자는 가상환경에서 Python 실행을 선호
- 백엔드 서버는 자동 재시작되므로 수동 재시작 불필요
- 작업 상태는 'in-progress'와 'complete'를 명확히 표시
---
## 🚨 **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
)
```
3. **환경별 설정 관리 개선**
- **문제**: 개발/프로덕션 환경 구분 없이 하드코딩
- **해결**: docker-compose 파일 분리
```bash
docker-compose.yml # 기본 설정
docker-compose.dev.yml # 개발 환경 오버라이드
docker-compose.prod.yml # 프로덕션 환경 오버라이드
```
### 실행 전 체크리스트
- [ ] Docker 및 Docker Compose 설치 확인
- [ ] 모든 컨테이너 정상 실행 확인: `docker-compose ps`
- [ ] 백엔드 API 문서 접근 가능: http://localhost:8000/docs
- [ ] 프론트엔드 로딩 확인: http://localhost:3000
- [ ] 데이터베이스 연결 확인: pgAdmin (http://localhost:5050)
**마지막 업데이트**: 2025-08-01 (Docker 환경 구성 완료)