Cursor 도입 확인 및 개선 사항 정리(REVIEW.md, IMPROVEMNETS.md)

This commit is contained in:
Hyungi Ahn
2025-07-16 07:09:15 +09:00
parent fc61e44fd6
commit 5ac9d562d5
10 changed files with 4225 additions and 0 deletions

28
IMPROVEMENTS.md Normal file
View File

@@ -0,0 +1,28 @@
# TK-MP-Project Backend 개선/확장/운영 권장사항
## 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 등 주요 엔티티의 논리적 삭제/수정 지원
---
*2024-07-15 기준, backend 코드 리뷰 기반 개선/확장/운영 권장사항 정리*

33
REVIEW.md Normal file
View File

@@ -0,0 +1,33 @@
# TK-MP-Project Backend 코드 리뷰 요약
## 1. 전체 구조
- FastAPI + SQLAlchemy 기반 백엔드
- models, schemas, routers, services, api, uploads 등 역할별 디렉토리 분리
- 자재/BOM/스풀/계장 등 플랜트/조선/기계 실무에 특화된 구조
## 2. 주요 코드 검토
- **main.py**: 앱 진입점, CORS, 라우터 등록, 헬스체크 등
- **routers/**: 파일, 작업(Job) 등 API 엔드포인트 구현
- **services/**: 품목별 분류기(볼트, 밸브, 플랜지, 피팅, 가스켓, 파이프, 계장 등), 스풀 관리, 테스트 코드
- **material_classifier.py**: 재질 분류 공통 모듈, 규격/패턴/키워드 기반 robust 분류
- **spool_manager.py/v2**: 도면-에어리어-스풀 넘버링, 유효성 검증, 자동 추천 등
- **api/**: 과거 버전/백업/보조 코드(실제 서비스는 routers/가 메인)
- **테스트 코드**: 다양한 실무 케이스를 print 기반으로 커버(자동화는 미흡)
- **materials_schema.py**: 분류기에서 사용하는 규격/패턴/키워드/등급 등 데이터 정의
## 3. 품목별 분류기 구조
- 볼트/밸브/플랜지/피팅/가스켓/파이프/계장 등 각 품목별로 dict 기반 패턴/키워드/규격 관리
- material_classifier와 연동, 신뢰도/구매정보 등 실무적 정보 제공
- 구조/로직은 유사하나, 각 품목별 실무 특성에 맞는 분류 포인트 반영
## 4. 테스트 코드
- 다양한 실무 케이스를 print 기반으로 커버
- 자동화(assert) 기반 테스트는 미흡(추후 개선 필요)
## 5. materials_schema.py
- 분류기에서 사용하는 규격/패턴/키워드/등급 등 실무적 데이터가 체계적으로 구조화
- 신규 규격/등급/패턴 추가/수정이 용이
---
*2024-07-15 기준, 전체 backend 코드 리뷰 및 구조 요약*

24
frontend/.gitignore vendored Normal file
View File

@@ -0,0 +1,24 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
node_modules
dist
dist-ssr
*.local
# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?

106
frontend/README.md Normal file
View File

@@ -0,0 +1,106 @@
# TK-MP BOM 관리 시스템 - 프론트엔드
React + Material-UI 기반의 BOM(Bill of Materials) 관리 시스템 프론트엔드입니다.
## 🚀 기능
- **대시보드**: 프로젝트 현황 및 통계 확인
- **프로젝트 관리**: 프로젝트 생성, 수정, 삭제
- **파일 업로드**: 드래그&드롭으로 Excel 파일 업로드
- **자재 목록**: 검색, 필터링, 정렬이 가능한 자재 테이블
## 🛠️ 기술 스택
- **React 18** - 컴포넌트 기반 UI 라이브러리
- **Material-UI (MUI)** - 현대적인 UI 컴포넌트
- **Vite** - 빠른 개발 서버 및 빌드 도구
- **React Dropzone** - 드래그&드롭 파일 업로드
- **MUI DataGrid** - 고성능 데이터 테이블
## 📦 설치 및 실행
```bash
# 의존성 설치
npm install
# 개발 서버 실행 (http://localhost:3000)
npm run dev
# 프로덕션 빌드
npm run build
# 빌드 미리보기
npm run preview
```
## 🔗 백엔드 연동
백엔드 서버가 `http://localhost:8000`에서 실행되고 있어야 합니다.
```bash
# 백엔드 서버 실행 (별도 터미널)
cd ../backend
source venv/bin/activate
uvicorn app.main:app --reload
```
## 📁 프로젝트 구조
```
frontend/
├── src/
│ ├── components/
│ │ ├── Dashboard.jsx # 대시보드
│ │ ├── FileUpload.jsx # 파일 업로드
│ │ ├── MaterialList.jsx # 자재 목록
│ │ └── ProjectManager.jsx # 프로젝트 관리
│ ├── App.jsx # 메인 앱
│ ├── main.jsx # 엔트리 포인트
│ └── index.css # 전역 스타일
├── package.json
└── vite.config.js
```
## 🎯 주요 컴포넌트
### Dashboard
- 프로젝트 통계 및 현황 표시
- 최근 활동 목록
- 실시간 데이터 업데이트
### FileUpload
- 드래그&드롭 인터페이스
- Excel 파일 검증
- 업로드 진행률 표시
- 배치 파일 처리
### MaterialList
- 페이지네이션이 있는 데이터 그리드
- 실시간 검색 및 필터링
- CSV 내보내기
- 정렬 및 컬럼 관리
### ProjectManager
- 프로젝트 CRUD 작업
- 카드 형태의 프로젝트 표시
- 모달 기반 편집
## 📱 반응형 디자인
- 모바일, 태블릿, 데스크톱 지원
- Material-UI의 Grid 시스템 활용
- 적응형 네비게이션
## 🔧 개발 도구
- **ESLint** - 코드 품질 검사
- **Vite HMR** - 빠른 핫 리로드
- **React DevTools** - 디버깅 지원
## 🚀 성능 최적화
- 컴포넌트 지연 로딩
- 메모이제이션 적용
- 번들 크기 최적화
- API 요청 최적화

29
frontend/eslint.config.js Normal file
View File

@@ -0,0 +1,29 @@
import js from '@eslint/js'
import globals from 'globals'
import reactHooks from 'eslint-plugin-react-hooks'
import reactRefresh from 'eslint-plugin-react-refresh'
import { defineConfig, globalIgnores } from 'eslint/config'
export default defineConfig([
globalIgnores(['dist']),
{
files: ['**/*.{js,jsx}'],
extends: [
js.configs.recommended,
reactHooks.configs['recommended-latest'],
reactRefresh.configs.vite,
],
languageOptions: {
ecmaVersion: 2020,
globals: globals.browser,
parserOptions: {
ecmaVersion: 'latest',
ecmaFeatures: { jsx: true },
sourceType: 'module',
},
},
rules: {
'no-unused-vars': ['error', { varsIgnorePattern: '^[A-Z_]' }],
},
},
])

