Files
M-Project/DATABASE_SCHEMA.md
Hyungi Ahn d3333c4dc2 docs: 프로젝트 문서화 및 개발 가이드 추가
- 데이터베이스 스키마 및 변경 로그 문서화
- 신규 페이지 개발 가이드 작성
- 모듈 아키텍처 설계 문서 추가
- 성능 최적화 전략 문서화
- 리팩토링 계획 및 진행 상황 정리

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 테스트 페이지
2025-10-25 09:01:54 +09:00

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
**검토자:** -
**승인자:** -
> 이 문서는 데이터베이스 스키마 변경 시마다 업데이트되어야 합니다.