Files
TK-FB-Project/docs/TBM_DEPLOYMENT_GUIDE.md
Hyungi Ahn 4d0c4c0801 feat: TBM 시스템 구축 및 페이지 권한 관리 기능 추가
## 주요 변경사항

### 1. TBM (Tool Box Meeting) 시스템 구축
- **데이터베이스 스키마** (5개 테이블 생성)
  - tbm_sessions: TBM 세션 관리
  - tbm_team_assignments: 팀 구성 관리
  - tbm_safety_checks: 안전 체크리스트 마스터 (17개 항목)
  - tbm_safety_records: 안전 체크 기록
  - team_handovers: 작업 인계 관리

- **API 엔드포인트** (17개)
  - TBM 세션 CRUD
  - 팀 구성 관리
  - 안전 체크리스트
  - 작업 인계
  - 통계 및 리포트

- **프론트엔드**
  - TBM 관리 페이지 (/pages/work/tbm.html)
  - 모달 기반 UI (세션 생성, 팀 구성, 안전 체크)

### 2. 페이지 권한 관리 시스템
- 페이지별 접근 권한 설정 기능
- 관리자 페이지 (/pages/admin/page-access.html)
- 사용자별 페이지 권한 부여/회수
- TBM 페이지 등록 및 권한 연동

### 3. 네비게이션 role 표시 버그 수정
- load-navbar.js: case-insensitive role 매칭 적용
- JWT의 "Admin" role이 "관리자"로 정상 표시
- admin-only 메뉴 항목 정상 표시

### 4. 대시보드 개선
- 작업 현황 테이블 가독성 향상
- 고대비 색상 및 명확한 구분선 적용
- 이모지 제거 및 SVG 아이콘 적용

### 5. 문서화
- TBM 배포 가이드 작성 (docs/TBM_DEPLOYMENT_GUIDE.md)
- 데이터베이스 스키마 상세 기록
- 배포 절차 및 체크리스트 제공

## 기술 스택
- Backend: Node.js, Express, MySQL
- Frontend: Vanilla JavaScript, HTML5, CSS3
- Database: MySQL (InnoDB)

## 파일 변경사항

### 신규 파일
- api.hyungi.net/db/migrations/20260120000000_create_tbm_system.js
- api.hyungi.net/db/migrations/20260120000001_add_tbm_page.js
- api.hyungi.net/models/tbmModel.js
- api.hyungi.net/models/pageAccessModel.js
- api.hyungi.net/controllers/tbmController.js
- api.hyungi.net/controllers/pageAccessController.js
- api.hyungi.net/routes/tbmRoutes.js
- web-ui/pages/work/tbm.html
- web-ui/pages/admin/page-access.html
- web-ui/js/page-access-management.js
- docs/TBM_DEPLOYMENT_GUIDE.md

### 수정 파일
- api.hyungi.net/config/routes.js (TBM 라우트 추가)
- web-ui/js/load-navbar.js (role 매칭 버그 수정)
- web-ui/pages/admin/workers.html (HTML 구조 수정)
- web-ui/pages/dashboard.html (이모지 제거)
- web-ui/css/design-system.css (색상 팔레트 추가)
- web-ui/css/modern-dashboard.css (가독성 개선)
- web-ui/js/modern-dashboard.js (SVG 아이콘 적용)

## 배포 시 주의사항
⚠️ 본 서버 배포 시 반드시 마이그레이션 실행 필요:
```bash
npm run db:migrate
```

상세한 배포 절차는 docs/TBM_DEPLOYMENT_GUIDE.md 참조

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-01-20 15:38:17 +09:00

13 KiB

TBM 시스템 배포 가이드

📋 개요

TBM (Tool Box Meeting) 시스템은 아침 안전 회의 및 팀 구성 관리를 위한 기능입니다.

배포일: 2026-01-20 버전: 1.0.0


🗄️ 데이터베이스 마이그레이션

필수 마이그레이션 파일

본 서버에 배포 시 반드시 실행해야 할 마이그레이션:

  1. 20260120000000_create_tbm_system.js - TBM 시스템 테이블 생성
  2. 20260120000001_add_tbm_page.js - TBM 페이지 등록

생성되는 테이블

1. tbm_sessions - TBM 세션 (아침 미팅)

