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

9.7 KiB

개발 로그 - 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 대기)
  • 변경 내용:
    // 에러 메시지 추출 개선
    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.jsload-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_oldrole_name 조회
    3. 응답에 role_id, role_name 필드 추가
    4. 하위 호환성을 위해 access_level 필드 유지 (role_name 기반)
  • 변경 내용:
    -- 이전
    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
    
  • 응답 구조 변경:
    {
      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 권한 설정 기능 테스트
  • 모든 페이지 스크립트 로드 확인
  • 헤더 통일 시각적 확인