- 데이터베이스 스키마 및 변경 로그 문서화 - 신규 페이지 개발 가이드 작성 - 모듈 아키텍처 설계 문서 추가 - 성능 최적화 전략 문서화 - 리팩토링 계획 및 진행 상황 정리 Documentation: - DATABASE_SCHEMA.md: 전체 DB 스키마 구조 - DB_CHANGE_LOG.md: 마이그레이션 변경 이력 - DEVELOPMENT_GUIDE.md: 신규 기능 개발 표준 - MODULE_ARCHITECTURE.md: 프론트엔드 모듈 구조 - PERFORMANCE_OPTIMIZATION.md: 성능 최적화 가이드 - REFACTORING_PLAN.md: 리팩토링 진행 상황 Test Files: - app.html, app.js: SPA 테스트 파일 - test_api.html: API 테스트 페이지
329 lines
11 KiB
Markdown
329 lines
11 KiB
Markdown
# M-Project 데이터베이스 스키마 문서
|
|
|
|
## 개요
|
|
작업보고서 시스템의 PostgreSQL 데이터베이스 스키마 정의
|
|
|
|
**최종 업데이트:** 2025-10-25
|
|
**데이터베이스 버전:** PostgreSQL 15
|
|
**스키마 버전:** 1.4 (마이그레이션 009까지 적용)
|
|
|
|
---
|
|
|
|
## 테이블 구조
|
|
|
|
### 1. users (사용자)
|
|
사용자 계정 정보를 저장하는 테이블
|
|
|
|
| 컬럼명 | 타입 | 제약조건 | 설명 |
|
|
|--------|------|----------|------|
|
|
| id | INTEGER | PRIMARY KEY, AUTO_INCREMENT | 사용자 고유 ID |
|
|
| username | VARCHAR(50) | UNIQUE, NOT NULL | 로그인 아이디 |
|
|
| hashed_password | VARCHAR(255) | NOT NULL | 암호화된 비밀번호 (bcrypt) |
|
|
| full_name | VARCHAR(100) | NULL | 사용자 실명 |
|
|
| role | userrole | DEFAULT 'user' | 사용자 권한 |
|
|
| is_active | BOOLEAN | DEFAULT TRUE | 계정 활성화 상태 |
|
|
| created_at | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP | 계정 생성일시 |
|
|
|
|
**인덱스:**
|
|
- `users_pkey` PRIMARY KEY (id)
|
|
- `users_username_key` UNIQUE (username)
|
|
|
|
**참조되는 테이블:**
|
|
- daily_works.created_by_id
|
|
- issues.reporter_id
|
|
- project_daily_works.created_by_id
|
|
- projects.created_by_id
|
|
|
|
---
|
|
|
|
### 2. projects (프로젝트)
|
|
프로젝트 정보를 저장하는 테이블
|
|
|
|
| 컬럼명 | 타입 | 제약조건 | 설명 |
|
|
|--------|------|----------|------|
|
|
| id | BIGINT | PRIMARY KEY, AUTO_INCREMENT | 프로젝트 고유 ID |
|
|
| job_no | VARCHAR(50) | UNIQUE, NOT NULL | Job 번호 |
|
|
| project_name | VARCHAR(200) | NOT NULL | 프로젝트 이름 |
|
|
| created_by_id | INTEGER | FOREIGN KEY → users(id) | 생성자 ID |
|
|
| created_at | TIMESTAMP WITH TIME ZONE | DEFAULT NOW() | 생성일시 |
|
|
| is_active | BOOLEAN | DEFAULT TRUE | 활성 상태 |
|
|
|
|
**인덱스:**
|
|
- `projects_pkey` PRIMARY KEY (id)
|
|
- `projects_job_no_key` UNIQUE (job_no)
|
|
- `idx_projects_job_no` (job_no)
|
|
- `idx_projects_created_by_id` (created_by_id)
|
|
- `idx_projects_is_active` (is_active)
|
|
|
|
**외래키:**
|
|
- `projects_created_by_id_fkey` created_by_id → users(id)
|
|
|
|
**참조되는 테이블:**
|
|
- issues.project_id
|
|
- project_daily_works.project_id
|
|
|
|
---
|
|
|
|
### 3. issues (부적합 사항)
|
|
부적합 사항 정보를 저장하는 테이블
|
|
|
|
| 컬럼명 | 타입 | 제약조건 | 설명 |
|
|
|--------|------|----------|------|
|
|
| id | INTEGER | PRIMARY KEY, AUTO_INCREMENT | 부적합 사항 고유 ID |
|
|
| photo_path | VARCHAR(500) | NULL | 첫 번째 사진 경로 |
|
|
| photo_path2 | VARCHAR(500) | NULL | 두 번째 사진 경로 |
|
|
| category | issuecategory | NOT NULL | 부적합 카테고리 |
|
|
| description | TEXT | NOT NULL | 부적합 사항 설명 |
|
|
| status | issuestatus | DEFAULT 'new' | 처리 상태 |
|
|
| reporter_id | INTEGER | FOREIGN KEY → users(id) | 보고자 ID |
|
|
| report_date | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP | 보고일시 |
|
|
| work_hours | DOUBLE PRECISION | DEFAULT 0 | 작업 시간 |
|
|
| detail_notes | TEXT | NULL | 상세 메모 |
|
|
| project_id | BIGINT | FOREIGN KEY → projects(id) | 프로젝트 ID |
|
|
|
|
**인덱스:**
|
|
- `issues_pkey` PRIMARY KEY (id)
|
|
- `idx_issues_category` (category)
|
|
- `idx_issues_photo_path2` (photo_path2)
|
|
- `idx_issues_project_id` (project_id)
|
|
- `idx_issues_reporter_id` (reporter_id)
|
|
- `idx_issues_status` (status)
|
|
|
|
**외래키:**
|
|
- `fk_issues_project_id` project_id → projects(id)
|
|
- `issues_reporter_id_fkey` reporter_id → users(id)
|
|
|
|
---
|
|
|
|
### 4. daily_works (일일 공수)
|
|
전체 일일 작업 공수 정보를 저장하는 테이블 (레거시)
|
|
|
|
| 컬럼명 | 타입 | 제약조건 | 설명 |
|
|
|--------|------|----------|------|
|
|
| id | INTEGER | PRIMARY KEY, AUTO_INCREMENT | 일일 공수 고유 ID |
|
|
| date | DATE | NOT NULL, UNIQUE | 작업 날짜 |
|
|
| worker_count | INTEGER | NOT NULL | 작업자 수 |
|
|
| regular_hours | DOUBLE PRECISION | NOT NULL | 정규 시간 |
|
|
| overtime_workers | INTEGER | DEFAULT 0 | 야근 작업자 수 |
|
|
| overtime_hours | DOUBLE PRECISION | DEFAULT 0 | 야근 시간 |
|
|
| overtime_total | DOUBLE PRECISION | DEFAULT 0 | 야근 총 시간 |
|
|
| total_hours | DOUBLE PRECISION | NOT NULL | 총 작업 시간 |
|
|
| created_by_id | INTEGER | FOREIGN KEY → users(id) | 생성자 ID |
|
|
| created_at | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP | 생성일시 |
|
|
|
|
**인덱스:**
|
|
- `daily_works_pkey` PRIMARY KEY (id)
|
|
- `daily_works_date_key` UNIQUE (date)
|
|
- `idx_daily_works_date` (date)
|
|
- `idx_daily_works_created_by_id` (created_by_id)
|
|
|
|
**외래키:**
|
|
- `daily_works_created_by_id_fkey` created_by_id → users(id)
|
|
|
|
---
|
|
|
|
### 5. project_daily_works (프로젝트별 일일공수)
|
|
프로젝트별 일일 작업 공수 정보를 저장하는 테이블
|
|
|
|
| 컬럼명 | 타입 | 제약조건 | 설명 |
|
|
|--------|------|----------|------|
|
|
| id | INTEGER | PRIMARY KEY, AUTO_INCREMENT | 프로젝트 일일공수 고유 ID |
|
|
| date | DATE | NOT NULL | 작업 날짜 |
|
|
| project_id | BIGINT | NOT NULL, FOREIGN KEY → projects(id) | 프로젝트 ID |
|
|
| hours | DOUBLE PRECISION | NOT NULL | 작업 시간 |
|
|
| created_by_id | INTEGER | NOT NULL, FOREIGN KEY → users(id) | 생성자 ID |
|
|
| created_at | TIMESTAMP WITH TIME ZONE | DEFAULT CURRENT_TIMESTAMP | 생성일시 |
|
|
|
|
**인덱스:**
|
|
- `project_daily_works_pkey` PRIMARY KEY (id)
|
|
- `idx_project_daily_works_date` (date)
|
|
- `idx_project_daily_works_project_id` (project_id)
|
|
- `idx_project_daily_works_date_project` (date, project_id)
|
|
|
|
**외래키:**
|
|
- `project_daily_works_created_by_id_fkey` created_by_id → users(id)
|
|
- `project_daily_works_project_id_fkey` project_id → projects(id) ON DELETE CASCADE
|
|
|
|
---
|
|
|
|
## ENUM 타입 정의
|
|
|
|
### userrole
|
|
사용자 권한 타입
|
|
- `admin`: 관리자 (모든 권한)
|
|
- `user`: 일반 사용자 (제한된 권한)
|
|
|
|
### issuestatus
|
|
부적합 사항 처리 상태
|
|
- `new`: 신규 (미처리)
|
|
- `progress`: 진행중
|
|
- `complete`: 완료
|
|
|
|
### issuecategory
|
|
부적합 사항 카테고리
|
|
- `material_missing`: 자재누락
|
|
- `design_error`: 설계미스
|
|
- `incoming_defect`: 입고자재 불량
|
|
- `inspection_miss`: 검사미스
|
|
- `etc`: 기타
|
|
|
|
---
|
|
|
|
## 관계도 (Entity Relationship)
|
|
|
|
```
|
|
users (1) ←→ (N) projects
|
|
↓ ↓
|
|
users (1) ←→ (N) issues ←→ (1) projects
|
|
↓ ↓
|
|
users (1) ←→ (N) daily_works
|
|
↓
|
|
users (1) ←→ (N) project_daily_works ←→ (1) projects
|
|
```
|
|
|
|
**주요 관계:**
|
|
1. **users → projects**: 사용자가 프로젝트를 생성
|
|
2. **users → issues**: 사용자가 부적합 사항을 보고
|
|
3. **projects → issues**: 프로젝트에 부적합 사항이 속함
|
|
4. **users → daily_works**: 사용자가 전체 일일공수를 입력 (레거시)
|
|
5. **users → project_daily_works**: 사용자가 프로젝트별 일일공수를 입력
|
|
6. **projects → project_daily_works**: 프로젝트에 일일공수가 속함
|
|
|
|
---
|
|
|
|
## 마이그레이션 히스토리
|
|
|
|
| 파일명 | 설명 | 적용일 |
|
|
|--------|------|--------|
|
|
| `001_init.sql` | 초기 테이블 생성 (users, issues, daily_works) | 초기 |
|
|
| `002_add_second_photo.sql` | issues 테이블에 두 번째 사진 필드 추가 | 초기 |
|
|
| `003_update_categories.sql` | 카테고리 업데이트 (dimension_defect → design_error) | 초기 |
|
|
| `004_fix_category_values.sql` | 카테고리 값 정규화 (대소문자 통일) | 초기 |
|
|
| `005_recreate_enum_type.sql` | issuecategory ENUM 타입 재생성 | 초기 |
|
|
| `006_add_projects_table.sql` | projects 테이블 추가 | 2025-10-25 |
|
|
| `007_add_project_id_to_issues.sql` | issues 테이블에 project_id 컬럼 추가 | 2025-10-25 |
|
|
| `008_fix_project_id_bigint.sql` | project_id를 BIGINT로 변경 | 2025-10-25 |
|
|
| `009_add_project_daily_works_table.sql` | project_daily_works 테이블 추가 | 2025-10-25 |
|
|
| `010_add_etc_category.sql` | issuecategory에 'etc' 값 추가 | 2025-10-25 |
|
|
|
|
---
|
|
|
|
## 데이터베이스 연결 정보
|
|
|
|
### Docker 환경
|
|
- **Host:** db (컨테이너 내부), localhost (외부)
|
|
- **Port:** 5432 (내부), 16432 (외부)
|
|
- **Database:** mproject
|
|
- **Username:** mproject
|
|
- **Password:** mproject2024
|
|
- **Timezone:** Asia/Seoul
|
|
|
|
### 환경변수
|
|
```bash
|
|
DATABASE_URL=postgresql://mproject:mproject2024@db:5432/mproject
|
|
POSTGRES_USER=mproject
|
|
POSTGRES_PASSWORD=mproject2024
|
|
POSTGRES_DB=mproject
|
|
TZ=Asia/Seoul
|
|
PGTZ=Asia/Seoul
|
|
```
|
|
|
|
---
|
|
|
|
## 기본 데이터
|
|
|
|
### 관리자 계정
|
|
- **Username:** hyungi
|
|
- **Password:** 123456
|
|
- **Role:** admin
|
|
- **Full Name:** 관리자
|
|
|
|
---
|
|
|
|
## 데이터베이스 관리
|
|
|
|
### 백업
|
|
```bash
|
|
# 전체 백업
|
|
docker exec m-project-db pg_dump -U mproject mproject > backup_$(date +%Y%m%d_%H%M%S).sql
|
|
|
|
# 스키마만 백업
|
|
docker exec m-project-db pg_dump -U mproject -s mproject > schema_backup.sql
|
|
|
|
# 데이터만 백업
|
|
docker exec m-project-db pg_dump -U mproject -a mproject > data_backup.sql
|
|
```
|
|
|
|
### 복구
|
|
```bash
|
|
# 전체 복구
|
|
docker exec -i m-project-db psql -U mproject mproject < backup.sql
|
|
|
|
# 스키마 복구
|
|
docker exec -i m-project-db psql -U mproject mproject < schema_backup.sql
|
|
```
|
|
|
|
### 테이블 상태 확인
|
|
```bash
|
|
# 모든 테이블 목록
|
|
docker exec m-project-db psql -U mproject -d mproject -c "\dt"
|
|
|
|
# 특정 테이블 구조
|
|
docker exec m-project-db psql -U mproject -d mproject -c "\d table_name"
|
|
|
|
# ENUM 타입 확인
|
|
docker exec m-project-db psql -U mproject -d mproject -c "\dT+"
|
|
|
|
# 인덱스 확인
|
|
docker exec m-project-db psql -U mproject -d mproject -c "\di"
|
|
```
|
|
|
|
---
|
|
|
|
## 성능 최적화
|
|
|
|
### 인덱스 전략
|
|
1. **Primary Keys**: 모든 테이블에 자동 생성
|
|
2. **Foreign Keys**: 모든 외래키에 인덱스 생성
|
|
3. **검색 필드**: 자주 검색되는 컬럼 (date, status, category 등)
|
|
4. **복합 인덱스**: 날짜+프로젝트 조합 검색 최적화
|
|
|
|
### 쿼리 최적화 권장사항
|
|
1. **날짜 범위 검색**: date 컬럼 인덱스 활용
|
|
2. **프로젝트별 필터링**: project_id 인덱스 활용
|
|
3. **상태별 필터링**: status, is_active 인덱스 활용
|
|
4. **JOIN 최적화**: 외래키 인덱스 활용
|
|
|
|
---
|
|
|
|
## 보안 고려사항
|
|
|
|
1. **비밀번호 암호화**: bcrypt 해시 사용 (최소 12 rounds)
|
|
2. **SQL 인젝션 방지**: 파라미터화된 쿼리 사용
|
|
3. **접근 제어**: 역할 기반 권한 관리
|
|
4. **데이터 검증**: 애플리케이션 레벨에서 입력값 검증
|
|
5. **백업 암호화**: 민감한 데이터 백업 시 암호화 권장
|
|
|
|
---
|
|
|
|
## 향후 확장 계획
|
|
|
|
### 예정된 변경사항
|
|
- [ ] 부적합 사항에 우선순위 필드 추가
|
|
- [ ] 프로젝트 상태 관리 (진행중, 완료, 보류 등)
|
|
- [ ] 파일 첨부 기능 확장 (문서, 도면 등)
|
|
- [ ] 알림 시스템을 위한 notifications 테이블
|
|
- [ ] 감사 로그를 위한 audit_logs 테이블
|
|
|
|
### 성능 개선 계획
|
|
- [ ] 파티셔닝: 대용량 데이터 처리를 위한 날짜별 파티셔닝
|
|
- [ ] 아카이빙: 오래된 데이터 아카이브 전략
|
|
- [ ] 캐싱: Redis를 활용한 자주 조회되는 데이터 캐싱
|
|
|
|
---
|
|
|
|
**문서 작성자:** AI Assistant
|
|
**검토자:** -
|
|
**승인자:** -
|
|
|
|
> 이 문서는 데이터베이스 스키마 변경 시마다 업데이트되어야 합니다. |