CREATE TABLE `tbm_sessions` (
  `session_id` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
  `session_date` DATE NOT NULL COMMENT 'TBM 날짜',
  `leader_id` INT NOT NULL COMMENT '팀장 worker_id',
  `project_id` INT NULL COMMENT '프로젝트 ID',
  `work_location` VARCHAR(200) NULL COMMENT '작업 장소',
  `work_description` TEXT NULL COMMENT '작업 내용',
  `safety_notes` TEXT NULL COMMENT '안전 관련 특이사항',
  `status` ENUM('draft', 'completed', 'cancelled') DEFAULT 'draft' COMMENT '상태',
  `start_time` TIME NULL COMMENT 'TBM 시작 시간',
  `end_time` TIME NULL COMMENT 'TBM 종료 시간',
  `created_by` INT NOT NULL COMMENT '생성자 user_id',
  `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  `updated_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  INDEX `idx_session_date_leader` (`session_date`, `leader_id`),
  FOREIGN KEY (`leader_id`) REFERENCES `workers` (`worker_id`),
  FOREIGN KEY (`project_id`) REFERENCES `projects` (`project_id`) ON DELETE SET NULL,
  FOREIGN KEY (`created_by`) REFERENCES `users` (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

2. tbm_team_assignments - TBM 팀 구성

CREATE TABLE `tbm_team_assignments` (
  `assignment_id` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
  `session_id` INT UNSIGNED NOT NULL COMMENT 'TBM 세션 ID',
  `worker_id` INT NOT NULL COMMENT '팀원 worker_id',
  `assigned_role` VARCHAR(100) NULL COMMENT '역할/담당',
  `work_detail` TEXT NULL COMMENT '세부 작업 내용',
  `is_present` BOOLEAN DEFAULT TRUE COMMENT '출석 여부',
  `absence_reason` TEXT NULL COMMENT '결석 사유',
  `assigned_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  UNIQUE KEY `uk_session_worker` (`session_id`, `worker_id`),
  FOREIGN KEY (`session_id`) REFERENCES `tbm_sessions` (`session_id`) ON DELETE CASCADE,
  FOREIGN KEY (`worker_id`) REFERENCES `workers` (`worker_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

3. tbm_safety_checks - 안전 체크리스트 마스터

CREATE TABLE `tbm_safety_checks` (
  `check_id` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
  `check_category` VARCHAR(50) NOT NULL COMMENT '카테고리 (PPE, EQUIPMENT, ENVIRONMENT, EMERGENCY)',
  `check_item` VARCHAR(200) NOT NULL COMMENT '체크 항목',
  `description` TEXT NULL COMMENT '설명',
  `display_order` INT DEFAULT 0 COMMENT '표시 순서',
  `is_required` BOOLEAN DEFAULT TRUE COMMENT '필수 체크 여부',
  `is_active` BOOLEAN DEFAULT TRUE COMMENT '활성 여부',
  `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  `updated_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  INDEX `idx_check_category` (`check_category`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

초기 데이터 (17개 항목):

  • PPE (개인 보호 장비): 5개
  • EQUIPMENT (장비 점검): 4개
  • ENVIRONMENT (작업 환경): 4개
  • EMERGENCY (비상 대응): 3개

4. tbm_safety_records - 안전 체크 기록

CREATE TABLE `tbm_safety_records` (
  `record_id` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
  `session_id` INT UNSIGNED NOT NULL COMMENT 'TBM 세션 ID',
  `check_id` INT UNSIGNED NOT NULL COMMENT '체크 항목 ID',
  `is_checked` BOOLEAN DEFAULT FALSE COMMENT '체크 여부',
  `notes` TEXT NULL COMMENT '비고/특이사항',
  `checked_by` INT NULL COMMENT '체크한 user_id',
  `checked_at` TIMESTAMP NULL COMMENT '체크 시간',
  UNIQUE KEY `uk_session_check` (`session_id`, `check_id`),
  FOREIGN KEY (`session_id`) REFERENCES `tbm_sessions` (`session_id`) ON DELETE CASCADE,
  FOREIGN KEY (`check_id`) REFERENCES `tbm_safety_checks` (`check_id`),
  FOREIGN KEY (`checked_by`) REFERENCES `users` (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

5. team_handovers - 작업 인계

CREATE TABLE `team_handovers` (
  `handover_id` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
  `session_id` INT UNSIGNED NOT NULL COMMENT 'TBM 세션 ID',
  `from_leader_id` INT NOT NULL COMMENT '인계자 worker_id',
  `to_leader_id` INT NOT NULL COMMENT '인수자 worker_id',
  `handover_date` DATE NOT NULL COMMENT '인계 날짜',
  `handover_time` TIME NULL COMMENT '인계 시간',
  `reason` ENUM('half_day', 'early_leave', 'emergency', 'other') NOT NULL COMMENT '인계 사유',
  `handover_notes` TEXT NULL COMMENT '인계 내용',
  `worker_ids` TEXT NULL COMMENT '인계하는 작업자 IDs (JSON array)',
  `is_confirmed` BOOLEAN DEFAULT FALSE COMMENT '인수 확인 여부',
  `confirmed_at` TIMESTAMP NULL COMMENT '인수 확인 시간',
  `confirmed_by` INT NULL COMMENT '인수 확인자 user_id',
  `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  INDEX `idx_session_handover_date` (`session_id`, `handover_date`),
  FOREIGN KEY (`session_id`) REFERENCES `tbm_sessions` (`session_id`) ON DELETE CASCADE,
  FOREIGN KEY (`from_leader_id`) REFERENCES `workers` (`worker_id`),
  FOREIGN KEY (`to_leader_id`) REFERENCES `workers` (`worker_id`),
  FOREIGN KEY (`confirmed_by`) REFERENCES `users` (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

🚀 배포 절차

1. 데이터베이스 마이그레이션 실행

# 본 서버에서 실행
cd /path/to/api.hyungi.net

# 환경 변수 설정 (필요 시)
export DB_HOST=your_db_host
export DB_PORT=your_db_port
export DB_USER=your_db_user
export DB_PASSWORD=your_db_password
export DB_NAME=hyungi

# 마이그레이션 실행
npm run db:migrate

# 또는 직접 실행
npx knex migrate:latest --knexfile knexfile.js

2. 마이그레이션 확인

# 마이그레이션 상태 확인
npx knex migrate:status --knexfile knexfile.js

# 테이블 생성 확인
mysql -u root -p -e "SHOW TABLES LIKE 'tbm%'" hyungi
mysql -u root -p -e "SHOW TABLES LIKE 'team_handovers'" hyungi

# 안전 체크리스트 초기 데이터 확인
mysql -u root -p -e "SELECT check_category, COUNT(*) as count FROM tbm_safety_checks GROUP BY check_category" hyungi

예상 결과:

+----------------+-------+
| check_category | count |
+----------------+-------+
| PPE            |     5 |
| EQUIPMENT      |     4 |
| ENVIRONMENT    |     4 |
| EMERGENCY      |     3 |
+----------------+-------+

3. API 서버 재시작

# PM2 사용 시
pm2 restart api-hyungi

# 또는 직접 재시작
pm2 stop api-hyungi
pm2 start ecosystem.config.js --env production

4. 페이지 권한 확인

# TBM 페이지가 pages 테이블에 등록되었는지 확인
mysql -u root -p -e "SELECT * FROM pages WHERE page_key='tbm'\G" hyungi

예상 결과:

        page_id: [auto_increment]
       page_key: tbm
      page_name: TBM 관리
      page_path: /pages/work/tbm.html
       category: work
    description: Tool Box Meeting - 아침 안전 회의 및 팀 구성 관리
  is_admin_only: 0
  display_order: 10

📡 API 엔드포인트

TBM 세션 관리

  • POST /api/tbm/sessions - TBM 세션 생성
  • GET /api/tbm/sessions/date/:date - 특정 날짜의 TBM 세션 목록
  • GET /api/tbm/sessions/:sessionId - TBM 세션 상세 조회
  • PUT /api/tbm/sessions/:sessionId - TBM 세션 수정
  • POST /api/tbm/sessions/:sessionId/complete - TBM 세션 완료

팀 구성 관리

  • POST /api/tbm/sessions/:sessionId/team - 팀원 추가 (단일)
  • POST /api/tbm/sessions/:sessionId/team/batch - 팀원 일괄 추가
  • GET /api/tbm/sessions/:sessionId/team - 팀 구성 조회
  • DELETE /api/tbm/sessions/:sessionId/team/:workerId - 팀원 제거

안전 체크리스트

  • GET /api/tbm/safety-checks - 모든 안전 체크 항목 조회
  • GET /api/tbm/sessions/:sessionId/safety - 안전 체크 기록 조회
  • POST /api/tbm/sessions/:sessionId/safety - 안전 체크 일괄 저장

작업 인계

  • POST /api/tbm/handovers - 작업 인계 생성
  • POST /api/tbm/handovers/:handoverId/confirm - 작업 인계 확인
  • GET /api/tbm/handovers/date/:date - 특정 날짜의 인계 목록
  • GET /api/tbm/handovers/pending - 나에게 온 미확인 인계 건

통계 및 리포트

  • GET /api/tbm/statistics/tbm?startDate=&endDate= - TBM 통계
  • GET /api/tbm/statistics/leaders?startDate=&endDate= - 리더별 통계

🔐 권한 설정

1. 관리자가 페이지 권한 설정

  1. 관리자 계정으로 로그인
  2. /pages/admin/page-access.html 접속
  3. 권한을 부여할 사용자 선택
  4. "TBM 관리" 페이지 체크
  5. 저장

2. 기본 권한 (권장)

  • 그룹장 (Leader): TBM 페이지 접근 권한 부여 필요
  • 관리자 (Admin): 자동으로 모든 페이지 접근 가능
  • 일반 작업자 (User): 필요에 따라 부여

📁 파일 구조

백엔드 (API)

api.hyungi.net/
├── db/migrations/
│   ├── 20260120000000_create_tbm_system.js      # TBM 테이블 생성
│   └── 20260120000001_add_tbm_page.js           # TBM 페이지 등록
├── models/
│   └── tbmModel.js                               # TBM 데이터 모델
├── controllers/
│   └── tbmController.js                          # TBM 컨트롤러
├── routes/
│   └── tbmRoutes.js                              # TBM 라우트
└── config/
    └── routes.js                                 # 라우트 등록 (수정됨)

프론트엔드 (Web UI)

web-ui/
├── pages/work/
│   └── tbm.html                                  # TBM 페이지
└── js/
    └── tbm.js                                    # TBM JavaScript (예정)

⚠️ 주의사항

1. 외래 키 제약 조건

  • workers 테이블의 worker_idsigned INT(11)
  • users 테이블의 user_idsigned INT(11)
  • projects 테이블의 PK는 project_id (NOT id)
  • 외래 키 컬럼은 반드시 signed INT로 선언 (unsigned 사용 금지)

2. 데이터 정합성

  • TBM 세션 삭제 시 관련 팀 구성, 안전 체크 기록 자동 삭제 (CASCADE)
  • 작업자 삭제 시 관련 TBM 세션도 삭제됨 (workers 테이블의 CASCADE 설정)

3. 백업

마이그레이션 실행 전 반드시 데이터베이스 백업:

mysqldump -u root -p hyungi > backup_before_tbm_$(date +%Y%m%d_%H%M%S).sql

4. 롤백

문제 발생 시 롤백:

# 한 단계 롤백
npx knex migrate:rollback --knexfile knexfile.js

# 또는 백업 복구
mysql -u root -p hyungi < backup_before_tbm_YYYYMMDD_HHMMSS.sql

배포 체크리스트

배포 전 확인:

  • 데이터베이스 백업 완료
  • 마이그레이션 파일 본 서버에 복사 완료
  • 환경 변수 설정 확인 (DB 접속 정보)
  • 마이그레이션 실행 완료
  • 5개 테이블 생성 확인
  • tbm_safety_checks 초기 데이터 (17개) 확인
  • pages 테이블에 TBM 페이지 등록 확인
  • API 서버 재시작 완료
  • API 엔드포인트 테스트 (최소 1개)
  • TBM 페이지 접속 테스트
  • 권한 설정 테스트 (그룹장 계정)

🔍 테스트 방법

1. API 테스트

# 안전 체크 항목 조회
curl -X GET http://localhost:20005/api/tbm/safety-checks \
  -H "Authorization: Bearer YOUR_TOKEN"

# 오늘 날짜의 TBM 세션 조회
curl -X GET http://localhost:20005/api/tbm/sessions/date/2026-01-20 \
  -H "Authorization: Bearer YOUR_TOKEN"

2. 웹 페이지 테스트

  1. 그룹장 계정으로 로그인
  2. /pages/work/tbm.html 접속
  3. "새 TBM 시작" 버튼 클릭
  4. TBM 세션 생성 및 팀 구성

📞 문제 해결

문제 1: 마이그레이션 실패 (errno: 150)

원인: 외래 키 제약 조건 오류 (데이터 타입 불일치) 해결: 마이그레이션 파일에서 외래 키 컬럼을 signed INT로 수정

문제 2: API 엔드포인트 404

원인: 라우트 등록 누락 또는 서버 미재시작 해결:

pm2 logs api-hyungi --lines 50  # 로그 확인
pm2 restart api-hyungi          # 서버 재시작

문제 3: TBM 페이지 접근 불가

원인: 페이지 권한 미설정 해결: 관리자가 /pages/admin/page-access.html에서 권한 부여


📝 변경 이력

v1.0.0 (2026-01-20)

  • TBM 시스템 초기 배포
  • 5개 테이블 생성
  • 17개 안전 체크리스트 항목
  • API 엔드포인트 17개
  • 페이지 권한 시스템 연동

📚 관련 문서


작성자: Claude 최종 수정일: 2026-01-20