Files
TK-FB-Project/개발 log/2026-01-19.md
Hyungi Ahn 70630b380a feat: 작업자-계정 통합 및 연차/출근 관리 시스템 구축
모든 작업자가 개인 계정으로 로그인하여 본인의 연차와 출근 기록을 확인할 수 있는 시스템을 구축했습니다.

주요 기능:
- 작업자-계정 1:1 통합 (기존 작업자 자동 계정 생성)
- 연차 관리 시스템 (연도별 잔액 관리)
- 출근 기록 시스템 (일일 근태 기록)
- 나의 대시보드 페이지 (개인 정보 조회)

데이터베이스:
- workers 테이블에 salary, base_annual_leave 컬럼 추가
- work_attendance_types, vacation_types 테이블 생성
- daily_attendance_records 테이블 생성
- worker_vacation_balance 테이블 생성
- 기존 작업자 자동 계정 생성 (username: 이름 기반)
- Guest 역할 추가

백엔드 API:
- 한글→영문 변환 유틸리티 (hangulToRoman.js)
- UserRoutes에 개인 정보 조회 API 추가
  - GET /api/users/me (내 정보)
  - GET /api/users/me/attendance-records (출근 기록)
  - GET /api/users/me/vacation-balance (연차 잔액)
  - GET /api/users/me/work-reports (작업 보고서)
  - GET /api/users/me/monthly-stats (월별 통계)

프론트엔드:
- 나의 대시보드 페이지 (my-dashboard.html)
- 연차 정보 위젯 (총/사용/잔여)
- 월별 출근 캘린더
- 근무 시간 통계
- 최근 작업 보고서 목록
- 네비게이션 바에 "나의 대시보드" 메뉴 추가

배포 시 주의사항:
- 마이그레이션 실행 필요
- 자동 생성된 계정 초기 비밀번호: 1234
- 작업자들에게 첫 로그인 후 비밀번호 변경 안내 필요

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

Co-Authored-By: Claude <noreply@anthropic.com>
2026-01-19 09:49:48 +09:00

260 lines
9.7 KiB
Markdown

