- 개발팀 전용 폴더 dev/ 생성 (standards, guides, quickstart, changes, deploys, data, history, dev_plans 이동) - 프론트엔드 전용 폴더 frontend/ 생성 (api/ → frontend/api-specs/) - 기획팀 폴더 requests/ 생성 - plans/ → dev/dev_plans/ 이름 변경 - README.md 신규 (사람용 안내), INDEX.md 재작성 (Claude Code용) - resources.md 신규 (노션 링크용, assets/brochure 이관 예정) - CURRENT_WORKS.md 삭제, TODO.md → dev/ 이동 - 전체 참조 경로 업데이트 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
23 KiB
23 KiB
휴가관리 모듈 개발 계획서
작성일: 2026-02-26 상태: 설계 중
1. 개요
1.1 목적
근태현황에 포함된 휴가/연차 기능을 독립된 휴가관리 모듈로 분리한다. 근로기준법 기반 연차 자동 계산, 휴가 신청/승인, 잔여 연차 관리를 체계적으로 지원한다.
1.2 핵심 원칙
- 근태현황의
vacation상태는 결과 기록으로만 유지 (휴가 승인 완료 시 자동 기록) - 휴가 신청/승인/잔여일수 관리는 모두 휴가관리 모듈에서 수행
- 기존 API 테이블/모델(
leaves,leave_balances,leave_policies,leave_grants)을 최대한 활용 - MNG에서 관리자 인터페이스(Blade + HTMX) 구현
1.3 현재 상태 분석
| 항목 | API (DB/모델) | MNG (UI/서비스) | 비고 |
|---|---|---|---|
leaves 테이블 |
✅ 마이그레이션 완료 | ❌ 미구현 | 핵심 테이블 |
leave_balances 테이블 |
✅ 마이그레이션 완료 | ⚠️ 단순 모델만 | 연차 잔액 |
leave_policies 테이블 |
✅ 마이그레이션 완료 | ❌ 미구현 | 연차 정책 설정 |
leave_grants 테이블 |
✅ 마이그레이션 완료 | ❌ 미구현 | 연차 부여 이력 |
attendance_requests 테이블 |
✅ 마이그레이션 완료 | ✅ 신청/승인 구현 | 근태현황에 포함 |
| 연차 자동 차감 | — | ⚠️ 단순 구현 | 복원 로직 없음 |
1.4 근태현황과의 역할 분리
| 기능 | 근태현황 (유지) | 휴가관리 (신규) |
|---|---|---|
| 출퇴근 기록 | ✅ | — |
| 출장/재택/외근 신청·승인 | ✅ | — |
vacation 상태 표시 |
✅ (결과만) | — |
| 연차 부여/발생 규칙 | — | ✅ |
| 휴가 신청·승인 워크플로우 | — | ✅ |
| 잔여 연차 관리 | — | ✅ |
| 연차 촉진 알림 | — | ✅ (Phase 3) |
2. 기존 DB 스키마
API에 이미 마이그레이션 완료된 테이블들. MNG에서 모델만 생성하여 활용한다.
2.1 leaves 테이블
┌──────────────────────────────────────────────────────────┐
│ leaves │
├────────────────┬─────────────┬────────────────────────────┤
│ id │ bigint PK │ Auto Increment │
│ tenant_id │ bigint FK │ → tenants.id │
│ user_id │ bigint FK │ → users.id │
│ leave_type │ enum │ annual, half_am, half_pm, │
│ │ │ sick, family, maternity, │
│ │ │ parental │
│ start_date │ date │ 시작일 │
│ end_date │ date │ 종료일 │
│ days │ decimal(3,1)│ 사용일수 (0.5 = 반차) │
│ reason │ text │ 사유 │
│ status │ enum │ pending, approved, rejected, │
│ │ │ cancelled │
│ approved_by │ bigint │ 승인자 ID │
│ approved_at │ datetime │ 승인 일시 │
│ reject_reason │ text │ 반려 사유 │
│ created_by/ │ bigint │ 감사 필드 │
│ updated_by/ │ │ │
│ deleted_by │ │ │
│ timestamps │ │ │
│ soft_deletes │ │ │
└────────────────┴─────────────┴────────────────────────────┘
INDEX: (tenant_id, user_id), status, (start_date, end_date)
2.2 leave_balances 테이블
┌──────────────────────────────────────────────────────────┐
│ leave_balances │
├────────────────┬─────────────┬────────────────────────────┤
│ id │ bigint PK │ │
│ tenant_id │ bigint FK │ │
│ user_id │ bigint FK │ │
│ year │ int │ 연도 │
│ total_days │ decimal(4,1)│ 부여일수 (기본 15) │
│ used_days │ decimal(4,1)│ 사용일수 │
│ remaining_days │ decimal(4,1)│ storedAs(total - used) │
└────────────────┴─────────────┴────────────────────────────┘
UNIQUE: (tenant_id, user_id, year)
2.3 leave_policies 테이블
┌──────────────────────────────────────────────────────────┐
│ leave_policies │
├──────────────────────┬─────────────┬─────────────────────┤
│ tenant_id │ bigint UNIQUE│ 테넌트당 1개 │
│ standard_type │ enum │ fiscal / hire │
│ fiscal_start_month │ tinyint │ 회계연도 시작월 │
│ fiscal_start_day │ tinyint │ 회계연도 시작일 │
│ default_annual_leave │ int │ 기본 연차 (15) │
│ additional_leave_per_year │ int │ 근속 가산 (+1) │
│ max_annual_leave │ int │ 최대 연차 (25) │
│ carry_over_enabled │ boolean │ 이월 허용 │
│ carry_over_max_days │ int │ 이월 한도 │
│ carry_over_expiry_months │ int │ 이월 소멸 개월 │
└──────────────────────┴─────────────┴─────────────────────┘
2.4 leave_grants 테이블
┌──────────────────────────────────────────────────────────┐
│ leave_grants │
├────────────────┬─────────────┬────────────────────────────┤
│ tenant_id │ bigint FK │ │
│ user_id │ bigint FK │ │
│ grant_type │ enum │ annual, monthly, reward, │
│ │ │ condolence, other │
│ grant_date │ date │ 부여일 │
│ grant_days │ decimal(4,1)│ 부여일수 │
│ reason │ text │ 부여 사유 │
└────────────────┴─────────────┴────────────────────────────┘
INDEX: (tenant_id, user_id), grant_date, grant_type
3. Phase 1: 기본 휴가관리 (핵심)
🔴 필수 — 연차 조회, 휴가 신청/승인, 잔여일수 관리
3.1 MNG 모델 생성
| 모델 | 파일 | 대상 테이블 |
|---|---|---|
Leave |
app/Models/HR/Leave.php |
leaves |
LeavePolicy |
app/Models/HR/LeavePolicy.php |
leave_policies |
LeaveGrant |
app/Models/HR/LeaveGrant.php |
leave_grants |
LeaveBalance |
(기존 수정) | leave_balances |
3.2 LeaveService 생성
파일: app/Services/HR/LeaveService.php
| 메서드 | 설명 |
|---|---|
getLeaves(array $filters, int $perPage) |
휴가 목록 조회 (필터: 사원, 유형, 상태, 기간) |
storeLeave(array $data) |
휴가 신청 등록 (잔여일수 검증 포함) |
approve(int $id) |
승인 처리 → leave_balances 차감 → attendances 자동 기록 |
reject(int $id, ?string $reason) |
반려 처리 |
cancel(int $id) |
취소 처리 → leave_balances 복원 → attendances 삭제 |
getBalance(int $userId, ?int $year) |
사원별 연차 잔여일수 조회 |
getBalanceSummary(?int $year) |
전체 사원 잔여일수 요약 |
calculateDays(string $type, string $startDate, string $endDate) |
신청 일수 자동 계산 (주말 제외, 반차=0.5) |
3.3 LeaveController (API) 생성
파일: app/Http/Controllers/Api/Admin/HR/LeaveController.php
| Method | Path | 설명 |
|---|---|---|
| GET | /admin/hr/leaves |
휴가 목록 (HTMX/JSON) |
| POST | /admin/hr/leaves |
휴가 신청 등록 |
| POST | /admin/hr/leaves/{id}/approve |
승인 |
| POST | /admin/hr/leaves/{id}/reject |
반려 |
| POST | /admin/hr/leaves/{id}/cancel |
취소 |
| GET | /admin/hr/leaves/balance |
전체 사원 잔여일수 요약 |
| GET | /admin/hr/leaves/balance/{userId} |
개별 사원 잔여일수 |
| GET | /admin/hr/leaves/export |
엑셀(CSV) 내보내기 |
3.4 MNG 뷰 컨트롤러
파일: app/Http/Controllers/HR/LeaveController.php
GET /hr/leaves → index 페이지 (휴가관리 메인)
3.5 뷰 구성
파일: resources/views/hr/leaves/index.blade.php
┌───────────────────────────────────────────────────────┐
│ 휴가관리 │
├───────────┬───────────┬─────────────┬─────────────────┤
│ 휴가신청 │ 잔여연차 │ 사용현황 │ (Phase 2) 설정 │
│ (탭 1) │ (탭 2) │ (탭 3) │ (탭 4) │
└───────────┴───────────┴─────────────┴─────────────────┘
탭 1: 휴가신청 목록
┌─────────────────────────────────────────────────┐
│ [+ 휴가 신청] [엑셀 내보내기] │
│ │
│ 필터: [사원 ▼] [유형 ▼] [상태 ▼] [기간 ~] │
│ │
│ ┌──────┬──────┬──────┬──────┬─────┬──────┬─────┐ │
│ │ 사원 │ 유형 │ 기간 │ 일수 │사유 │ 상태 │ 처리│ │
│ ├──────┼──────┼──────┼──────┼─────┼──────┼─────┤ │
│ │홍길동│ 연차 │2/24~ │ 1.0 │개인 │ 대기 │승인 │ │
│ │ │ │ 2/24 │ │사유 │ │반려 │ │
│ │김영희│ 반차 │2/25 │ 0.5 │병원 │ 승인 │취소 │ │
│ │ │(오전)│ │ │ │ │ │ │
│ └──────┴──────┴──────┴──────┴─────┴──────┴─────┘ │
│ │
│ [페이지네이션] │
└─────────────────────────────────────────────────┘
탭 2: 잔여연차 현황
┌─────────────────────────────────────────────────┐
│ 연도: [2026 ▼] │
│ │
│ ┌──────┬──────┬──────┬──────┬──────┬──────────┐ │
│ │ 사원 │ 부서 │ 입사일│ 부여 │ 사용 │ 잔여 │ │
│ ├──────┼──────┼──────┼──────┼──────┼──────────┤ │
│ │홍길동│ 개발 │21.03 │ 20.0 │ 5.0 │ 15.0 │ │
│ │김영희│ 영업 │23.08 │ 15.0 │ 3.5 │ 11.5 │ │
│ │이민수│ 총무 │25.06 │ 11.0 │ 2.0 │ 9.0 │ │
│ └──────┴──────┴──────┴──────┴──────┴──────────┘ │
└─────────────────────────────────────────────────┘
탭 3: 사용현황 통계
┌─────────────────────────────────────────────────┐
│ 기간: [2026 ▼] [전체/부서별 ▼] │
│ │
│ 유형별 집계: 연차 45건 | 반차 12건 | 병가 3건 │
│ │
│ 월별 사용 추이 차트 (선택적) │
│ │
│ ┌──────┬──────┬──────┬──────┬──────┬──────────┐ │
│ │ 사원 │ 연차 │ 반차 │ 병가 │ 경조 │ 합계 │ │
│ ├──────┼──────┼──────┼──────┼──────┼──────────┤ │
│ │홍길동│ 3.0 │ 1.0 │ 1.0 │ 0.0 │ 5.0 │ │
│ │김영희│ 2.0 │ 1.5 │ 0.0 │ 0.0 │ 3.5 │ │
│ └──────┴──────┴──────┴──────┴──────┴──────────┘ │
└─────────────────────────────────────────────────┘
3.6 휴가 신청 모달
┌──────────────────────────────────────────┐
│ 휴가 신청 │
├──────────────────────────────────────────┤
│ 사원: [홍길동 ▼] 잔여: 15.0일 │
│ 유형: [연차 ▼] │
│ 기간: [2026-02-27] ~ [2026-02-28] │
│ 일수: 2.0일 (자동 계산, 주말 제외) │
│ 사유: [ ] │
│ │
│ [취소] [신청] │
└──────────────────────────────────────────┘
3.7 근태현황 연동 로직
휴가 승인 시:
┌──────────┐ ┌──────────────┐ ┌──────────────┐
│ Leave │──→ │ LeaveBalance │──→ │ Attendance │
│ approved │ │ used_days +N │ │ status= │
│ │ │ │ │ vacation │
└──────────┘ └──────────────┘ └──────────────┘
휴가 취소 시:
┌──────────┐ ┌──────────────┐ ┌──────────────┐
│ Leave │──→ │ LeaveBalance │──→ │ Attendance │
│ cancelled │ │ used_days -N │ │ 해당 날짜 │
│ │ │ │ │ 레코드 삭제 │
└──────────┘ └──────────────┘ └──────────────┘
3.8 근태현황 정리 작업
Phase 1 구현 후 근태현황에서 다음을 정리:
AttendanceRequest의vacation유형 → 휴가관리로 이관 (출장/재택/외근만 유지)AttendanceService.deductLeaveBalance()제거 →LeaveService로 일원화AttendanceController.leaveBalance()제거 →LeaveController로 이관
4. Phase 2: 연차 정책 및 자동 계산
🟡 중요 — 근로기준법 기반 연차 자동 발생, 정책 설정
4.1 연차 정책 설정 UI
탭 4: 휴가 설정 (Phase 2에서 활성화)
┌──────────────────────────────────────────┐
│ 연차 기준 │
│ ○ 입사일 기준 ● 회계연도 기준 │
│ 회계연도 시작: [1]월 [1]일 │
│ │
│ 연차 일수 │
│ 기본 연차: [15]일 │
│ 2년 초과 시 가산: [1]일/2년 │
│ 최대 연차: [25]일 │
│ │
│ 이월 설정 │
│ □ 잔여 연차 이월 허용 │
│ 이월 한도: [5]일 │
│ 이월 소멸: [3]개월 후 │
│ │
│ [저장] │
└──────────────────────────────────────────┘
4.2 LeavePolicyService
파일: app/Services/HR/LeavePolicyService.php
| 메서드 | 설명 |
|---|---|
getPolicy() |
현재 테넌트 연차 정책 조회 |
updatePolicy(array $data) |
정책 저장/수정 |
calculateAnnualLeave(int $userId) |
사원별 연차 자동 계산 (입사일 + 근속년수 기반) |
generateAnnualLeaves() |
전체 사원 연차 일괄 발생 (연초/입사일 기준) |
processCarryOver() |
이월 처리 (연말) |
4.3 연차 발생 규칙 (근로기준법)
// 입사일 기준 연차 계산 로직
function calculateAnnualDays(Carbon $hireDate): float
{
$years = $hireDate->diffInYears(now());
if ($years < 1) {
// 1년 미만: 매월 개근 시 1일 (최대 11일)
$months = $hireDate->diffInMonths(now());
return min($months, 11);
}
// 1년 이상: 15일 + (근속년수-1)/2 가산 (최대 25일)
$base = 15;
$additional = max(0, floor(($years - 1) / 2));
return min($base + $additional, 25);
}
4.4 연차 부여 이력 관리
leave_grants 테이블을 활용하여 부여 이력 추적:
| grant_type | 설명 | 예시 |
|---|---|---|
annual |
연차 자동 발생 | 2026년 연차 15일 부여 |
monthly |
1년 미만 월차 | 2026-03 월차 1일 부여 |
reward |
포상 휴가 | 우수사원 포상 2일 |
condolence |
경조사 | 결혼 경조 5일 |
other |
기타 | 회사 지정 휴가 |
5. Phase 3: 고급 기능
🟢 권장 — 연차 촉진, 알림, 리포트
5.1 연차 촉진제도 (근로기준법 제61조)
| 시기 | 내용 | 자동화 |
|---|---|---|
| 만료 6개월 전 | 1차 촉진 통보 (미사용 일수 안내) | 카카오 알림톡 발송 |
| 근로자 미응답 시 | 사용 시기 지정 촉구 | 리마인더 알림 |
| 만료 2개월 전 | 2차 촉진 통보 (회사 지정) | 카카오 알림톡 + 이력 보관 |
5.2 알림 기능
- 휴가 승인/반려 시 신청자에게 알림톡
- 잔여 연차 N일 이하 시 사용 권고 알림
- 연차 소멸 D-30, D-7 자동 알림
5.3 리포트
- 부서별/사원별 연차 사용율 대시보드
- 연차 대장 엑셀 출력 (노무감사 대비)
- 월별 사용 추이 통계
6. 구현 순서
Phase 1 (기본 — 약 1~2일)
| Step | 작업 | 파일 |
|---|---|---|
| 1 | MNG 모델 생성 (Leave, LeavePolicy, LeaveGrant) | app/Models/HR/ |
| 2 | LeaveService 생성 | app/Services/HR/LeaveService.php |
| 3 | LeaveController (API) 생성 | app/Http/Controllers/Api/Admin/HR/ |
| 4 | API 라우트 등록 | routes/api.php |
| 5 | 뷰 컨트롤러 생성 | app/Http/Controllers/HR/LeaveController.php |
| 6 | 웹 라우트 등록 | routes/web.php |
| 7 | index.blade.php 작성 (3개 탭) | resources/views/hr/leaves/ |
| 8 | 파셜 뷰 작성 (목록, 잔여, 통계) | resources/views/hr/leaves/partials/ |
| 9 | 근태현황 vacation 연동 정리 | AttendanceService 수정 |
| 10 | 메뉴 등록 안내 | tinker 명령 제공 |
Phase 2 (정책 — 약 1일)
| Step | 작업 |
|---|---|
| 1 | LeavePolicyService 생성 |
| 2 | 연차 자동 계산 로직 구현 |
| 3 | 설정 UI (탭 4) 추가 |
| 4 | 연차 일괄 발생 Artisan 명령 |
| 5 | 이월 처리 로직 |
Phase 3 (고급 — 추후)
| Step | 작업 |
|---|---|
| 1 | 연차 촉진 스케줄러 |
| 2 | 카카오 알림톡 연동 |
| 3 | 연차 대장 리포트 |
| 4 | 대시보드 위젯 |
7. 핵심 설계 결정
| 항목 | 결정 | 이유 |
|---|---|---|
| 신규 테이블 | 불필요 | API에 4개 테이블 이미 존재 |
| 휴가 신청 테이블 | leaves 사용 |
attendance_requests에서 vacation 분리 |
| 반차 처리 | leave_type=half_am/half_pm, days=0.5 |
기존 enum 활용 |
| 연차 차감 시점 | 승인 시 즉시 차감 | 잔여일수 실시간 반영 |
| 근태 연동 | 승인 시 Attendance 자동 생성 | 기존 패턴 유지 |
| 취소 시 복원 | used_days 복원 + Attendance 삭제 | 데이터 일관성 |
관련 문서
plans/attendance-management-plan.md— 근태현황 개발 계획rules/attendance-api.md— 근태 API 규칙
최종 업데이트: 2026-02-26