13
frontend/index.html Normal file
View File

@@ -0,0 +1,13 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite + React</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.jsx"></script>
</body>
</html>

3940
frontend/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

1
frontend/public/vite.svg Normal file
View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

35
frontend/run.sh Executable file
View File

@@ -0,0 +1,35 @@
#!/bin/bash
echo "🚀 TK-MP 프론트엔드 시작 스크립트"
echo "=================================="
# 현재 디렉토리 확인
if [ ! -f "package.json" ]; then
echo "❌ package.json이 없습니다. frontend 폴더로 이동해주세요."
exit 1
fi
# 의존성 설치 확인
if [ ! -d "node_modules" ]; then
echo "📦 의존성을 설치합니다..."
npm install
fi
# 백엔드 서버 확인
echo "🔗 백엔드 서버 연결 테스트..."
curl -s http://localhost:8000/api/projects > /dev/null
if [ $? -eq 0 ]; then
echo "✅ 백엔드 서버가 실행 중입니다."
else
echo "⚠️ 백엔드 서버가 실행되지 않았습니다."
echo " 다른 터미널에서 다음 명령어를 실행해주세요:"
echo " cd ../backend && source venv/bin/activate && uvicorn app.main:app --reload"
fi
echo ""
echo "🌐 프론트엔드 서버를 시작합니다..."
echo " 브라우저에서 http://localhost:3000 이 자동으로 열립니다."
echo ""
# 개발 서버 실행
npm run dev

16
frontend/vite.config.js Normal file
View File

@@ -0,0 +1,16 @@
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [react()],
server: {
port: 3000,
host: true,
open: true
},
build: {
outDir: 'dist',
sourcemap: true
}
})