# 개발 로그 - 2026-01-19
## 타임라인
### 09:00 - API 에러 파싱 및 Rate Limit 문제 해결
- **작업**: 수정
- **대상**: `web-ui/js/api-config.js`, `web-ui/js/modules/calendar/CalendarAPI.js`
- **문제**:
1. 에러 응답을 파싱할 때 Response body를 두 번 읽으려 해서 `[object Object]` 오류
2. HTTP 429 (Too Many Requests) 오류 발생 - 한 달치 데이터를 동시에 요청
- **원인**:
- `api-config.js`의 에러 처리에서 response.json()과 response.text()를 순차적으로 호출
- CalendarAPI의 fallback 로직이 42개의 일일 데이터를 Promise.all로 동시 요청
- **해결방법**:
1. Content-Type 헤더를 확인하여 JSON/텍스트 구분
2. 에러 객체를 문자열로 제대로 변환 (여러 형식 지원)
3. Fallback 로직을 배치 방식으로 변경 (5개씩, 100ms 대기)
- **변경 내용**:
```javascript
// 에러 메시지 추출 개선
if (errorData.error) {
errorMessage = typeof errorData.error === 'string'
? errorData.error
: JSON.stringify(errorData.error);
}
// Rate limit 방지 배치 처리
const BATCH_SIZE = 5;
const DELAY_BETWEEN_BATCHES = 100;
```
- **파일**:
- `web-ui/js/api-config.js:117-151`
- `web-ui/js/modules/calendar/CalendarAPI.js:91-146`
---
### 09:30 - 불필요한 load-navbar.js 제거 및 컴포넌트 로더 에러 개선
- **작업**: 수정
- **대상**: `web-ui/pages/common/daily-work-report-viewer.html`, `web-ui/js/component-loader.js`
- **문제**:
1. navbar-container가 없는 페이지에서 에러 로그 발생
2. daily-work-report-viewer.html이 자체 헤더를 사용하는데 navbar 로더가 불필요
- **해결방법**:
1. daily-work-report-viewer.html에서 load-navbar.js 제거
2. component-loader.js의 에러를 warning으로 변경
- **파일**:
- `web-ui/pages/common/daily-work-report-viewer.html:339`
- `web-ui/js/component-loader.js:14`
---
### 10:00 - 권한 시스템 단순화 및 페이지 접근 권한 관리 기능 구현
- **작업**: 생성, 수정
- **대상**: 권한 시스템 전체 개편
- **요구사항**:
- Admin 제외 모든 사용자에게 동일한 권한 부여
- Admin이 사용자별로 페이지 접근 권한 설정 가능
- 계정 관리 페이지에서 권한 관리
#### 10:10 - 데이터베이스 마이그레이션 작성
- **작업**: 생성
- **대상**: `api.hyungi.net/db/migrations/20260119000000_simplify_permissions_and_add_page_access.js`
- **변경 내용**:
1. **테이블 생성**:
- `pages`: 페이지 목록 (page_key, page_name, page_path, category, is_admin_only 등)
- `user_page_access`: 사용자별 페이지 접근 권한 (user_id, page_id, can_access, granted_by)
2. **권한 단순화**:
- Leader와 Worker 역할을 User로 통합
- User에게 모든 일반 기능 권한 부여 (Admin 기능 제외)
- Leader 역할 삭제
3. **기본 페이지 등록**:
- Dashboard: user, leader
- Management: worker, project, work, code
- Common: daily-work-report
- Admin: user-management (Admin 전용)
4. **기존 사용자 마이그레이션**:
- Leader → User로 변환
- 모든 일반 사용자에게 일반 페이지 접근 권한 부여
- **파일**: `api.hyungi.net/db/migrations/20260119000000_simplify_permissions_and_add_page_access.js:1-178`
#### 10:30 - 페이지 접근 권한 관리 API 작성
- **작업**: 생성
- **대상**: `api.hyungi.net/routes/pageAccessRoutes.js`
- **구현 엔드포인트**:
1. `GET /api/pages`: 모든 페이지 목록 조회
2. `GET /api/users/:userId/page-access`: 특정 사용자의 페이지 접근 권한 조회
3. `POST /api/users/:userId/page-access`: 페이지 접근 권한 부여/회수
4. `DELETE /api/users/:userId/page-access/:pageId`: 특정 페이지 권한 회수
5. `GET /api/page-access/summary`: 전체 사용자 권한 요약 (Admin용)
- **기능**:
- Admin/System Admin은 모든 페이지 자동 접근 가능
- 일반 사용자는 user_page_access 테이블 기반 권한 체크
- Admin만 권한 설정 가능 (권한 검증)
- **파일**:
- `api.hyungi.net/routes/pageAccessRoutes.js:1-237`
- `api.hyungi.net/config/routes.js:42,129` (라우트 등록)
#### 10:45 - Admin 사용자 관리 페이지에 권한 관리 UI 추가
- **작업**: 수정
- **대상**: `web-ui/pages/admin/manage-user.html`, `web-ui/js/manage-user.js`
- **UI 구현**:
1. **모달 추가**:
- 페이지 접근 권한 관리 모달
- 카테고리별 페이지 목록 (대시보드, 관리, 공통)
- 체크박스로 권한 ON/OFF
2. **사용자 목록에 버튼 추가**:
- "페이지 권한" 버튼 (Admin/System 제외한 사용자만)
- 기존 "삭제" 버튼과 함께 표시
3. **스타일링**:
- 모달 디자인
- 페이지 아이템 레이아웃
- 카테고리별 구분
- **JavaScript 기능**:
1. `openPageAccessModal()`: 사용자 선택 시 권한 조회 및 모달 표시
2. `renderPageAccessList()`: 카테고리별 페이지 목록 렌더링
3. `savePageAccessChanges()`: 체크박스 상태 기반 권한 업데이트
4. `closePageAccessModal()`: 모달 닫기
- **파일**:
- `web-ui/pages/admin/manage-user.html:102-281` (모달 추가)
- `web-ui/js/manage-user.js:225-233,320-512` (권한 관리 로직)
---
### 11:30 - 모든 페이지 스크립트 태그 통일 (type="module" 추가)
- **작업**: 수정
- **대상**: 웹 페이지 HTML 파일들
- **문제**:
- `api-config.js`와 `load-navbar.js`를 모듈로 import하는데 일부 페이지에서 `type="module"` 누락
- "Unexpected token '{'. import call expects one or two arguments" 오류
- **해결방법**:
- 모든 페이지의 api-config.js와 load-navbar.js 스크립트 태그에 `type="module"` 추가
- Task agent로 일괄 수정
- **수정된 파일**:
- `web-ui/pages/analysis/work-analysis-modular.html`
- `web-ui/pages/analysis/work-analysis-legacy.html`
- `web-ui/pages/profile/admin-settings.html`
- 기타 23개 파일 (이미 적용됨)
---
### 11:45 - admin-settings.html 페이지 헤더 중복 제거
- **작업**: 수정
- **대상**: `web-ui/pages/profile/admin-settings.html`
- **문제**:
- work-report-header와 page-header가 중복되어 표시됨
- 뒤로가기 버튼도 중복
- **해결방법**:
- work-report-header 제거
- page-header만 유지하여 일관된 구조 유지
- **파일**: `web-ui/pages/profile/admin-settings.html:13-28`
---
### 12:00 - /api/users 엔드포인트 500 에러 수정
- **작업**: 수정
- **대상**: `api.hyungi.net/routes/authRoutes.js`
- **문제**:
- admin-settings.html 페이지에서 `/api/users` 호출 시 500 Internal Server Error 발생
- 에러 메시지: `{"message":"사용자 목록을 조회하는데 실패했습니다","code":"DATABASE_ERROR"}`
- **원인**:
- 권한 마이그레이션으로 `users` 테이블 구조 변경됨
- `access_level` 필드가 `_access_level_old`로 변경되고 `role_id` 추가됨
- 기존 쿼리가 여전히 `access_level` 필드를 조회하려 시도
- `roles` 테이블과 JOIN 없이 조회
- **해결방법**:
1. `users` 테이블과 `roles` 테이블 LEFT JOIN
2. `access_level` 대신 `_access_level_old`와 `role_name` 조회
3. 응답에 `role_id`, `role_name` 필드 추가
4. 하위 호환성을 위해 `access_level` 필드 유지 (role_name 기반)
- **변경 내용**:
```sql
-- 이전
SELECT user_id, username, name, email, access_level, ...
FROM Users
WHERE 1=1
-- 이후
SELECT
u.user_id, u.username, u.name, u.email,
u.role_id, r.name as role_name,
u._access_level_old as access_level, ...
FROM users u
LEFT JOIN roles r ON u.role_id = r.id
WHERE 1=1
```
- **응답 구조 변경**:
```javascript
{
user_id: number,
username: string,
name: string,
email: string,
role_id: number, // 새로 추가
role_name: string, // 새로 추가
access_level: string, // 하위 호환성 (role_name 기반)
worker_id: number,
is_active: boolean,
last_login_at: datetime,
created_at: datetime
}
```
- **파일**: `api.hyungi.net/routes/authRoutes.js:601-650`
- **영향받는 페이지**:
- admin-settings.html (사용자 목록)
- manage-user.html (사용자 관리)
---
## 요약
### 백엔드 변경
1. **권한 시스템 개편**:
- 마이그레이션: `20260119000000_simplify_permissions_and_add_page_access.js`
- API 라우트: `pageAccessRoutes.js` 신규 생성
- Leader/Worker → User 통합
2. **새 API 엔드포인트** (5개):
- GET /api/pages
- GET /api/users/:userId/page-access
- POST /api/users/:userId/page-access
- DELETE /api/users/:userId/page-access/:pageId
- GET /api/page-access/summary
### 프론트엔드 변경
1. **버그 수정**:
- API 에러 파싱 개선
- Rate limit 방지 (배치 처리)
- 컴포넌트 로더 에러 → warning
2. **페이지 권한 관리 UI** (manage-user.html):
- 모달 기반 권한 관리 인터페이스
- 카테고리별 페이지 목록
- 체크박스로 권한 설정
3. **스크립트 태그 통일**:
- 모든 페이지에 `type="module"` 적용
- import 오류 해결
4. **헤더 통일**:
- admin-settings.html 중복 헤더 제거
- 일관된 page-header 구조
### 데이터베이스 변경
- **신규 테이블** (2개):
- `pages`: 페이지 메타데이터
- `user_page_access`: 사용자별 페이지 접근 권한
- **roles 테이블 변경**:
- Leader 역할 삭제
- Worker → User로 이름 변경 및 권한 확대
### 테스트 필요
- [ ] 마이그레이션 실행 확인
- [ ] 일반 사용자 페이지 접근 권한 확인
- [ ] Admin 권한 설정 기능 테스트
- [ ] 모든 페이지 스크립트 로드 확인
- [ ] 헤더 통일 시각적 확인
---